当前位置: > Linux编程 >

自动动手写发包工具

时间:2014-10-07 16:40来源:linux.it.net.cn 作者:it

自动动手写发包工具

 

为了测试服务器大量在线的性能,需要自己写机器人,模拟大量客户端在线的情况。第一步是创建帐号,第一个办法是直接在服务器后台用脚本创建帐号,另一个办法是模拟客户端发包。前者需要登录到服务器执行,后者可以在其他机器上执行,于是试着用后一种方法实现。

 

第一步,包含协议头文件,再用C++写一个简单的查询帐号封包。

发包代码如下:

 

    struct tagMsg& stMsg = m_stMsg.msg;
    memset((void*)&stMsg, 0, sizeof(stMsg));
    // 消息包头的构造
    stMsg.m_stMsgHead.m_uiBodyLength = htonl(21);
    stMsg.m_stMsgHead.m_uiMsgID = htonl(MSGID_ACCOUNT_CREATEROLE_REQUEST);
    stMsg.m_stMsgHead.m_uiUin = htonl(uiUin);
    stMsg.m_stMsgHead.m_shMsgVersion = htons(1);
    // 这里是验证信息,需要特别处理
    stMsg.m_stMsgHead.m_ucSKeyLength = 0x0f;
    memset(&stMsg.m_stMsgHead.m_szSessionKey[0], 0x0c, MAX_SESSIONKEY_LENGTH);

    // 协议体初始化
    LPCTSTR lpText = (LPCTSTR)"%d";
    CString string;
    string.Format(lpText, uiUin);
    wsprintfA(&stMsg.m_stMsgBody.m_stAccountCreateRoleRequest.m_szNickName[0], "%S", string);
    stMsg.m_stMsgBody.m_stAccountCreateRoleRequest.m_shWorldID = htons(1);
    stMsg.m_stMsgBody.m_stAccountCreateRoleRequest.m_uiUin = htonl(uiUin);

 

测试了之后发现服务器收到包与客户端发包并不一致。仔细检查了之后才发现,原来在消息头还插入了两个字节的消息包长度。

第二步,加入消息包长度,发送封包。代码如下:

 

#pragma pack(1)
typedef struct tagCommMsg{
    unsigned short ushLength;
    struct tagKylinMsg msg;
} TCommMsg;
#pragma pack()
unsigned short length = sizeof(short) + sizeof(MSGHEAD) + sizeof(tagCreateRole_Account_Request);    
m_stMsg.ushLength = htons(length);


 

在服务器收到封包还是不一致。用抓包工具看原客户端发送的封包,说明在发送的时候就已经不一致了,那么肯定是客户端在发包之前做了一定的处理。

第三步,发布协议头是没有经过修改的,但协议体并不是和协议一一对应。那么就直接按照原客户端处理后的发包模拟发包了。

 

        0x0000:  0016 3e70 b800 c89c 1dee aebf 0800 4500  ..>p..........E.
        0x0010:  0063 1d02 4000 3306 033a 0a06 3323 0a06  .c..@.3..:..3#..
        0x0020:  e02a ec56 1f58 305e ee9a 9d4d debf 5018  .*.V.X0^...M..P.
        0x0030:  4071 4ac1 0000 003b 0001 0000 0000 0000  @qJ....;........
        0x0040:  0000 0000 02c1 0000 0141 0000 0000 0000  .........A......
        0x0050:  0014 0a40 6a75 354b 4d47 3036 6100 0000  ...@ju5KMG06a...
        0x0060:  0a40 6a75 354b 4d47 3036 6100 0001 4100  .@ju5KMG06a...A.
        0x0070:  00                                       .
这是原客户端发包抓下来的,看到了吗?从0x0034-0x00337是新增的unsigned short字段,接下来就是MSGHEAD,再接下来是MSGBODY。

 

而右边的@ju5KMG06a很明显是MSGHEAD中的key。

比较协议之间的区别,将相应字段修改成我们需要的字段。比如我们使用的uiUin为321,转换为十六进制是0x141,在封包里找到这个字段的位置是0x006e,0x006d

直接在程序里把这两个字段改成我们需要的字段就OK啦。代码非常简单,51是从消息头到该字段的偏移。

     *((unsigned int*)((char*)&stMsg.m_stMsgHead + 51)) = htonl(uiUin);
修改之后,就可以顺利地实现到我们的目的,其他字段的修改也同理。创建帐号的协议同样道理也可以实现的。

小结一下步骤:

一、用原客户端发包

二、用工具过滤,抓指定协议的包

三、找到关注字段,将相应字段修改

四、模拟客户端发包

附:tcpdump抓包过滤   tcpdump -i eth1  -XX 'ip[54:2]==701' -s 0

说明一下:-i eth1只监听eth1网口,-XX是将包详细十六进制打出,更直观看封包内容,'ip[54:2]==701'表示IP头开始第54字节处的两个字节值为701,这里是消息号

-s 0表示不仅仅打印包头,tcpdump默认只打印0x52字节包头,加了这个参数才能看到包体内容。

如果还需要过滤,可以加src XX发包源过滤,dst XX发包目的过滤,port XX端口过滤。

PS:当然有很有工具如WPE,XNetHelper就已经实现了修改封包的功能了。自己写的至少有两个好处,第一个,有些抓包工具是被杀毒软件认为是病毒,需要关闭杀毒软件再操作。第二个,自己写的程序更方便集成到其他系统中去。

(责任编辑:IT)
------分隔线----------------------------