通过Row Socket实现IP欺骗(C语言)

最近由于项目需要,研究了一下ICMP和ROW SOCKET协议,顺便在这里记下,一是方便给自已
留个笔记,也方便和朋友们一起学习和进步。

昨天在修改公司一个wince的程序时,偶然发现其中一个ping主机的模块代码有内存泄露问题,但我也有几年没有去看过ICMP的东东,因此,把以前项目用过的ICMP和row socket协议代码拿出来再翻翻,把BUG给修正了,顺道也把row socet实现IP欺骗的代码也贴出来。(PING的代码就不贴了,网上很多例子,简单的就几个ICMP的api就可实现,也有用socket来实现的,代码量多一点而已。)

我对协议的理解是在每层加上一个包头而已,IP层位于网络层,socket提供的函数只能修改网络层的东东,因此,平常我们用的socket函数一般只能使用在网络层以后面的像HTTP层上,Http这些应该属于应用层,只是在网络层上再加一个Http包头而已。

下面的代码是在三年前一个用于做自动网络拓朴发现中用到的IP欺骗的一个模块,说起Auto拓朴发现,就是通过一个网管程序,采用SNMP+ICMP+socket+TD等各设备厂家提供的自有协议的前提下,能够自动把企业内的网络图画出来,刚好那时候公司安排我做的这个模块,因此也研究过阿尔卡特/北电/华为/思科等的路由器和交换机,对他们的公有、私有mib库都有一些了解,二层和三层的拓朴图还是画得比较完善的,只是在交换机到普通的PC服务器之间的线画得不全,后来才通过采用IP欺骗才得到进一点提高。

简单的讲一下IP欺骗,目的是向A设备发送ICMP包,在包里面把本应该是填自已的IP地址改为B设备的IP地址,让A设备误以为是B设备向他发的包,因此,A就会把回应的包发到B设备去。而这样,原A和B设备之间也许没有通信,通过IP欺骗主动使他们交流一下,这样就方便我在A设备的mib库中找到关于更多B的信息。

说不多说了,下面是代码,是用C++写的,但因为主项目是用python写的,因为下面的代码中,会有一些关于生成python可以调用的dll的东东,如果你编译时报错可以直接去掉即可。因为你不需要生成python能调的dll,呵呵。

//#define WIN32_LEAN_AND_MEAN

#include "include/Python.h"
#include <winsock2.h>
//#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>

//
// Set up some default values
//

#define DEFAULT_COUNT      4
#define DEFAULT_MESSAGE    "This is a test"
#define ICMP_FLOOD 0
#define IP_HDRINCL 2
#define IP_TTL 255

typedef struct ip_hdr
{
 //BYTE h_len:4;           // Length of the header in dwords
 //BYTE version:4;         // Version of IP
 
 unsigned char  ip_verlen;        // IP version & length
 unsigned char  ip_tos;           // IP type of service
 unsigned short ip_totallength;   // Total length
 unsigned short ip_id;            // Unique identifier
 unsigned short ip_offset;        // Fragment offset field
 unsigned char  ip_ttl;           // Time to live
 unsigned char  ip_protocol;      // Protocol(TCP, UDP, etc.)
 unsigned short ip_checksum;      // IP checksum
 unsigned int   ip_srcaddr;       // Source address
 unsigned int   ip_destaddr;      // Destination address
} ;

typedef struct icmp_hdr {
 BYTE type;          // ICMP packet type
 BYTE code;          // Type sub code
 USHORT checksum;
 USHORT id;
 USHORT seq;
 //ULONG timestamp;    // not part of ICMP, but we need it
};

struct pkt
{
   struct ip_hdr   ip;
   struct icmp_hdr icmp;   
}pack;

 

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);
}

static PyObject* icmpsend(PyObject *self, PyObject *args); 

static PyObject* icmpsend(PyObject* self, PyObject* args)  
{  
   char *src_ip,*dest_ip;  
   
   WSADATA            wsd;
   SOCKET             s;
   int                bOpt;
   struct sockaddr_in remote;       // IP addressing structures
   struct ip_hdr      ipHdr;
   
   int                ret;
   unsigned short     iIPVersion,
                      iIPSize;
   
   IN_ADDR            addr;
   unsigned short     chk; 
   int                ttl;
   DWORD                i;


   if (! PyArg_ParseTuple(args, "s|s", &src_ip, &dest_ip)) 
   return Py_BuildValue("i", -1);
   
   if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
   {
       ret =GetLastError();
       return Py_BuildValue("i", ret);
   }
   s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0);
   if (s == INVALID_SOCKET)
   {
       ret =WSAGetLastError();
       return Py_BuildValue("i", ret);
   }


   bOpt = 1;
   ttl = 30;
   
   ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt));
      
   //ret = setsockopt(s, IPPROTO_IP, IP_TTL, (const char*)&ttl,sizeof(ttl));
      
   if (ret == SOCKET_ERROR)
   {
       ret = WSAGetLastError();
       return Py_BuildValue("i", ret); 
   }
   // Initalize the IP header
   //
   
   iIPVersion = 4;
   iIPSize = sizeof(ipHdr) / sizeof(unsigned long);
   //
   // IP version goes in the high-order 4 bits of ip_verlen. The
   // IP header length (in 32-bit words) goes in the lower 4 bits.
   //
   
   //pack.ip.ihl=5;
   pack.ip.ip_verlen=(iIPVersion << 4) | iIPSize;
   pack.ip.ip_tos=0;
   pack.ip.ip_totallength = htons(28);
   pack.ip.ip_id=0;
   pack.ip.ip_offset=0;
   pack.ip.ip_ttl=255;
   pack.ip.ip_protocol=1;
   pack.ip.ip_checksum=0;
   //pack.ip.ip_checksum = chk;
   pack.ip.ip_srcaddr = inet_addr(src_ip);
   pack.ip.ip_destaddr = inet_addr(dest_ip); 
   
   pack.icmp.type = 8;
   pack.icmp.code = 0;
   pack.icmp.checksum = 0;
   chk=checksum((unsigned short *)&pack.icmp, 8);   
   pack.icmp.checksum=chk;
   chk=checksum((unsigned short *)&pack, 28);
   pack.ip.ip_checksum=chk;    
   
   
   remote.sin_family = AF_INET;
   
   remote.sin_addr.s_addr = pack.ip.ip_destaddr;


   for(i = 0; i < DEFAULT_COUNT; i++)
   {
       ret = sendto(s, (char *)&pack, sizeof(pack), 0, (SOCKADDR *)&remote,sizeof(remote));
       if (ret == SOCKET_ERROR)
       {
           ret = WSAGetLastError();
           break;
       }
   }
   closesocket(s);
   WSACleanup();

   return Py_BuildValue("i", ret);

static PyMethodDef addMethods[] = 
{  
   {"icmpsend",  icmpsend, METH_VARARGS, "Execute a shell command."},  
   {NULL, NULL, 0, NULL} 
}; 

#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC _declspec(dllexport) void
#endif


PyMODINIT_FUNC initipspoof() 

{  
   Py_InitModule("ipspoof", addMethods);  

忘了说一点了,只有用Row Socket才可以使icmp_hdr和IP_hdr修改生效。才能做到IP欺骗。

刚起床,把昨天做的东东记下来,一会找朋友打几局星际,我的周未就这样子过了。写程序这么些年来我一直不会交际,不喜欢出去玩,周未在家就是一个人,习惯了寂寞,习惯了一个人呆在房子里的日子...


你可能感兴趣的:(c,python,socket,struct,header,语言)