游戏:天龙八部
版本:0.13.0402
系统:windows xp
工具:CE5.2+OD1.10
目标:搜索人物基地址
第一步,用CE搜索人物HP,得到一堆地址,掉血后继续搜索,得到唯一地址0ABDC360(HP地址)
第二步,切换地图后发现该地址里的值已经不是HP,是动态地址,重复第一步搜索出新的HP地址(地址省略)
第三步,这时候不再切换地图,用CE5.2对找到的HP地址下写访问内存断点,此步也可用OD下写内存断点,找到汇编语句如下
0044B280 55 PUSH EBP
0044B281 8BEC MOV EBP,ESP
0044B283 56 PUSH ESI
0044B284 8BF1 MOV ESI,ECX ; 1.2 esi=ecx
0044B286 8B4E 04 MOV ECX,DWORD PTR DS:[ESI+4]
0044B289 8B01 MOV EAX,DWORD PTR DS:[ECX]
0044B28B 57 PUSH EDI
0044B28C FF90 14010000 CALL DWORD PTR DS:[EAX+114]
0044B292 83F8 02 CMP EAX,2
0044B295 8B3D 48465700 MOV EDI,DWORD PTR DS:[<&tEngine.?tThrowS>; tEngine.?tThrowStringException@@YAXPBDZZ
0044B29B 75 19 JNZ SHORT Game.0044B2B6
0044B29D 68 63050000 PUSH 563
0044B2A2 68 54975700 PUSH Game.00579754 ; ASCII ".\DataPool\GMDP_CharacterData.cpp"
0044B2A7 68 48975700 PUSH Game.00579748 ; ASCII "CT_MONSTER"
0044B2AC 68 20975700 PUSH Game.00579720 ; ASCII "Character must not %s,(File:%s Line:%d)"
0044B2B1 FFD7 CALL EDI
0044B2B3 83C4 10 ADD ESP,10
0044B2B6 8B4E 04 MOV ECX,DWORD PTR DS:[ESI+4]
0044B2B9 8B11 MOV EDX,DWORD PTR DS:[ECX]
0044B2BB FF92 14010000 CALL DWORD PTR DS:[EDX+114]
0044B2C1 83F8 01 CMP EAX,1
0044B2C4 75 19 JNZ SHORT Game.0044B2DF
0044B2C6 68 64050000 PUSH 564
0044B2CB 68 54975700 PUSH Game.00579754 ; ASCII ".\DataPool\GMDP_CharacterData.cpp"
0044B2D0 68 78975700 PUSH Game.00579778 ; ASCII "CT_PLAYEROTHER"
0044B2D5 68 20975700 PUSH Game.00579720 ; ASCII "Character must not %s,(File:%s Line:%d)"
0044B2DA FFD7 CALL EDI
0044B2DC 83C4 10 ADD ESP,10
0044B2DF 8B46 08 MOV EAX,DWORD PTR DS:[ESI+8] ; 1.2 eax=[esi+8]
0044B2E2 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8] ; 01.1 血来自父函数第一个参数
0044B2E5 8988 B8060000 MOV DWORD PTR DS:[EAX+6B8],ECX ; 1.1 血被写入
0044B2EB 8B0D 9C975B00 MOV ECX,DWORD PTR DS:[5B979C]
0044B2F1 8B11 MOV EDX,DWORD PTR DS:[ECX]
0044B2F3 68 B4545700 PUSH Game.005754B4 ; ASCII "player"
0044B2F8 6A 19 PUSH 19
0044B2FA FF52 4C CALL DWORD PTR DS:[EDX+4C]
0044B2FD 5F POP EDI
0044B2FE 5E POP ESI
0044B2FF 5D POP EBP
0044B300 C2 0400 RETN 4
0044B281 8BEC MOV EBP,ESP
0044B283 56 PUSH ESI
0044B284 8BF1 MOV ESI,ECX ; 1.2 esi=ecx
0044B286 8B4E 04 MOV ECX,DWORD PTR DS:[ESI+4]
0044B289 8B01 MOV EAX,DWORD PTR DS:[ECX]
0044B28B 57 PUSH EDI
0044B28C FF90 14010000 CALL DWORD PTR DS:[EAX+114]
0044B292 83F8 02 CMP EAX,2
0044B295 8B3D 48465700 MOV EDI,DWORD PTR DS:[<&tEngine.?tThrowS>; tEngine.?tThrowStringException@@YAXPBDZZ
0044B29B 75 19 JNZ SHORT Game.0044B2B6
0044B29D 68 63050000 PUSH 563
0044B2A2 68 54975700 PUSH Game.00579754 ; ASCII ".\DataPool\GMDP_CharacterData.cpp"
0044B2A7 68 48975700 PUSH Game.00579748 ; ASCII "CT_MONSTER"
0044B2AC 68 20975700 PUSH Game.00579720 ; ASCII "Character must not %s,(File:%s Line:%d)"
0044B2B1 FFD7 CALL EDI
0044B2B3 83C4 10 ADD ESP,10
0044B2B6 8B4E 04 MOV ECX,DWORD PTR DS:[ESI+4]
0044B2B9 8B11 MOV EDX,DWORD PTR DS:[ECX]
0044B2BB FF92 14010000 CALL DWORD PTR DS:[EDX+114]
0044B2C1 83F8 01 CMP EAX,1
0044B2C4 75 19 JNZ SHORT Game.0044B2DF
0044B2C6 68 64050000 PUSH 564
0044B2CB 68 54975700 PUSH Game.00579754 ; ASCII ".\DataPool\GMDP_CharacterData.cpp"
0044B2D0 68 78975700 PUSH Game.00579778 ; ASCII "CT_PLAYEROTHER"
0044B2D5 68 20975700 PUSH Game.00579720 ; ASCII "Character must not %s,(File:%s Line:%d)"
0044B2DA FFD7 CALL EDI
0044B2DC 83C4 10 ADD ESP,10
0044B2DF 8B46 08 MOV EAX,DWORD PTR DS:[ESI+8] ; 1.2 eax=[esi+8]
0044B2E2 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8] ; 01.1 血来自父函数第一个参数
0044B2E5 8988 B8060000 MOV DWORD PTR DS:[EAX+6B8],ECX ; 1.1 血被写入
0044B2EB 8B0D 9C975B00 MOV ECX,DWORD PTR DS:[5B979C]
0044B2F1 8B11 MOV EDX,DWORD PTR DS:[ECX]
0044B2F3 68 B4545700 PUSH Game.005754B4 ; ASCII "player"
0044B2F8 6A 19 PUSH 19
0044B2FA FF52 4C CALL DWORD PTR DS:[EDX+4C]
0044B2FD 5F POP EDI
0044B2FE 5E POP ESI
0044B2FF 5D POP EBP
0044B300 C2 0400 RETN 4
这是完整的子函数,实际血被写入的那句代码是红色那句,由此可得知血被存在[eax+6b8]中,6b8是个偏移量,HP指针地址其实存在eax中,根据该段代码的分析,得知eax=[esi+8],而esi=调用函数带进来的ecx,以上代码中注释1.1,1.2,1.3有说明,记好此时的eax,ecx两个值,下面一步就是要查这两个值存的东西变不变
第四步,让自己掉一次血,发现HP地址没变,OD中0044B2F5行代码处下断点,发现此时的eax,ecx也没变,猜测HP地址切换地图时才可能重新分配
第五步:切换一次地图后代码中断,发现此时的eax,ecx与上次又不一样了,上步的猜测可能正确,因为eax=[esi+8]=[ecx+8],所以eax是依赖ecx的,ecx又是来自调用函数的,所以使用调用堆栈去查看调用函数中ecx是怎么来的,OD中调用堆栈的父函数处回车即可,以下是父函数代码
004D7A10 55 PUSH EBP
004D7A11 8BEC MOV EBP,ESP
004D7A13 51 PUSH ECX
004D7A14 A1 F0975B00 MOV EAX,DWORD PTR DS:[5B97F0]
004D7A19 3B05 E4975B00 CMP EAX,DWORD PTR DS:[5B97E4]
004D7A1F 53 PUSH EBX
004D7A20 56 PUSH ESI
004D7A21 0F85 AB080000 JNZ Game.004D82D2
004D7A27 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8]
004D7A2A 8B0D 78695B00 MOV ECX,DWORD PTR DS:[5B6978]
004D7A30 8B46 08 &n
004D7A11 8BEC MOV EBP,ESP
004D7A13 51 PUSH ECX
004D7A14 A1 F0975B00 MOV EAX,DWORD PTR DS:[5B97F0]
004D7A19 3B05 E4975B00 CMP EAX,DWORD PTR DS:[5B97E4]
004D7A1F 53 PUSH EBX
004D7A20 56 PUSH ESI
004D7A21 0F85 AB080000 JNZ Game.004D82D2
004D7A27 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8]
004D7A2A 8B0D 78695B00 MOV ECX,DWORD PTR DS:[5B6978]
004D7A30 8B46 08 &n
