潇潇 发表于 2011-11-3 11:27:04

聚仙过心跳包分析(一)

首先,进入游戏(进入游戏是指要到打怪界面,如果连打怪界面不知道的话,下面就不用看了……才发现自己废话这么多的),当然是OD附加游戏进程了,看了后核心模块用得是RekNet,这里顺便简单介绍下这个多用于网游的网络库:

RakNet是一个基于UDP网络传输协议的C++网络库,允许程序员在他们自己的程序中实现高效的网络传输服务。通常情况下用于游戏,但也可以用于其它项目。
Raknet有以下好处:
1、高性能 在同一台计算机上,Radnet可以实现在两个程序之间每秒传输25,000条信息;
2、容易使用 Raknet有在线用户手册,视频教程。每一个函数和类都有详细的讲解,每一个功能都有自己的例程
3、跨平台,当前Raknet支持Windows, Linux, Macs,可以建立在Visual Studio, GCC, Code: Blocks, DevCPP 和其它平台上
4、在线技术支持 RakNet有一个活跃的论坛,邮件列表,你只要给他们发信,他们可以在几小时之内回复你。
5、安全的传输 RakNet在你的代码中自动使用SHA1, AES128, SYN,用RSA避免传输受到攻击
6、音频传输 用Speex编码解码,8位的音频只需要每秒500字节传输。
7、远程终端 用RakNet,你能远程管理你的程序,包括程序的设置,密码的管理和日志的管理。
8、目录服务器 目录服务器允许服务器列举他们自己需要的客户端,并与他们连接。
9、Autopatcher Autopatcher系统将限制客户端传输到服务端的文件,这样是为了避免一些不合法的用户将一些不合法的文件传输到服务端。
10、对象重载系统
11、网络数据压缩 BitStream类允许压缩矢量,矩阵,四元数和在-1到1之间的实数。
12、远程功能调用强健的通信层 可以保障信息按照不同的信道传输
13、RakNet支持两种版权,如果你是做免费游戏,RakNet将是免费的。相反,你必须支付一定的费用。
上面介绍了这个网络库,它是基于UDP协议的,那如果我们分析发包数据,下断send或WSASend函数是没用的,所以我们考虑下断sendto或其它的发包函数,我们这就先下断sendto函数,在游戏中无任何自己的操作动作,断下了,根据经验来说这样的游戏多数是带了心跳包(这样的话只要找到判断关键跳转的地方改成强行跳转就可以,也就是反汇编中类似jb、jnz、jnb等实现跳转的指令改为 jmp ,通常这样就可以跳过心跳包),所以去之……如果还问为何要去之,这里也简单说下,我们在分析功能CALL时,都要经过发包来分析,如果游戏中没任何自己的操作动作也会断下的话,不去掉这个检验是不行的,这是必须的工作,分析代码:

下面是下断sendto函数断下的代码:
71A22C69 >8BFF            MOV EDI,EDI                              ; bp sendto 后断在这里
71A22C6B    55            PUSH EBP
71A22C6C    8BEC            MOV EBP,ESP
71A22C6E    83EC 10         SUB ESP,10
71A22C71    56            PUSH ESI
71A22C72    57            PUSH EDI
71A22C73    33FF            XOR EDI,EDI
71A22C75    813D 2840A371 4>CMP DWORD PTR DS:,WS2_32.71A29>
71A22C7F    0F85 7B680000   JNZ WS2_32.71A29500
71A22C85    393D 2C40A371   CMP DWORD PTR DS:,EDI
71A22C8B    0F84 6F680000   JE WS2_32.71A29500
71A22C91    FF35 2040A371   PUSH DWORD PTR DS:
71A22C97    FF15 AC11A271   CALL DWORD PTR DS:[<&KERNEL32.TlsGetValu>; kernel32.TlsGetValue
71A22C9D    3BC7            CMP EAX,EDI
71A22C9F    8945 F8         MOV DWORD PTR SS:,EAX
71A22CA2    0F84 58680000   JE WS2_32.71A29500
71A22CA8    897D FC         MOV DWORD PTR SS:,EDI
71A22CAB    FF75 08         PUSH DWORD PTR SS:
71A22CAE    E8 8EFEFFFF   CALL WS2_32.71A22B41
71A22CB3    8BF0            MOV ESI,EAX
71A22CB5    3BF7            CMP ESI,EDI
71A22CB7    0F84 F5890000   JE WS2_32.71A2B6B2
71A22CBD    8B45 10         MOV EAX,DWORD PTR SS:
71A22CC0    53            PUSH EBX
71A22CC1    8D4D FC         LEA ECX,DWORD PTR SS:
71A22CC4    51            PUSH ECX
71A22CC5    FF75 F8         PUSH DWORD PTR SS:
71A22CC8    8D4D 08         LEA ECX,DWORD PTR SS:
71A22CCB    57            PUSH EDI
71A22CCC    57            PUSH EDI
71A22CCD    FF75 1C         PUSH DWORD PTR SS:
71A22CD0    8945 F0         MOV DWORD PTR SS:,EAX
71A22CD3    FF75 18         PUSH DWORD PTR SS:
71A22CD6    8B45 0C         MOV EAX,DWORD PTR SS:
71A22CD9    FF75 14         PUSH DWORD PTR SS:
71A22CDC    8945 F4         MOV DWORD PTR SS:,EAX
71A22CDF    8B46 0C         MOV EAX,DWORD PTR DS:
71A22CE2    51            PUSH ECX
71A22CE3    6A 01         PUSH 1
71A22CE5    8D4D F0         LEA ECX,DWORD PTR SS:
71A22CE8    51            PUSH ECX
71A22CE9    FF75 08         PUSH DWORD PTR SS:
71A22CEC    FF50 6C         CALL DWORD PTR DS:
71A22CEF    8BCE            MOV ECX,ESI
71A22CF1    8BD8            MOV EBX,EAX
71A22CF3    E8 2EFEFFFF   CALL WS2_32.71A22B26
71A22CF8    3BDF            CMP EBX,EDI
71A22CFA    5B            POP EBX
71A22CFB    0F85 A3890000   JNZ WS2_32.71A2B6A4
71A22D01    8B45 08         MOV EAX,DWORD PTR SS:
71A22D04    5F            POP EDI
71A22D05    5E            POP ESI
71A22D06    C9            LEAVE
71A22D07    C2 1800         RETN 18下断后接下来的事就是返回或者叫回朔,这里你怎么理解就怎么叫了,我这通常都叫“返回”:
CTRL+F9,F8 返回7次来到这里,
1004CBE0    55            PUSH EBP
1004CBE1    8BEC            MOV EBP,ESP
1004CBE3    83EC 10         SUB ESP,10
1004CBE6    8B45 08         MOV EAX,DWORD PTR SS:
1004CBE9    8945 F0         MOV DWORD PTR SS:,EAX
1004CBEC    8B4D F0         MOV ECX,DWORD PTR SS:
1004CBEF    C641 05 01      MOV BYTE PTR DS:,1
1004CBF3    8B55 F0         MOV EDX,DWORD PTR SS:            ; 循环头
1004CBF6    0FB642 04       MOVZX EAX,BYTE PTR DS:
1004CBFA    85C0            TEST EAX,EAX
1004CBFC    75 66         JNZ SHORT RakNet.1004CC64
1004CBFE    C745 F8 0000000>MOV DWORD PTR SS:,0
1004CC05    C745 FC 0000000>MOV DWORD PTR SS:,0
1004CC0C    C745 F4 0000000>MOV DWORD PTR SS:,0
1004CC13    8B4D F0         MOV ECX,DWORD PTR SS:
1004CC16    83B9 1C060000 0>CMP DWORD PTR DS:,0
1004CC1D    74 1C         JE SHORT RakNet.1004CC3B
1004CC1F    8B55 F0         MOV EDX,DWORD PTR SS:
1004CC22    8B82 20060000   MOV EAX,DWORD PTR DS:
1004CC28    50            PUSH EAX
1004CC29    8B4D F0         MOV ECX,DWORD PTR SS:
1004CC2C    51            PUSH ECX
1004CC2D    8B55 F0         MOV EDX,DWORD PTR SS:
1004CC30    8B82 1C060000   MOV EAX,DWORD PTR DS:
1004CC36    FFD0            CALL EAX
1004CC38    83C4 08         ADD ESP,8
1004CC3B    8B4D F4         MOV ECX,DWORD PTR SS:
1004CC3E    33D2            XOR EDX,EDX
1004CC40    52            PUSH EDX
1004CC41    51            PUSH ECX
1004CC42    8B45 FC         MOV EAX,DWORD PTR SS:
1004CC45    50            PUSH EAX
1004CC46    8B4D F8         MOV ECX,DWORD PTR SS:
1004CC49    51            PUSH ECX
1004CC4A    8B4D F0         MOV ECX,DWORD PTR SS:
1004CC4D    E8 CEDEFFFF   CALL RakNet.?RunUpdateCycle@RakPeer@RakN>
1004CC52    6A 0A         PUSH 0A                                  ; 返回7次后来以这里
1004CC54    8B4D F0         MOV ECX,DWORD PTR SS:
1004CC57    81C1 24060000   ADD ECX,624
1004CC5D    E8 0E520200   CALL RakNet.?WaitOnEvent@SignaledEvent@R>
1004CC62^ EB 8F         JMP SHORT RakNet.1004CBF3                ; 跳到循环头
1004CC64    8B55 F0         MOV EDX,DWORD PTR SS:
1004CC67    C642 05 00      MOV BYTE PTR DS:,0
1004CC6B    33C0            XOR EAX,EAX
1004CC6D    8BE5            MOV ESP,EBP
1004CC6F    5D            POP EBP
1004CC70    C2 0400         RETN 4看上面的反汇编代码,起初我以为心跳包应该在这里,但仔细看了这有个死循环,才想到这里是启动了线程实现的。按照“正向思路法”——按照CALL的执行顺序划分。所以心跳包应该是被CALL RakNet.?RunUpdateCycle@RakPeer@RakN>所调用的,所以在OD中右键跟随这个地址来到下面的代码:

1004AB20 >55            PUSH EBP                                 ; 在这里F2下断
1004AB21    8BEC            MOV EBP,ESP
1004AB23    B8 08120000   MOV EAX,1208
1004AB28    E8 73FB0300   CALL RakNet.1008A6A0
1004AB2D    56            PUSH ESI
1004AB2E    898D 38EEFFFF   MOV DWORD PTR SS:,ECX
1004AB34    8D4D D8         LEA ECX,DWORD PTR SS:
1004AB37    E8 5446FFFF   CALL RakNet.??0SystemAddress@RakNet@@QAE>
1004AB3C    E8 5F2DFDFF   CALL RakNet.?GetSocketLayerOverride@Sock>
1004AB41    85C0            TEST EAX,EAX
1004AB43    0F84 E6000000   JE RakNet.1004AC2F                     ; 线程函数经过,跳实现
………………
………………
1004AC2F    8B8D 38EEFFFF   MOV ECX,DWORD PTR SS:
1004AC35    81C1 1C040000   ADD ECX,41C
1004AC3B    E8 30290000   CALL RakNet.?PopInaccurate@?$ThreadsafeA>
1004AC40    8945 F4         MOV DWORD PTR SS:,EAX
1004AC43    837D F4 00      CMP DWORD PTR SS:,0
1004AC47    0F84 06010000   JE RakNet.1004AD53                     ; 线程函数经过,跳实现
………………
………………
1004AD53    8B8D 38EEFFFF   MOV ECX,DWORD PTR SS:
1004AD59    81C1 C8030000   ADD ECX,3C8
1004AD5F    E8 0C280000   CALL RakNet.?PopInaccurate@?$ThreadsafeA>
1004AD64    8945 D4         MOV DWORD PTR SS:,EAX
1004AD67    837D D4 00      CMP DWORD PTR SS:,0
1004AD6B    0F84 D7020000   JE RakNet.1004B048                     ; 线程函数经过,跳实现
……………………
……………………
1004B048    8B8D 38EEFFFF   MOV ECX,DWORD PTR SS:
1004B04E    81C1 A0030000   ADD ECX,3A0
1004B054    E8 47D00200   CALL RakNet.?IsEmpty@?$Queue@VRakString@>
1004B059    0FB6C0          MOVZX EAX,AL
1004B05C    85C0            TEST EAX,EAX
1004B05E    0F85 7C090000   JNZ RakNet.1004B9E0                      ; 线程函数经过,跳实现
…………………………
…………………………
1004B9E0    C745 CC 0000000>MOV DWORD PTR SS:,0
1004B9E7    EB 09         JMP SHORT RakNet.1004B9F2
1004B9E9    8B45 CC         MOV EAX,DWORD PTR SS:
1004B9EC    83C0 01         ADD EAX,1
1004B9EF    8945 CC         MOV DWORD PTR SS:,EAX
1004B9F2    8B8D 38EEFFFF   MOV ECX,DWORD PTR SS:
1004B9F8    8B55 CC         MOV EDX,DWORD PTR SS:
1004B9FB    3B91 FC020000   CMP EDX,DWORD PTR DS:
1004BA01    0F83 72100000   JNB RakNet.1004CA79                      ; 1线程函数经过,跳未实现,过心跳包的关键点有可能是这里
1004BA07    8B85 38EEFFFF   MOV EAX,DWORD PTR SS:
1004BA0D    8B88 F8020000   MOV ECX,DWORD PTR DS:
1004BA13    8B55 CC         MOV EDX,DWORD PTR SS:
1004BA16    8B0491          MOV EAX,DWORD PTR DS:
1004BA19    8945 EC         MOV DWORD PTR SS:,EAX
1004BA1C    8B4D EC         MOV ECX,DWORD PTR SS:
1004BA1F    83C1 04         ADD ECX,4
1004BA22    51            PUSH ECX
1004BA23    8D4D D8         LEA ECX,DWORD PTR SS:
1004BA26    E8 F532FFFF   CALL RakNet.??4SystemAddress@RakNet@@QAE>; 心跳包函数???
1004BA2B    8B55 08         MOV EDX,DWORD PTR SS:
1004BA2E    0B55 0C         OR EDX,DWORD PTR SS:
1004BA31    75 27         JNZ SHORT RakNet.1004BA5A                ; 2线程函数经过,跳未实现,过心跳包的关键点有可能是这里
1004BA33    E8 78DEFDFF   CALL RakNet.?GetTimeUS@RakNet@@YA_KXZ    ; 心跳包函数????
1004BA38    8945 08         MOV DWORD PTR SS:,EAX
1004BA3B    8955 0C         MOV DWORD PTR SS:,EDX
1004BA3E    6A 00         PUSH 0
1004BA40    68 E8030000   PUSH 3E8
1004BA45    8B45 0C         MOV EAX,DWORD PTR SS:
1004BA48    50            PUSH EAX
1004BA49    8B4D 08         MOV ECX,DWORD PTR SS:
1004BA4C    51            PUSH ECX
1004BA4D    E8 EEE90300   CALL RakNet.1008A440                     ; 心跳包函数????
1004BA52    33D2            XOR EDX,EDX
1004BA54    8945 10         MOV DWORD PTR SS:,EAX
1004BA57    8955 14         MOV DWORD PTR SS:,EDX
1004BA5A    8B45 EC         MOV EAX,DWORD PTR SS:
1004BA5D    8985 18EEFFFF   MOV DWORD PTR SS:,EAX
1004BA63    8B8D 18EEFFFF   MOV ECX,DWORD PTR SS:
1004BA69    8B55 14         MOV EDX,DWORD PTR SS:
1004BA6C    3B91 54100000   CMP EDX,DWORD PTR DS:          ; 比较
1004BA72    0F82 EC000000   JB RakNet.1004BB64                     ; 3线程函数经过,跳未实现,过心跳包的关键点有可能是这里
1004BA78    77 15         JA SHORT RakNet.1004BA8F
1004BA7A    8B85 18EEFFFF   MOV EAX,DWORD PTR SS:
1004BA80    8B4D 10         MOV ECX,DWORD PTR SS:
1004BA83    3B88 50100000   CMP ECX,DWORD PTR DS:
1004BA89    0F86 D5000000   JBE RakNet.1004BB64
1004BA8F    8B55 EC         MOV EDX,DWORD PTR SS:
1004BA92    8B45 10         MOV EAX,DWORD PTR SS:
1004BA95    2B82 50100000   SUB EAX,DWORD PTR DS:
1004BA9B    8B4D 14         MOV ECX,DWORD PTR SS:
1004BA9E    1B8A 54100000   SBB ECX,DWORD PTR DS:
1004BAA4    8B95 38EEFFFF   MOV EDX,DWORD PTR SS:
1004BAAA    8B92 0C050000   MOV EDX,DWORD PTR DS:
1004BAB0    D1EA            SHR EDX,1
1004BAB2    33F6            XOR ESI,ESI
1004BAB4    8985 10EEFFFF   MOV DWORD PTR SS:,EAX
1004BABA    898D 14EEFFFF   MOV DWORD PTR SS:,ECX
1004BAC0    8995 08EEFFFF   MOV DWORD PTR SS:,EDX
1004BAC6    89B5 0CEEFFFF   MOV DWORD PTR SS:,ESI
1004BACC    8B85 14EEFFFF   MOV EAX,DWORD PTR SS:
1004BAD2    3B85 0CEEFFFF   CMP EAX,DWORD PTR SS:
1004BAD8    0F82 86000000   JB RakNet.1004BB64                     ; 4线程函数经过,跳未实现,过心跳包的关键点有可能是这里
1004BADE    77 0E         JA SHORT RakNet.1004BAEE
1004BAE0    8B8D 10EEFFFF   MOV ECX,DWORD PTR SS:
1004BAE6    3B8D 08EEFFFF   CMP ECX,DWORD PTR SS:
1004BAEC    76 76         JBE SHORT RakNet.1004BB64
1004BAEE    8B55 EC         MOV EDX,DWORD PTR SS:
1004BAF1    83BA 80100000 0>CMP DWORD PTR DS:,7
1004BAF8    75 6A         JNZ SHORT RakNet.1004BB64
1004BAFA    8D85 40F7FFFF   LEA EAX,DWORD PTR SS:
1004BB00    50            PUSH EAX
1004BB01    8B4D EC         MOV ECX,DWORD PTR SS:
1004BB04    81C1 F8000000   ADD ECX,0F8
1004BB0A    E8 A1F00000   CALL RakNet.1005ABB0                     ; 心跳包函数????
1004BB0F    8945 FC         MOV DWORD PTR SS:,EAX
1004BB12    8B4D FC         MOV ECX,DWORD PTR SS:
1004BB15    83B9 C8000000 0>CMP DWORD PTR DS:,0
1004BB1C    75 46         JNZ SHORT RakNet.1004BB64                ; 5线程函数经过,跳未实现,过心跳包的关键点有可能是这里
1004BB1E    6A 02         PUSH 2
1004BB20    6A 01         PUSH 1
1004BB22    83EC 14         SUB ESP,14
1004BB25    8BD4            MOV EDX,ESP
1004BB27    8B45 D8         MOV EAX,DWORD PTR SS:
1004BB2A    8902            MOV DWORD PTR DS:,EAX
1004BB2C    8B4D DC         MOV ECX,DWORD PTR SS:
1004BB2F    894A 04         MOV DWORD PTR DS:,ECX
1004BB32    8B45 E0         MOV EAX,DWORD PTR SS:
1004BB35    8942 08         MOV DWORD PTR DS:,EAX
1004BB38    8B4D E4         MOV ECX,DWORD PTR SS:
1004BB3B    894A 0C         MOV DWORD PTR DS:,ECX
1004BB3E    8B45 E8         MOV EAX,DWORD PTR SS:
1004BB41    8942 10         MOV DWORD PTR DS:,EAX
1004BB44    8B8D 38EEFFFF   MOV ECX,DWORD PTR SS:
1004BB4A    E8 21B9FFFF   CALL RakNet.?PingInternal@RakPeer@RakNet>
1004BB4F    8B4D EC         MOV ECX,DWORD PTR SS:
1004BB52    8B55 10         MOV EDX,DWORD PTR SS:
1004BB55    8991 50100000   MOV DWORD PTR DS:,EDX
1004BB5B    8B45 14         MOV EAX,DWORD PTR SS:
1004BB5E    8981 54100000   MOV DWORD PTR DS:,EAX
1004BB64    8B4D EC         MOV ECX,DWORD PTR SS:
1004BB67    81C1 74100000   ADD ECX,1074
1004BB6D    E8 0E70FEFF   CALL RakNet.?Size@?$CircularLinkedList@P>
1004BB72    8B48 28         MOV ECX,DWORD PTR DS:
1004BB75    51            PUSH ECX
1004BB76    8B4D EC         MOV ECX,DWORD PTR SS:
1004BB79    81C1 74100000   ADD ECX,1074
1004BB7F    E8 FC6FFEFF   CALL RakNet.?Size@?$CircularLinkedList@P>
1004BB84    0FB750 24       MOVZX EDX,WORD PTR DS:
1004BB88    52            PUSH EDX
1004BB89    68 F8111110   PUSH RakNet.101111F8
……………………………………
……………………………………先吃饭去过会儿接着分析……饭后来了,哎……

我们常说做任何事都要理论结合实际,没有实践精神是不行的,对我们程序员来说多数时间都要实践,下面就来说说实践……

大家看了上面的反汇编代码不难看出,线程启动后在地址1004AB20里断下,我们F8单步,经过比较后跳转的地方有两种情况,一是直接跳过,二是跳未实现(这里又是废话了),直接跳过的地方我们就不用管了(比如:1004AB43、1004AC47、1004AD6B、1004B05E等地方),而对于标注为“线程函数经过,跳未实现,过心跳包的关键点有可能是这里”的地方,我们要特别留意,这些个地方往往就是突破口。

下面来插个话题:说说"反向思路法"——也可以说成“函数返回法”,这里是指我们在发包函数(或收包函数)下断断下后,返回的上一级函数(CALL)的方法,在OD里有的叫返回,有的叫回朔,同样你怎么理解就怎么叫。当然也不外呼就这些叫法了。
好了,刚才提到这个方法,下面我们就来实践下了,同样是进游戏后bp sendto 断下,前面我们提到返回7次就到了死循环地方,也就是线程函数里,那这次我们只用返回6次就到了CALL RakNet.?RunUpdateCycle@RakPeer@RakN>函数的执行代码的1004BBDC地址,也就是这个CALL的内部执行部分,如下面代码所示:

1004BB84    0FB750 24       MOVZX EDX,WORD PTR DS:
1004BB88    52            PUSH EDX
1004BB89    68 F8111110   PUSH RakNet.101111F8
1004BB8E    8B85 38EEFFFF   MOV EAX,DWORD PTR SS:
1004BB94    05 94030000   ADD EAX,394
1004BB99    50            PUSH EAX
1004BB9A    8B8D 38EEFFFF   MOV ECX,DWORD PTR SS:
1004BBA0    8B91 20050000   MOV EDX,DWORD PTR DS:
1004BBA6    52            PUSH EDX
1004BBA7    8B45 0C         MOV EAX,DWORD PTR SS:
1004BBAA    50            PUSH EAX
1004BBAB    8B4D 08         MOV ECX,DWORD PTR SS:
1004BBAE    51            PUSH ECX
1004BBAF    8B55 EC         MOV EDX,DWORD PTR SS:
1004BBB2    8B82 70100000   MOV EAX,DWORD PTR DS:
1004BBB8    50            PUSH EAX
1004BBB9    8D4D D8         LEA ECX,DWORD PTR SS:
1004BBBC    51            PUSH ECX
1004BBBD    8B4D EC         MOV ECX,DWORD PTR SS:
1004BBC0    81C1 74100000   ADD ECX,1074
1004BBC6    E8 B56FFEFF   CALL RakNet.?Size@?$CircularLinkedList@PAUInternalPacket@Rak>
1004BBCB    8B10            MOV EDX,DWORD PTR DS:
1004BBCD    52            PUSH EDX
1004BBCE    8B4D EC         MOV ECX,DWORD PTR SS:
1004BBD1    81C1 F8000000   ADD ECX,0F8
1004BBD7    E8 64C50000   CALL RakNet.10058140
1004BBDC    8B4D EC         MOV ECX,DWORD PTR SS:                              ; bp sendto 后6次返回到这里
1004BBDF    81C1 F8000000   ADD ECX,0F8
1004BBE5    E8 86EF0000   CALL RakNet.1005AB70
1004BBEA    0FB6C0          MOVZX EAX,AL
1004BBED    85C0            TEST EAX,EAX
1004BBEF    0F85 0F010000   JNZ RakNet.1004BD04
1004BBF5    8B4D EC         MOV ECX,DWORD PTR SS:
1004BBF8    83B9 80100000 0>CMP DWORD PTR DS:,1
1004BBFF    74 0C         JE SHORT RakNet.1004BC0D
1004BC01    8B55 EC         MOV EDX,DWORD PTR SS:
1004BC04    83BA 80100000 0>CMP DWORD PTR DS:,2
1004BC0B    75 19         JNZ SHORT RakNet.1004BC26
1004BC0D    8B4D EC         MOV ECX,DWORD PTR SS:
1004BC10    81C1 F8000000   ADD ECX,0F8
1004BC16    E8 B5D70000   CALL RakNet.100593D0
1004BC1B    0FB6C0          MOVZX EAX,AL
1004BC1E    85C0            TEST EAX,EAX
1004BC20    0F84 DE000000   JE RakNet.1004BD04
1004BC26    8B4D EC         MOV ECX,DWORD PTR SS:
1004BC29    83B9 80100000 0>CMP DWORD PTR DS:,3
1004BC30    75 3B         JNZ SHORT RakNet.1004BC6D
1004BC32    8B4D EC         MOV ECX,DWORD PTR SS:
1004BC35    81C1 F8000000   ADD ECX,0F8
1004BC3B    E8 D0D70000   CALL RakNet.10059410
那为何我们要用到“正向思路法”和“反向思路法”呢?通常情况下我们用得是后者,也就是下断发包函数后返回,而在返回过程中,你觉得可疑的地方你就可以在些执行代码头下F2断点来分析,所以两者有必要结合应用。看了上面的反汇编代码也不难想了,我们的两种思路法,都是在同一个CALL的执行内部,也就是在同一个执行函数内,那么,我们分析心跳包的关键地址就在1004AB20~1004BBDC这个范围内,除掉前面提到过的几个单步标注为“线程函数经过,跳实现”的地方,那地址范围又缩小了,在1004B9E0~1004BBDC之间。
好的,下面我们来分析标注为“线程函数经过,跳未实现,过心跳包的关键点有可能是这里”,上面我们标注了5个这样的地方。现在看第一个:
1004BA01    0F83 72100000   JNB RakNet.1004CA79                      ; 1线程函数经过,跳未实现,过心跳包的关键点有可能是这里我们在OD的反汇编栏目中双点鼠标,把JNB RakNet.1004CA79 改为 jmp 1004CA79 ,但改后游戏提示断线(注:这里不可以游戏中执行任何操作),那说明这个判断跳不是我们要找的心跳包的关键地方。呵呵没办法,重新登陆游戏账号再进入打怪界面……
下面看第二个:

1004BA31    75 27         JNZ SHORT RakNet.1004BA5A                ; 2线程函数经过,跳未实现,过心跳包的关键点有可能是这里
用同样的方法得到同样的结果,重新来过吧……以此类推到了:
1004BAD8    0F82 86000000   JB RakNet.1004BB64                     ; 4线程函数经过,跳未实现,过心跳包的关键点有可能是这里当我们改了地址1004BAD8中的 JB->JMP 游戏没掉线了,那说明心跳包的关键跳转找到了,下面我们就来看看这个跳转下面的几个CALL:

1004BB0A    E8 A1F00000   CALL RakNet.1005ABB0                     ; 心跳包函数????
…………
1004BB4A    E8 21B9FFFF   CALL RakNet.?PingInternal@RakPeer@RakNet>
…………仔细看下上面两个地址中还有个关键跳:
1004BB1C    75 46         JNZ SHORT RakNet.1004BB64                ; 5线程函数经过,跳未实现,过心跳包的关键点有可能是这里和上面我们改的目标地址是一个,那我们可以排除CALL RakNet.1005ABB0   不是心跳包的关键CALL,这样以来我们只有一个CALL是心跳包了……

另外我们所修改的地址1004BAD8(到这里别再问我修改成啥了……)到我们返回的函数地址不远,那说明关键心跳包执行的地方就是这里,我们改了便可以,通常这方法都叫“爆破”,如下代码所示:




1004BAD8   /0F82 86000000   JB RakNet.1004BB64                           ;这里改为 jmp 1004BB64
1004BADE   |77 0E         JA SHORT RakNet.1004BAEE
1004BAE0   |8B8D 10EEFFFF   MOV ECX,DWORD PTR SS:
1004BAE6   |3B8D 08EEFFFF   CMP ECX,DWORD PTR SS:
1004BAEC   |76 76         JBE SHORT RakNet.1004BB64
1004BAEE   |8B55 EC         MOV EDX,DWORD PTR SS:
1004BAF1   |83BA 80100000 0>CMP DWORD PTR DS:,7
1004BAF8   |75 6A         JNZ SHORT RakNet.1004BB64
1004BAFA   |8D85 40F7FFFF   LEA EAX,DWORD PTR SS:
1004BB00   |50            PUSH EAX
1004BB01   |8B4D EC         MOV ECX,DWORD PTR SS:
1004BB04   |81C1 F8000000   ADD ECX,0F8
1004BB0A   |E8 A1F00000   CALL RakNet.1005ABB0
1004BB0F   |8945 FC         MOV DWORD PTR SS:,EAX
1004BB12   |8B4D FC         MOV ECX,DWORD PTR SS:
1004BB15   |83B9 C8000000 0>CMP DWORD PTR DS:,0
1004BB1C   |75 46         JNZ SHORT RakNet.1004BB64
1004BB1E   |6A 02         PUSH 2
1004BB20   |6A 01         PUSH 1
1004BB22   |83EC 14         SUB ESP,14
1004BB25   |8BD4            MOV EDX,ESP
1004BB27   |8B45 D8         MOV EAX,DWORD PTR SS:
1004BB2A   |8902            MOV DWORD PTR DS:,EAX
1004BB2C   |8B4D DC         MOV ECX,DWORD PTR SS:
1004BB2F   |894A 04         MOV DWORD PTR DS:,ECX
1004BB32   |8B45 E0         MOV EAX,DWORD PTR SS:
1004BB35   |8942 08         MOV DWORD PTR DS:,EAX
1004BB38   |8B4D E4         MOV ECX,DWORD PTR SS:
1004BB3B   |894A 0C         MOV DWORD PTR DS:,ECX
1004BB3E   |8B45 E8         MOV EAX,DWORD PTR SS:
1004BB41   |8942 10         MOV DWORD PTR DS:,EAX
1004BB44   |8B8D 38EEFFFF   MOV ECX,DWORD PTR SS:
1004BB4A   |E8 21B9FFFF   CALL RakNet.?PingInternal@RakPeer@RakNet@@IAEXUSystemAddress>
1004BB4F   |8B4D EC         MOV ECX,DWORD PTR SS:
1004BB52   |8B55 10         MOV EDX,DWORD PTR SS:
1004BB55   |8991 50100000   MOV DWORD PTR DS:,EDX
1004BB5B   |8B45 14         MOV EAX,DWORD PTR SS:
1004BB5E   |8981 54100000   MOV DWORD PTR DS:,EAX
1004BB64   \8B4D EC         MOV ECX,DWORD PTR SS:
1004BB67    81C1 74100000   ADD ECX,1074
1004BB6D    E8 0E70FEFF   CALL RakNet.?Size@?$CircularLinkedList@PAUInternalPacket@Rak>
1004BB72    8B48 28         MOV ECX,DWORD PTR DS:
1004BB75    51            PUSH ECX
1004BB76    8B4D EC         MOV ECX,DWORD PTR SS:
1004BB79    81C1 74100000   ADD ECX,1074
1004BB7F    E8 FC6FFEFF   CALL RakNet.?Size@?$CircularLinkedList@PAUInternalPacket@Rak>
1004BB84    0FB750 24       MOVZX EDX,WORD PTR DS:
1004BB88    52            PUSH EDX
1004BB89    68 F8111110   PUSH RakNet.101111F8
1004BB8E    8B85 38EEFFFF   MOV EAX,DWORD PTR SS:
1004BB94    05 94030000   ADD EAX,394
1004BB99    50            PUSH EAX
1004BB9A    8B8D 38EEFFFF   MOV ECX,DWORD PTR SS:
1004BBA0    8B91 20050000   MOV EDX,DWORD PTR DS:
1004BBA6    52            PUSH EDX
1004BBA7    8B45 0C         MOV EAX,DWORD PTR SS:
1004BBAA    50            PUSH EAX
1004BBAB    8B4D 08         MOV ECX,DWORD PTR SS:
1004BBAE    51            PUSH ECX
1004BBAF    8B55 EC         MOV EDX,DWORD PTR SS:
1004BBB2    8B82 70100000   MOV EAX,DWORD PTR DS:
1004BBB8    50            PUSH EAX
1004BBB9    8D4D D8         LEA ECX,DWORD PTR SS:
1004BBBC    51            PUSH ECX
1004BBBD    8B4D EC         MOV ECX,DWORD PTR SS:
1004BBC0    81C1 74100000   ADD ECX,1074
1004BBC6    E8 B56FFEFF   CALL RakNet.?Size@?$CircularLinkedList@PAUInternalPacket@Rak>
1004BBCB    8B10            MOV EDX,DWORD PTR DS:
1004BBCD    52            PUSH EDX
1004BBCE    8B4D EC         MOV ECX,DWORD PTR SS:
1004BBD1    81C1 F8000000   ADD ECX,0F8
1004BBD7    E8 64C50000   CALL RakNet.10058140
1004BBDC    8B4D EC         MOV ECX,DWORD PTR SS:                              ; bp sendto 后5次返回到这里
1004BBDF    81C1 F8000000   ADD ECX,0F8


总结:实际上心跳包分析和大家常听到的找CALL没区别,关键点就是改个判断就成,好了,终于完成了……

caohuamei520 发表于 2011-11-3 13:01:59

我试过了还是不行呀,一会就断,游戏掉线
页: [1]
查看完整版本: 聚仙过心跳包分析(一)