自动动手写发包工具
为了测试服务器大量在线的性能,需要自己写机器人,模拟大量客户端在线的情况。第一步是创建帐号,第一个办法是直接在服务器后台用脚本创建帐号,另一个办法是模拟客户端发包。前者需要登录到服务器执行,后者可以在其他机器上执行,于是试着用后一种方法实现。
第一步,包含协议头文件,再用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) |