📄 test.cpp
字号:
// test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "test.h"
#include "markup.h"
#pragma comment(lib, "ws2_32.lib")
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma comment(lib, "ws2_32.lib")
#define WIN32_LEAN_AND_MEAN
#define MAX_PACKET_SIZE 65536
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
typedef struct content_rule//数据包payload中关键字节串检测规则
{
CString payload;//payload中含有的关键字节串
int depth;//检测深度,即检测到payload的第n位为止
int offset;//检测位移,即从payload中第n位检测
bool nocase;//是否区分大小写
int distance;//
bool flag;//规则生效标记
}ContentRule;
typedef struct rule//规则结构,用于保存从xml中读入的检测规则,以检测特征数据包
{
int proto;//协议
double sourceIP;//源ip
long srcmask;//源掩码
double dstIP;//目的ip
long dstmask;//目的掩码
int sourcePort;//源端口
int dstPort;//目的端口
bool direction;//发送方向方向
int ttl;//检测数据包的ttl位
int tos;//检测数据包的tos位
int identity;//检测数据包的id位
int dsize;//检测数据包payload长度
int flags;//检测数据包flags位
long seq;//检测数据包seq号
long ack;//检测检测数据包ack号
int window;//检测数据包窗口大小
CString msg;//报警返回信息
ContentRule content[100];//payload规则
bool activity;//该规则是否生效
}Rule;
Rule rules[1000];//初始化1000条规则
typedef struct ip_header//ip包结构
{
unsigned char h_verlen;
unsigned char tos;
unsigned short total_len;
unsigned short ident;
unsigned short flag_and_flags;
unsigned char ttl;
unsigned char proto;
unsigned short chksum;
unsigned int sourceIp;
unsigned int dstIp;
}IPHeader;
typedef struct tcp_header//tcp包结构
{
unsigned short sourcePort;
unsigned short dstPort;
unsigned int seqNum;
unsigned int ackNum;
unsigned char dataOff;
unsigned char flags;
unsigned short window;
unsigned short chksum;
unsigned short urgPtr;
}TCPHeader;
typedef struct udp_header//udp包结构
{
unsigned short sourcePort;
unsigned short dstPort;
unsigned short pocketSize;
unsigned short chksum;
}UDPHeader;
void checkdatagram(char * temp,int packetSize);//数据包检测函数
bool checkpayload(ContentRule * content,char * payload,int payloadLen);//数据包payload检测函数
char * memmem(char * source,char * dest,unsigned int sourceLen,unsigned int destLen);//在字节串中找子字节串函数
char * memlowcase(char * str,int len);//把字节串小写化
char * strtohex(CString str,char * result,int * len);//字符串转换为十六进制
char * ipconv(char * strip,unsigned int ip);//ip格式转换
void loadrule(rule * rules);//从xml文件中读入检测规则
unsigned long GetLocalIP();//得到本机ip
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])//main
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
int nRetCode = 0;
int nRecvBytes = 0;
WSADATA wsaData;
char buf[2048];
DWORD dwBytes;
// DWORD dwFlags;
cout<<"load rules......"<<endl;
loadrule(rules);//读规则
cout<<"load success......"<<endl;
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0 )
{
//WSAStartup Error!
printf("WSAStartup Error!%d\n", WSAGetLastError());
nRetCode = -1;
return nRetCode;
}
char* pBuffer = NULL;
SOCKET nSock = INVALID_SOCKET;
//SOCKADDR_IN addr_in;
//DWORD dwBufferLen[10];
DWORD dwBufferInLen = 1;
DWORD dwBytesReturned = 0;
SOCKADDR_IN if0;
SOCKET_ADDRESS_LIST *slist=NULL;
//define a raw socket
nSock = WSASocket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == nSock)
{
nRetCode = -1;
goto Exit0;
}
if(SOCKET_ERROR==WSAIoctl(nSock,
SIO_ADDRESS_LIST_QUERY,NULL,
0,buf,2048,&dwBytes,NULL,NULL))
{
printf("seek failed!");
}
slist=(SOCKET_ADDRESS_LIST*)buf;
if(slist->iAddressCount<=0)
{
printf("seek2 failed!");
}
if0.sin_addr.s_addr=GetLocalIP();//绑定到列表中第一个接口(第一步之前声明过:SOCKADDR_IN if0)
if0.sin_family=AF_INET;
if0.sin_port=htons(0); //port0表示系统自定端口?
if(SOCKET_ERROR==::bind(nSock,(SOCKADDR*)&if0,sizeof(if0)))
{
printf("bind failed!");
}
//socket for sniffer
nRetCode = WSAIoctl(nSock, SIO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen),NULL,0, &dwBytesReturned , NULL , NULL );//设定网卡为混杂状态,接受所有的数据包
if (SOCKET_ERROR == nRetCode)
{
printf("WSAIOCTL Error!%d\n", WSAGetLastError());
goto Exit0;
}
//start sniffing
pBuffer = (char*)malloc(MAX_PACKET_SIZE);//接收缓冲区
cout<<"start snnifering......"<<endl;//开始截包
while(1)
{
memset(pBuffer, 0, MAX_PACKET_SIZE);
IPHeader * pIpHeader=NULL;
TCPHeader * pTcpHeader=NULL;
nRecvBytes = recv(nSock, pBuffer, MAX_PACKET_SIZE, 0);//把包内容放到缓冲区
pIpHeader = (IPHeader *)pBuffer;
if (SOCKET_ERROR == nRetCode)
{
printf("RECV Error!%d\n", WSAGetLastError());
goto Exit0;
}
if (nRecvBytes < 46)continue;
char * temp =new char [MAX_PACKET_SIZE];//建立临时缓冲区
memset(temp,0,MAX_PACKET_SIZE);
memcpy(temp,pBuffer,nRecvBytes);//把包考入临时缓冲区
checkdatagram(temp,nRecvBytes);//分析数据包
if(temp !=NULL) free(temp);//释放资源
}
Exit0://出错退出
if (pBuffer != NULL)
free(pBuffer);
if (nSock != INVALID_SOCKET)
closesocket(nSock);
return nRetCode;
}
}
void checkdatagram(char * temp,int packetSize)//数据包分析
{
IPHeader * pipheader=(IPHeader *)temp;
if(pipheader->proto==IPPROTO_TCP)//包协议为tcp
{
TCPHeader * ptcpheader=(TCPHeader *)(temp+sizeof(IPHeader));
char * payload=temp+sizeof(IPHeader)+sizeof(TCPHeader);
int payloadLen=packetSize-(sizeof(IPHeader)+sizeof(TCPHeader));
for(int count=0;count<1000;count++)
{
if(rules[count].activity!=true)break;
if(rules[count].proto>0)
{
if(rules[count].proto!=IPPROTO_TCP)continue;//检查协议是否符合rule定义
}
if(rules[count].sourceIP>0)
{
unsigned int tempip=rules[count].sourceIP;//检查源地址是否符合rule定义
if(rules[count].srcmask!=-1)//是否指定了掩码
{
if(((pipheader->sourceIp)&(rules[count].srcmask))!=(tempip&(rules[count].srcmask)))continue;
}
else if(pipheader->sourceIp!=tempip)continue;
}
if(rules[count].dstIP>0)//检查目的地址是否符合rule定义
{
unsigned int tempip=rules[count].dstIP;
if(rules[count].dstmask!=-1)//是否指定了掩码
{
if(((pipheader->dstIp)&(rules[count].dstmask))!=(tempip&(rules[count].dstmask)))continue;
}
else if(pipheader->dstIp!=tempip)continue;
}
if(rules[count].direction==true)//是否检反方向数据包
{
if(rules[count].sourceIP>0)
{
unsigned int tempip=rules[count].sourceIP;
if(rules[count].srcmask!=-1)
{
if(((pipheader->dstIp)&(rules[count].srcmask))!=(tempip&(rules[count].srcmask))&&((pipheader->sourceIp)&(rules[count].srcmask))!=(tempip&(rules[count].srcmask)))continue;
}
else if(pipheader->dstIp!=tempip&&pipheader->sourceIp!=tempip)continue;
}
if(rules[count].dstIP>0)
{
unsigned int tempip=rules[count].dstIP;
if(rules[count].dstmask!=-1)
{
if(((pipheader->sourceIp)&(rules[count].dstmask))!=(tempip&(rules[count].dstmask))&&((pipheader->dstIp)&(rules[count].dstmask))!=(tempip&(rules[count].dstmask)))continue;
}
else if(pipheader->sourceIp!=tempip&&pipheader->dstIp!=tempip)continue;
}
}
if(rules[count].sourcePort>0)//检查源端口是否符合rule定义
{
if(ntohs(ptcpheader->sourcePort)!=rules[count].sourcePort)continue;
}
if(rules[count].dstPort>0)//检查目的端口是佛符合rule定义
{
if(ntohs(ptcpheader->dstPort)!=rules[count].dstPort)continue;
}
if(rules[count].direction==true)//相反反方向数据包
{
if(rules[count].dstPort>0)
{
if(ntohs(ptcpheader->dstPort)!=rules[count].dstPort&&ntohs(ptcpheader->dstPort)!=rules[count].sourcePort)continue;
}
if(rules[count].sourcePort>0)
{
if(ntohs(ptcpheader->sourcePort)!=rules[count].sourcePort&&ntohs(ptcpheader->sourcePort)!=rules[count].dstPort)continue;
}
}
if(rules[count].ttl>0)//检查ttl是否符合rule定义
{
if(pipheader->ttl!=rules[count].ttl)continue;
}
if(rules[count].tos>0)//检查tos是否符合rule定义
{
if(pipheader->tos!=rules[count].tos)continue;
}
if(rules[count].identity>0)//检查id是否符合rule定义
{
if(pipheader->ident!=rules[count].identity)continue;
}
if(rules[count].dsize>0)//检查payload长度是否符合rule定义
{
int payloadLen=packetSize-sizeof(IPHeader)-sizeof(TCPHeader);
if(payloadLen!=rules[count].dsize)continue;
}
if(rules[count].flags>0)//检查flags位是否符合rule定义
{
if(ptcpheader->flags!=rules[count].flags)continue;
}
if(rules[count].seq>0)//检查seq号是否符合rule定义
{
long tempSeq=ntohl(ptcpheader->seqNum);
if(tempSeq!=rules[count].seq)continue;
}
if(rules[count].ack>0)//检查ack号是否符合rule定义
{
if(rules[count].ack!=ptcpheader->ackNum)continue;
}
if(rules[count].window>0)//检查窗口大小是否符合rule定义
{
if(ntohs(ptcpheader->window)!=rules[count].window)continue;
}
if(checkpayload(rules[count].content,payload,payloadLen)!=true)continue;//进入payload检查函数
//匹配规则后,报警
char srcip[20];
char dstip[20];
ipconv(srcip,pipheader->sourceIp);
ipconv(dstip,pipheader->dstIp);
CTime currenttime = CTime::GetCurrentTime();
CString time=currenttime.Format("(%#Y/%#m/%#d/%#H:%#M:%#S)");
cout<<time.GetBuffer(time.GetLength())<<"alert:"<<rules[count].msg.GetBuffer(rules[count].msg.GetLength())<<" "<<srcip<<" to "<<dstip<<endl;
CFile alertFile;
alertFile.Open("alert.txt",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite);
alertFile.Seek(0,CFile::end);
alertFile.Write(time.GetBuffer(time.GetLength()),time.GetLength());
alertFile.Write("alert: ",8);
alertFile.Write(rules[count].msg.GetBuffer(rules[count].msg.GetLength()),rules[count].msg.GetLength());
alertFile.Write(" ",3);
alertFile.Write(srcip,strlen(srcip));
alertFile.Write(" to ",4);
alertFile.Write(dstip,strlen(dstip));
alertFile.Write("\r\n",2);//txt记录警报
alertFile.Flush();
alertFile.Close();
//alert
}
}
else if(pipheader->proto==IPPROTO_UDP)//包协议为udp
{
UDPHeader * pudpheader=(UDPHeader *)(temp+sizeof(IPHeader));
char * payload=temp+sizeof(IPHeader)+sizeof(UDPHeader);
int payloadLen=packetSize-(sizeof(IPHeader)+sizeof(UDPHeader));
for(int count=0;count<1000;count++)//检查数据包
{
if(rules[count].activity!=true)break;
if(rules[count].proto>0)
{
if(rules[count].proto!=IPPROTO_UDP)continue;//检查包协议
}
if(rules[count].sourceIP>0)//检查源地址是否符合rule定义
{
unsigned int tempip=rules[count].sourceIP;
if(rules[count].srcmask!=-1)//是否指定了掩码
{
if(((pipheader->sourceIp)&(rules[count].srcmask))!=(tempip&(rules[count].srcmask)))continue;
}
else if(pipheader->sourceIp!=tempip)continue;
}
if(rules[count].dstIP>0)//检查目的地址是否符合rule定义
{
unsigned int tempip=rules[count].dstIP;
if(rules[count].dstmask!=-1)
{
if(((pipheader->dstIp)&(rules[count].dstmask))!=(tempip&(rules[count].dstmask)))continue;
}
else if(pipheader->dstIp!=tempip)continue;
}
if(rules[count].direction==true)//是否指定检查反方向数据包
{
if(rules[count].sourceIP>0)
{
unsigned int tempip=rules[count].sourceIP;
if(rules[count].srcmask!=-1)
{
if(((pipheader->dstIp)&(rules[count].srcmask))!=(tempip&(rules[count].srcmask))&&((pipheader->sourceIp)&(rules[count].srcmask))!=(tempip&(rules[count].srcmask)))continue;
}
else if(pipheader->dstIp!=tempip&&pipheader->sourceIp!=tempip)continue;
}
if(rules[count].dstIP>0)
{
unsigned int tempip=rules[count].dstIP;
if(rules[count].dstmask!=-1)
{
if(((pipheader->sourceIp)&(rules[count].dstmask))!=(tempip&(rules[count].dstmask))&&((pipheader->dstIp)&(rules[count].dstmask))!=(tempip&(rules[count].dstmask)))continue;
}
else if(pipheader->sourceIp!=tempip&&pipheader->dstIp!=tempip)continue;
}
}
if(rules[count].sourcePort>0)//检查源端口是否符合规则定义
{
if(ntohs(pudpheader->sourcePort)!=rules[count].sourcePort)continue;
}
if(rules[count].dstPort>0)//检查目的端口是否符合规则定义
{
if(ntohs(pudpheader->dstPort)!=rules[count].dstPort)continue;
}
if(rules[count].direction==true)//是否检查反方向数据包
{
if(rules[count].dstPort>0)
{
if(ntohs(pudpheader->dstPort)!=rules[count].dstPort&&ntohs(pudpheader->dstPort)!=rules[count].sourcePort)continue;
}
if(rules[count].sourcePort>0)
{
if(ntohs(pudpheader->sourcePort)!=rules[count].sourcePort&&ntohs(pudpheader->sourcePort)!=rules[count].dstPort)continue;
}
}
if(rules[count].dsize>0)//检查payload长度是否符合rule定义
{
if(payloadLen!=rules[count].dsize)continue;
}
if(checkpayload(rules[count].content,payload,payloadLen)!=true)continue;//按照payload规则检查数据包的payload
//匹配规则,alert
char srcip[20];
char dstip[20];
ipconv(srcip,pipheader->sourceIp);
ipconv(dstip,pipheader->dstIp);
CTime currenttime = CTime::GetCurrentTime();
CString time=currenttime.Format("(%#Y/%#m/%#d/%#H:%#M:%#S)");
cout<<time.GetBuffer(time.GetLength())<<"alert:"<<rules[count].msg.GetBuffer(rules[count].msg.GetLength())<<" "<<srcip<<" to "<<dstip<<endl;
CFile alertFile;
alertFile.Open("alert.txt",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite);
alertFile.Seek(0,CFile::end);
alertFile.Write(time.GetBuffer(time.GetLength()),time.GetLength());
alertFile.Write("alert: ",8);
alertFile.Write(rules[count].msg.GetBuffer(rules[count].msg.GetLength()),rules[count].msg.GetLength());
alertFile.Write(srcip,strlen(srcip));
alertFile.Write(" ",3);
alertFile.Write(" to ",4);
alertFile.Write(dstip,strlen(dstip));
alertFile.Write("\r\n",2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -