网络测试工具tomahawk之二 代码修改篇

来源:互联网 发布:java运算类型有哪几种 编辑:程序博客网 时间:2024/05/01 20:18

     在上一篇中提到了Tomahawk只能测试二层设备,这可能是由于该工具本来就是tipping point公司用来测试其IPS的,而该公司的IPS刚好为二层透明模式。

二层的IPS产品很多,尤其是国外的产品,配置方便(实际上几乎不需要配置),但是国内的IPS往往附加在防火墙设备上,其工作在哪一层依赖于防火墙的配置,虽然防火墙可以配置成透明模式,但是一般单位都是把NAT做在防火墙上,所以网关型的IPS也是很常见。Tomahawk的局限在此。

本文将对tomahawk的代码作一个粗略的分析,比较乱,仅仅涉及为了将其修改为可以测试三层设备的部分。

1.  代码文件清单:

Tomahawk1.1包括以下文件

alloc.c 
alloc.h
eventloop.c
eventloop.h 
packetutil.c 
packetutil.h    
//定义了两个重要的结构:trace和handle及其相关操作

test.pcap        //一个用于测试的数据包文件(不是攻击)
tomahawk.c  //主要发包收包程序

 

2.  具体代码

要看懂tomahawk,一定要理解其中两个重要的结构:tracehandle

l         trace

包括多个包文件的内容,是一个链表结构,包括发送次数等信息,也就是一次命令可以定义的一个发送过程。该结构由函数LoadTrace装载,LoadTrace(前段)并未初始化数据报(trace->pkt = NULL;),只是记录了文件名;包文件内容由LoadPacket导入到trace->pkt,LoadPacket函数判断源和目的IP地址,并且修改MAC(在此可加入网关mac功能)

       注:LoadPacket1.1版中作了CanRewrite检查,即只处理TCP/UDP/ICMP数据包

l         handle

createHandle创建,是一个链表结构,完成一次发送过程(一个数据包一次发送为一个handle)。其中主要函数:

       CreatePacketSendGroup 查找包文件中独立的包(不依赖接收到的包就可以发送的那些,放入group)         

       SendPackets 其中修改了源和目的IP地址将包发送出去,此函数还被RecvPacket,RetrySendPackets,ResendPackets调用;

       RecvPacket中会根据收到数据报的handleID判断是否为发出的包。

l         如何判断收到的包

关键判断函数GetHandler,如果返回值不为nullnumRecv++

       GetHandler(const u_char *packetData, int len, int modAddrs, unsigned char startId, unsigned char endId)

       如果modAddrsip的第二位为handleID(192.22.1.122即为handle ID),如果handleID不在startIdendId之间也返回null.

       如果没有modAddrs则返回startIdhandle.

l                有一个activehandle[]数组记录了所有激活的handle

 

3.  代码修改

3.1 参数修改

添加了几个参数

-g GW1's MAC    Interface1 gateway MAC Address @New!@

-G GW2's MAC    Interface2 gateway MAC Address @New!@

-k GW1's IP     Interface1 gateway IP Address @New!@

-K GW2's IP     Interface2 gateway IP Address @New!@

-S StudyMode    Mode for gateway to study ARP @New!@

 

这几个参数分别指定了网关12IPMAC地址,-S参数是为了让网关学习到模拟出的IP地址的MAC地址,一般在测试时先运行一次:

 

tomahawk –S –k a.b.c.d –K e.f.g.h –g x:x:x:x:x:x –G x:x:x:x:x:x –l 251 –f test.pcap

这样受测设备将会学习到所有a.1.*.*~a.251.*.*e.1.*.*~e.251.*.*mac地址,也就是安装了tomahawk的机器的两个网卡的mac地址。

3.2代码修改

修改loadpacket中关于mac地址的内容为:

if (pkt->iface) {
        
if (useGate) 
{
            
//fprintf(stderr, "[info] mac1  ");

            ph->ether_shost[0= if1.eaddr[0];
            ph
->ether_shost[1= if1.eaddr[1
];
            ph
->ether_shost[2= if1.eaddr[2
];
            ph
->ether_shost[3= if1.eaddr[3
];
            ph
->ether_shost[4= if1.eaddr[4
];
            ph
->ether_shost[5= if1.eaddr[5
];
            ph
->ether_dhost[0= mac1[0
];
            ph
->ether_dhost[1= mac1[1
];
            ph
->ether_dhost[2= mac1[2
];
            ph
->ether_dhost[3= mac1[3
];
            ph
->ether_dhost[4= mac1[4
];
            ph
->ether_dhost[5= mac1[5
];
        }
else{
            ph
->ether_shost[0= if1.eaddr[0
];
            ph
->ether_shost[1= if1.eaddr[1
];
            ph
->ether_shost[2= if1.eaddr[2
];
            ph
->ether_shost[3= if1.eaddr[3
];
            ph
->ether_shost[4= if1.eaddr[4
];
            ph
->ether_shost[5= if1.eaddr[5
];
            ph
->ether_dhost[0= if2.eaddr[0
];
            ph
->ether_dhost[1= if2.eaddr[1
];
            ph
->ether_dhost[2= if2.eaddr[2
];
            ph
->ether_dhost[3= if2.eaddr[3
];
            ph
->ether_dhost[4= if2.eaddr[4
];
            ph
->ether_dhost[5= if2.eaddr[5
];            
        }
        
    }
 else {
        
if (useGate)
{    
            
//fprintf(stderr, "[info] mac2  ");

            ph->ether_dhost[0= mac2[0];
            ph
->ether_dhost[1= mac2[1
];
            ph
->ether_dhost[2= mac2[2
];
            ph
->ether_dhost[3= mac2[3
];
            ph
->ether_dhost[4= mac2[4
];
            ph
->ether_dhost[5= mac2[5
];
            ph
->ether_shost[0= if2.eaddr[0
];
            ph
->ether_shost[1= if2.eaddr[1
];
            ph
->ether_shost[2= if2.eaddr[2
];
            ph
->ether_shost[3= if2.eaddr[3
];
            ph
->ether_shost[4= if2.eaddr[4
];
            ph
->ether_shost[5= if2.eaddr[5
];;
        }
else {
            ph
->ether_dhost[0= if1.eaddr[0
];
            ph
->ether_dhost[1= if1.eaddr[1
];
            ph
->ether_dhost[2= if1.eaddr[2
];
            ph
->ether_dhost[3= if1.eaddr[3
];
            ph
->ether_dhost[4= if1.eaddr[4
];
            ph
->ether_dhost[5= if1.eaddr[5
];
            ph
->ether_shost[0= if2.eaddr[0
];
            ph
->ether_shost[1= if2.eaddr[1
];
            ph
->ether_shost[2= if2.eaddr[2
];
            ph
->ether_shost[3= if2.eaddr[3
];
            ph
->ether_shost[4= if2.eaddr[4
];
            ph
->ether_shost[5= if2.eaddr[5
];
        }

}

 

修改ReadPacket函数,使其在-S模式下可以发送arp学习包

    if (ARPStudyMode){
        
if (memcmp(x1,arp,6))
{
        }
else
{
            memcpy (
&arp_r, buffer, 42
);
            
//
ip4p.s_addr    = arp_r.arp_tpa;    
            
//
fprintf(stderr, "[info] find arp %s", inet_ntoa(ip4p)); 
            
//
fprintf(stderr, "[info] find arp %s", arp_r.arp_tpa); 
            
//
fprintf(stderr, "[info] IP %x:%x:%x:%x  ", arp_r.arp_tpa[0],arp_r.arp_tpa[1],arp_r.arp_tpa[2],arp_r.arp_tpa[3]); 
            
//
for (k=0; k<42; k++){            
            
//
    fprintf(stderr, "%x:", arp_r.eh_dst[k]);     
            
//}            

            if ((( arp_r.arp_tha[6]  & 0xFF== firstByte1) && (!strncmp(interface->device, interface1, 4))){
            
for (k=0; k<4; k++)
{
                arp_s1.arp_spa[k]
=
arp_r.arp_tpa[k];
            }

                memset(sendbuf, 
0sizeof(sendbuf));
                memcpy(sendbuf, 
&arp_s1, 42
);
                
//fprintf(stderr, "on interface 1 ");             

            }

            
if ((( arp_r.arp_tha[6]  & 0xFF== firstByte2) && (!strncmp(interface->device, interface2, 4))){
            
for (k=0;k<4;k++)
{
                arp_s2.arp_spa[k]
=
arp_r.arp_tpa[k];
            }

                memset(sendbuf, 
0sizeof(sendbuf));
                memcpy(sendbuf, 
&arp_s2, 42
);
                
//fprintf(stderr, "on interface 2 ");             

            }
                            
            sendto(
interface->fd, sendbuf, 420, (struct sockaddr *)NULL, 0
);
            
//WriteInterface(interface, sendbuf, 42);    

        }

    }



 

 

修改Sendpackets函数,使其在发送数据包时将IP改为同网关IP的第一位相对应

if (t->modAddrs) {
        
if (useGate)
{
            
if (p[pktId].iface == IFACE_I)
{
                iph.saddr 
= GetWireIP(h->
id, p[pktId].wireSrc, p[pktId].saddr, firstByte1);
                iph.daddr 
= GetWireIP(h->
id, p[pktId].wireDst, p[pktId].daddr, firstByte2);
            }
else{
                iph.saddr 
= GetWireIP(h->
id, p[pktId].wireSrc, p[pktId].saddr, firstByte2);
                iph.daddr 
= GetWireIP(h->
id, p[pktId].wireDst, p[pktId].daddr, firstByte1);
            }

        }
else{
            iph.saddr 
= GetWireIP(h->
id, p[pktId].wireSrc, p[pktId].saddr, firstByte);
            iph.daddr 
= GetWireIP(h->
id, p[pktId].wireDst, p[pktId].daddr, firstByte);
        }

。。。。。。。。。

 

至此,修改完毕。

在下图所示的测试环境中:

运行

tomahawk --00:13:72:77:EA:FC -00:05:5D:29:0F:91 -3.0.0.254 -4.0.0.254 -251 -f test.pcap

 

运行通过!

以前一直在搞java开发,这次使用C,指针刚用起来总是莫名其妙,后来解决了几个BUG后,感觉还是C灵活,指针可以“指哪打哪”!而且速度对于java来说快的不可想象,呵呵。想来有次测试任务需使用loadrunner测试SambaNFS服务器性能指标(1000并发),当时写了两个java程序,用了8台机器才勉强测完,有时被测试的机器安然无恙,我的测试机倒一台台的挂掉,现在看来,如果用C的话一对一测试都应该没有问题。

 

tomahawk的修改完毕了,下面该做些什么呢?在后面的文章里,将会介绍

1.  tomahawk做一个web方式的管理界面

2.  导出blade ids informer的攻击包作为tomahawk的攻击包库(blade ids informer的攻击库很全,但其格式不公开)

 
原创粉丝点击