|
下面给出程序源代码,欢迎批评指正
bool UserSended = false; //用于标记是否发送过密码 bool FirstPacket = true; //用于标记第一个包是否已经发送 bool online = false; // 是否在线的标记 HWND hOwner = 0; // 界面的窗体句柄 pcap_t *fp = NULL; // 网卡设备
初始化各种待发送的包,略(包结构参考有关资料) unsigned char ConnectBuf[60] 请求连接包 unsigned char DisconnectBuf[60] 请求断开包 unsigned char UnknowBufA[67] 我不知道的包 unsigned char PasswordBuf[60] 包含密码、用户名的包 unsigned char KeepBuf[60] 保持连接的包,包含IP、用户名 unsigned char SendUsernameBuf[60] 发送IP、用户名的包
//打开网卡,用pcap_findalldevs()获得*device bool OpenDevice(char* device) { char errbuf[PCAP_ERRBUF_SIZE]; //抓取的最大包的字节为60, 20ms抓取一次 if ((fp = pcap_open_live(device, 60, 1, 20, errbuf)) == NULL) return false; return true; }
void CloseDevice()// 关闭网卡 { if (fp != NULL) { pcap_close(fp); } }
void DeviceLoop()// 启动包处理循环
{ if (fp == NULL) return; pcap_loop(fp, 0, packet_handler, NULL); }
// 分析包并产生相应动作 void packet_handler(unsigned char *param, const struct pcap_pkthdr *header, const unsigned char *pkt_data) { // 判断包的类型的标志 static unsigned char Type[4] = {0x88, 0x8e, 0x01, 0x00}; //协议类型 static unsigned char SessionFlagA[3] = {0x00, 0x05, 0x01}; //保持连接包 static unsigned char SessionFlagB[3] = {0x00, 0x05, 0x01}; static unsigned char Unknow[3] = {0x00, 0x05, 0x02}; static unsigned char RequestPwdA[3] = {0x00, 0x16, 0x01}; //请求密码包 static unsigned char RequestPwdB[3] = {0x00, 0x16, 0x04}; static unsigned char SuccessA[3] = {0x00, 0x04, 0x03}; //成功认证包 static unsigned char SuccessB[3] = {0x00, 0x04, 0x00}; static unsigned char ByeA[3] = {0x00, 0x06, 0x04}; //成功断线包 static unsigned char ByeB[3] = {0x00, 0x07, 0x08};
// 找包的大小为60个字节, 协议为EAPoL的包 if (header->len == 60 && !memcmp(pkt_data + 0x0c, Type, 4)) { //获得以后我们所要回复的MAC地址,并放入包 if (FirstPacket) { FirstPacket = false; ChangeDestMac(pkt_data + 0x06); } // 判断是否为对话维持包或要求发送用户名的包(这两种包的特征是一样的) if (!memcmp(pkt_data + 0x10, SessionFlagA, 3) && !memcmp(pkt_data + 0x14, SessionFlagB, 3)) { if (online)//已经上线,发送对话维持包 { SetSessionID(pkt_data + 0x13); //设置标识位 pcap_sendpacket(fp, KeepBuf, 60); if (online == false) { online = true; ShowOnline(); //上线处理 } } else // 否则就发送用户名 { SetUsernameID(pkt_data + 0x13); //设置标识位 pcap_sendpacket(fp, SendUsernameBuf, 60); //包含IP、用户名 UserSended = true; } return; }
// 判断是否为未知类型的包 if (!memcmp(pkt_data + 0x10, SessionFlagA, 3) && !memcmp(pkt_data + 0x14, Unknow, 3)) { pcap_sendpacket(fp, UnknowBufA, 67); //固定的包 return; }
// 判断是否为要求发送密码的包 if (!memcmp(pkt_data + 0x10, RequestPwdA, 3) && !memcmp(pkt_data + 0x14, RequestPwdB, 3)) { SetPasswordID(pkt_data + 0x13); //设置标识位 SetMd5Buf(pkt_data + 0x13, pkt_data + 0x18);//MD5加密 pcap_sendpacket(fp, PasswordBuf, 60); //发送包含密码和用户名的包 return; } // 判断是否为认证成功的包 code=3 if (!memcmp(pkt_data + 0x10, SuccessA, 3) && !memcmp(pkt_data + 0x14, SuccessB, 3)) { if (online == false) { online = true; ShowOnline(); //上线处理 } return; }
// failure包 code=4 if (!memcmp(pkt_data + 0x10, ByeA, 3)) { // 判断是否为断线成功的包 if(!memcmp(pkt_data + 0x14, ByeB, 3)) { if (online == true) { online = false; ShowOffline(); //离线处理
UserSended = false; // 重置UserSended } return; } else// 其他离线包 { ShowOffline(); {//提示出错原因 strMsg.Format("%s", (pkt_data+0x18)); MessageBox(hOwner, strMsg, "连接失败",MB_ICONWARNING); } return; } } } }
十分感谢cshacker的帮助
|