首页 体育 教育 财经 社会 娱乐 军事 国内 科技 互联网 房产 国际 女人 汽车 游戏

自己动手制作一个恶意流量检测系统(附源码)

2019-12-17

没有做日志记载由于时刻联系。

咱们假定歹意C2C服务器IP是220.181.38.148,某个木马的歹意流量特征是?? ?? ?? ??

当咱们要屏蔽220.181.38.148IP的时分 在咱们后台输入这个IP地址就能够屏蔽了,当然这儿仅仅展现了屏蔽功用,也能够做成给后台报警

这是没有增加规矩的:

增加了规矩:

数据包同理,这儿的?? 代表匹配一切数据包。因而会把一切的数据包悉数drop 掉

 RtlInitUnicodeString;
 Status = ZwCreateFile;
 if  || !g_hClient)
 DPRINT;
 return Status;
 DPRINT;

然后WFP模板部分不独自发了,没什么好说的,要点说一下咱们要挂钩的几个当地:

FWPM_LAYER_ALE_AUTH_CONNECT_V4、FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 别离对应链接认证阶段阶段,区别是一个是out一个是income

FWPM_LAYER_STREAM_V4 抓取数据流,用于流量信息监测

if )
 DPRINT)
 DPRINT)
 DPRINT;

其间 值得一提的是FWPM_LAYER_ALE_CONNECT_REDIRECT_V4,能够改动衔接的地址,完成移花接木功用.十分合适拿去干坏事.不过不在本次的评论范围内

在SFALEConnectClassify和SFALERecvAcceptClassify回调中,担任屏蔽黑名单IP,这部分略微抄了一下长辈的代码:

//本地连他人的IP的衔接
void SFALEConnectClassify
 FWP_ACTION_TYPE Action =  ? FWP_ACTION_BLOCK : FWP_ACTION_PERMIT);
 PerformBasicAction;
//接纳长途IP的衔接
void SFALERecvAcceptClassify
 FWP_ACTION_TYPE Action =  ? FWP_ACTION_BLOCK : FWP_ACTION_PERMIT);
 PerformBasicAction;

FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 这儿是我之前代码,有个小bug,至于是什么bug大佬应该一眼看出来了:

void SFALERecvDataClassify DISPATCH_LEVEL)
 DPRINT);
 return FALSE;
 FWPS_STREAM_CALLOUT_IO_PACKET* streamPacket = layerData;
 DWORD RemoteIP = inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_ADDRESS].value.uint32;
 DWORD LocalIP = inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS].value.uint32;
 if 
 SIZE_T streamLength = streamPacket- streamData- dataLength;
 BOOLEAN inbound =  == FWPS_STREAM_FLAG_RECEIVE);
 BYTE* stream = ExAllocatePoolWithTag;
 SIZE_T byte_copied = 0;
 if 
 RtlZeroMemory;
 FwpsCopyStreamDataToBuffer;
 NT_ASSERT;
 DPRINT;
 SIZE_T buffsize = streamLength + sizeof;
 inbound =  == FWPS_STREAM_FLAG_RECEIVE);
 Networkreport* report = ExAllocatePoolWithTag;
 if 
 RtlZeroMemory;
 report- type = inbound ? r_stream_income : r_stream_output;
 report- Protocol = inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL].value.uint16;
 report- IPaddr = RemoteIP;
 report- BuffDataLen = streamLength;
 //定位到buffer的sizeof方位
 BYTE* tmp = report + sizeof;
 memcpy;
 ReportToR3;
 ExFreePool;
 ExFreePool;
 classifyOut- actionType = FWP_ACTION_CONTINUE;

成果:

好的能够抓包了就能够开端进行下一步过滤了:

首先是提交过滤的程序,这儿偷闲了:

//增加数据到 到黑名单数据列表
VOID AddBlackListData
 if 
 DPRINT;
 PBLACK_LIST_DATA newLink = ExAllocatePoolWithTag, TAG_NAME_BLACKLISTDATA);
 if 
 ASSERT;
 //RtlZeroMemory);
 memcpy;
 DPRINT;
 InsertTailListnewLink);
 else
 for 
 if 
 gBackListIPTable[i] = blockip;
 DPRINT;
 break;

操控码:

NTSTATUS DriverControlHandler
 PIO_STACK_LOCATION irpSp;// Pointer to current stack location
 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;// Assume success
 ULONG inBufLength; // Input buffer length
 ULONG outBufLength; // Output buffer length
 PUCHAR inBuf, outBuf;
 UNREFERENCED_PARAMETER;
 irpSp = IoGetCurrentIrpStackLocation;
 inBufLength = irpSp- Parameters.DeviceIoControl.InputBufferLength;
 outBufLength = irpSp- Parameters.DeviceIoControl.OutputBufferLength;
 inBuf = Irp- AssociatedIrp.SystemBuffer;
 outBuf = Irp- AssociatedIrp.SystemBuffer;
 DPRINT;
 if 
 ntStatus = STATUS_INVALID_PARAMETER;
 goto End;
 switch 
 case IOCTL_ADD_BLACKLIST_DATA:
 DPRINTExAllocatePoolWithTag, tM2d 
 if 
 RtlZeroMemory);
 memcpy;
 AddBlackListData;
 DPRINT;
 g_StartFilter = TRUE;
 ntStatus = STATUS_SUCCESS;
 ExFreePoolWithTag;
 return ntStatus;

黑名单IP匹配:

//黑名单IP匹配
BOOLEAN QueryBlackIP
 KIRQL Irql = ExAcquireSpinLockExclusive;
 BOOLEAN result = FALSE;
 for 
 if 
 result = TRUE;
 break;
 ExReleaseSpinLockExclusive;
 return result;

之后在SFALEConnectClassify和SFALERecvAcceptClassify的当地进行验证:

BOOLEAN CanIFilterThisRequest;
 if  DISPATCH_LEVEL)
 DPRINT);
 return FALSE;
 if 
 DWORD LocalIp = inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS].value.uint32;
 DWORD RemoteIP = inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_ADDRESS].value.uint32;
 if 
 if )
 DPRINT;
 DWORD LocalIp = inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS].value.uint32;
 DWORD RemoteIP = inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_ADDRESS].value.uint32;
 DPRINT 0xFF,  0xFF,  0xFF, LocalIp 0xFF,
 inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_PORT].value.uint16,
  0xFF,  0xFF,  0xFF, RemoteIP 0xFF,
 inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_PORT].value.uint16,
 ProtocolName);
 ExFreePool;
 return FALSE;

CanIFilterThisRequest 回来TRUE后 在SFALEConnectClassify和SFALERecvAcceptClassify中阻挠链接:

FWP_ACTION_TYPE Action =  ? FWP_ACTION_BLOCK : FWP_ACTION_PERMIT);
PerformBasicAction;

然后是数据包过滤:

//黑名单数据匹配
BOOLEAN QueryBlackListData
 KIRQL Irql = ExAcquireSpinLockExclusive;
 BOOLEAN result = FALSE;
 PLIST_ENTRY head = gBackListDataTable.link;
 PBLACK_LIST_DATA next = gBackListDataTable.link.Blink;
 while next)
 if)
 result = TRUE;
 break;
 ExReleaseSpinLockExclusive;
 return result;
void SFALERecvDataClassify DISPATCH_LEVEL)
 DPRINT);
 return FALSE;
 FWPS_STREAM_CALLOUT_IO_PACKET* streamPacket = layerData;
 DWORD RemoteIP = inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_ADDRESS].value.uint32;
 DWORD LocalIP = inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS].value.uint32;
 if 
 SIZE_T streamLength = streamPacket- streamData- dataLength;
 BOOLEAN inbound =  == FWPS_STREAM_FLAG_RECEIVE);
 BYTE* stream = ExAllocatePoolWithTag;
 SIZE_T byte_copied = 0;
 if 
 RtlZeroMemory;
 FwpsCopyStreamDataToBuffer;
 NT_ASSERT;
 if )
 DPRINT;
 return;
 //抓包与截包,假如你发现这儿蓝屏请自己加锁,可是会极大的影响体系运转功率;
 SIZE_T buffsize = streamLength + sizeof;
 inbound =  == FWPS_STREAM_FLAG_RECEIVE);
 Networkreport* report = ExAllocatePoolWithTag;
 if 
 RtlZeroMemory;
 report- type = inbound ? r_stream_income : r_stream_output;
 report- Protocol = inFixedValues- incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL].value.uint16;
 report- IPaddr = RemoteIP;
 report- BuffDataLen = streamLength;
 //定位到buffer的sizeof方位
 BYTE* tmp = report + sizeof;
 memcpy;
 ReportToR3;
 ExFreePool;
 ExFreePool;
 classifyOut- actionType = FWP_ACTION_CONTINUE;

匹配成功后 classifyOut- actionType = FWP_ACTION_BLOCK; 则丢掉这个数据包

匹配函数FindPattern

BOOL FindPattern
 const char* pat = pattern;
 DWORD firstMatch = 0;
 DWORD End = data + data_len;
 for data; pCur End; pCur++)
 if 
 return firstMatch;
 if pat == '\?' || *pCur == getByte)
 if 
 firstMatch = pCur;
 if 
 return firstMatch;
 if pat == '\?\?' || *pat != '\?')
 pat += 3;
 else
 pat += 2; //one ?
 else
 pat = pattern;
 firstMatch = 0;
 return firstMatch != NULL;

至此.驱动部分编写结束.

这儿有个失误,不应该运用Client作为TCP服务端,应该是Python来做服务端,无所谓了.先能用再说:

#define IOCTL_ADD_BLACKLIST_DATA \
 CTL_CODE
typedef NTSTATUSGetProcAddress, NtOpenFile 
HANDLE deviceHandle_;
bool is_loaded
 if  {
 //deviceHandle_ = CreateFile;
 IO_STATUS_BLOCK io_status;
 NTSTATUS status;
 UNICODE_STRING device_name = UNICODE_STRING{ sizeof - sizeof, sizeof, DEVICE_NAME };
 OBJECT_ATTRIBUTES obj_attr = OBJECT_ATTRIBUTES{ sizeof, nullptr, device_name, 0, nullptr, nullptr };
 status = fpNtOpenFile;
 if ) {
 ULONG i = 10;
 do {
 status = fpNtOpenFile;
 Sleep;
 } while  i--);
 return deviceHandle_ deviceHandle_ != INVALID_HANDLE_VALUE;
int main
 if )
 printf);
 system, wsaData) != 0)
 return false;
 SOCKET sockSrv = socket;
 SOCKADDR_IN addrSrv;
 addrSrv.sin_family = AF_INET;
 addrSrv.sin_port = htons; //1024以上的端口号 
 addrSrv.sin_addr.S_un.S_addr = htonl;
 int retVal = bind addrSrv, sizeof);
 if  {
 return false;
 if  == SOCKET_ERROR) {
 return false;
 SOCKADDR_IN addrClient;
 int len = sizeof;
 static bool first = false;
 ClientSocket = accept addrClient, len);
 if  {
 return false;
 while 
 char recvBuf[255];
 memset);
 if , 0) == 0 || ClientSocket == INVALID_SOCKET)
 first = false;
 closesocket;
 ClientSocket = accept addrClient, len);
 continue;
 Networkstruct* buffer = recvBuf;

热门文章

随机推荐

推荐文章