早就答应给大家说一下我是怎么找包裹地址的,今天有空,我就简单的讲一下,希望对大家有帮助...
首先我们用CE来找出是什么指令修改了我们包裹中物品的数量(怎么找我就不说了,不懂的看CCB老大的教程)
找到指令是
0048F0AB mov dword ptr [ecx+14], edx
用OD打开武林elementclient.exe,Ctrl+G转到表达式0048F0AB...
可以看到这条指令是在一个函数中
0048F0A0 /$ 8B4424 04 mov eax, dword ptr [esp+4] 0048F0A4 |. 8B51 14 mov edx, dword ptr [ecx+14] 0048F0A7 |. 03D0 add edx, eax 0048F0A9 |. 8BC2 mov eax, edx 0048F0AB |. 8951 14 mov dword ptr [ecx+14], edx 0048F0AE |. 85C0 test eax, eax 0048F0B0 |. 7D 07 jge short 0048F0B9 0048F0B2 |. C741 14 00000>mov dword ptr [ecx+14], 0 0048F0B9 |> 8B41 18 mov eax, dword ptr [ecx+18] 0048F0BC |. 8B51 14 mov edx, dword ptr [ecx+14] 0048F0BF |. 3BD0 cmp edx, eax 0048F0C1 |. 7E 03 jle short 0048F0C6 0048F0C3 |. 8941 14 mov dword ptr [ecx+14], eax 0048F0C6 |> 8B41 14 mov eax, dword ptr [ecx+14] 0048F0C9 \. C2 0400 retn 4
我们在开始的地方F2下断,F8单步步过看看每条指令都做了些什么...
粗略的看一下,可以发现,当前CALL传入的参数1也就是[ESP+4]是-1,也就是我们使用了这个物品(比如吃药),[ECX+14]是存放的当前物品的数量,而[ECX+18]上存放的当前物品堆叠上限...因为是16进制的,所以大家要习惯看这些数值...
再看看程序流程,基本可以看出这个函数的功能是判断当前使用的物品是否超出1~99这个范围,也就是判断是否用完了或者是捡满了...
那么找包裹物品的地址,我们就要找出ECX的值是怎么来的!!!
OK,Ctrl+F9执行到返回,我们来看看是哪条指令调用了这个CALL...
返回到指令
0048908D |. E8 0E600000 call 0048F0A0
老习惯,我们上下拖动大致看看这段指令有多长...(其实主要是大概要回溯多长,因为我们要找ECX的值)
00489060 /$ 53 push ebx 00489061 |. 8B5C24 08 mov ebx, dword ptr [esp+8] 00489065 |. 56 push esi 00489066 |. 57 push edi 00489067 |. 85DB test ebx, ebx 00489069 |. 8BF9 mov edi, ecx 0048906B |. 7C 3E jl short 004890AB 0048906D |. 3B5F 10 cmp ebx, dword ptr [edi+10] 00489070 |. 7D 39 jge short 004890AB 00489072 |. 8B47 0C mov eax, dword ptr [edi+C] 00489075 |. 8B3498 mov esi, dword ptr [eax+ebx*4] 00489078 |. 85F6 test esi, esi 0048907A |. 75 08 jnz short 00489084 0048907C |. 5F pop edi 0048907D |. 5E pop esi 0048907E |. B0 01 mov al, 1 00489080 |. 5B pop ebx 00489081 |. C2 0800 retn 8 00489084 |> 8B4C24 14 mov ecx, dword ptr [esp+14] 00489088 |. F7D9 neg ecx 0048908A |. 51 push ecx 0048908B |. 8BCE mov ecx, esi 0048908D |. E8 0E600000 call 0048F0A0
先看看指令,发现ECX=ESI,往上ESI=[EAX+EBX*4],OK!!!我们在
00489075 |. 8B3498 mov esi, dword ptr [eax+ebx*4]
处下断...
发现EBX的值实际上就是我们点击包裹的格子序号(当然,人家是从0开始计数的...)
恩,有门...再就是找EAX的值是怎么来的了...
往上看,EAX=[EDI+C],EDI=ECX...
没办法,ECX是由上一级函数传入的,好吧,继续Ctrl+F9...
转到指令
00457724 |. E8 37190300 call 00489060
还是上下看看...有点长,中间还有好几个CALL,郁闷...
004576B0 /$ 8B4424 04 mov eax, dword ptr [esp+4] 004576B4 |. 53 push ebx 004576B5 |. 55 push ebp 004576B6 |. 56 push esi 004576B7 |. 8B70 0C mov esi, dword ptr [eax+C] 004576BA |. 8BD9 mov ebx, ecx 004576BC |. 33C9 xor ecx, ecx 004576BE |. 57 push edi 004576BF |. 8A0E mov cl, byte ptr [esi] 004576C1 |. 51 push ecx 004576C2 |. 8BCB mov ecx, ebx 004576C4 |. E8 C7860000 call 0045FD90 004576C9 |. 8BE8 mov ebp, eax 004576CB |. 85ED test ebp, ebp 004576CD |. 0F84 AC000000 je 0045777F 004576D3 |. 33D2 xor edx, edx 004576D5 |. 6A 00 push 0 004576D7 |. 8A56 01 mov dl, byte ptr [esi+1] 004576DA |. 8BCD mov ecx, ebp 004576DC |. 52 push edx 004576DD |. E8 EE0F0300 call 004886D0 004576E2 |. 8BF8 mov edi, eax 004576E4 |. 85FF test edi, edi 004576E6 |. 0F84 93000000 je 0045777F 004576EC |. 8B46 02 mov eax, dword ptr [esi+2] 004576EF |. 8B4F 08 mov ecx, dword ptr [edi+8] 004576F2 |. 3BC8 cmp ecx, eax 004576F4 |. 0F85 85000000 jnz 0045777F 004576FA |. 6A 00 push 0 ; /Arg3 = 00000000 004576FC |. 6A 00 push 0 ; |Arg2 = 00000000 004576FE |. 50 push eax ; |Arg1 004576FF |. 8BCB mov ecx, ebx ; | 00457701 |. E8 9A4A0200 call 0047C1A0 ; \elementc.0047C1A0 00457706 |. 8B07 mov eax, dword ptr [edi] 00457708 |. 8BCF mov ecx, edi 0045770A |. FF50 1C call dword ptr [eax+1C] 0045770D |. 66:8B46 06 mov ax, word ptr [esi+6] 00457711 |. 66:85C0 test ax, ax 00457714 |. 74 3C je short 00457752 00457716 |. 33C9 xor ecx, ecx 00457718 |. 25 FFFF0000 and eax, 0FFFF 0045771D |. 8A4E 01 mov cl, byte ptr [esi+1] 00457720 |. 50 push eax 00457721 |. 51 push ecx 00457722 |. 8BCD mov ecx, ebp 00457724 |. E8 37190300 call 00489060
打起精神,记住我们要找的是ECX的值...
仔细看,就可以看出,ECX=EBP,而EBP=EAX
004576DA |. 8BCD mov ecx, ebp 004576C9 |. 8BE8 mov ebp, eax
从函数开始下断,我们看看是什么指令修改了EAX的值...
恩,mov ebp, eax上面有个CALL,大家都应该知道对于高级语言,编译器一般习惯于将返回值放如EAX中的吧...
二话不说,先进call 0045FD90里面看看是个什么情况...
0045FD90 /$ 8B4424 04 mov eax, dword ptr [esp+4] 0045FD94 |. 83F8 04 cmp eax, 4 ; Switch (cases 0..4) 0045FD97 |. 77 34 ja short 0045FDCD 0045FD99 |. FF2485 D4FD45>jmp dword ptr [eax*4+45FDD4] 0045FDA0 |> 8B81 3C080000 mov eax, dword ptr [ecx+83C] ; Case 0 of switch 0045FD94 0045FDA6 |. C2 0400 retn 4 0045FDA9 |> 8B81 40080000 mov eax, dword ptr [ecx+840] ; Case 1 of switch 0045FD94 0045FDAF |. C2 0400 retn 4 0045FDB2 |> 8B81 44080000 mov eax, dword ptr [ecx+844] ; Case 2 of switch 0045FD94 0045FDB8 |. C2 0400 retn 4 0045FDBB |> 8B81 78080000 mov eax, dword ptr [ecx+878] ; Case 3 of switch 0045FD94 0045FDC1 |. C2 0400 retn 4 0045FDC4 |> 8B81 7C080000 mov eax, dword ptr [ecx+87C] ; Case 4 of switch 0045FD94 0045FDCA |. C2 0400 retn 4 0045FDCD |> 33C0 xor eax, eax ; Default case of switch 0045FD94 0045FDCF \. C2 0400 retn 4 0045FDD2 8BFF mov edi, edi 0045FDD4 . A0FD4500 dd elementc.0045FDA0 ; 分支表 被用于 0045FD99 0045FDD8 . A9FD4500 dd elementc.0045FDA9 0045FDDC . B2FD4500 dd elementc.0045FDB2 0045FDE0 . BBFD4500 dd elementc.0045FDBB 0045FDE4 . C4FD4500 dd elementc.0045FDC4
发现是个分支处理的函数,至于吃药是怎么分支的,我们先出去看看这个参数[ESP+4]和ECX的值是怎么来的...
004576BF |. 8A0E mov cl, byte ptr [esi] 004576C1 |. 51 push ecx 004576C2 |. 8BCB mov ecx, ebx 004576C4 |. E8 C7860000 call 0045FD90
下断,可以知道push ecx的时候ECX是0,而mov ecx,ebx的时候不知道大家看出来什么没有...
当时我就觉得这个EBX的值很熟,后来一想,这个值不就是人物属性地址[[8BCB44]+1C]+24的值么...
而且,吃药的时候,那个CALL要传入的参数始终是0...
至此,所有的我们需要的信息都找到了...
那我们就可以总结了...
[[[[8BCB44]+1C]+24]+83C]+10 的值是角色包裹最大容量... [[[[8BCB44]+1C]+24]+83C]+C 是角色包裹首地址... [[[[[8BCB44]+1C]+24]+83C]+C]+4*格子序号 是格子物品首地址... [[[[[[8BCB44]+1C]+24]+83C]+C]+4*格子序号]+14 是此格物品的数量... [[[[[[8BCB44]+1C]+24]+83C]+C]+4*格子序号]+18 是此格物品的堆叠上限...
授人以鱼,不如授人以渔...关于其他的地址需要大家举一反三,自己查找了,我在这只是起个抛砖引玉的作用...
呵呵,写完了,不知道写得明不明白,有什么问题希望大家多多批评,谢谢!