**
梦醒暗黑廿年(三)物品篇
**
也不知道还有没有下一篇,估计做完这篇就应该是最后一篇了。NPC、物品、任务三项遍历是每个游戏最重要的三个部分,但以暗黑的尿性,任务有没有都只是那回事,所以有NPC和物品就差不多了。开始找遍历吧:
1、在SendPacket处下断,随便拿起一样物品,断下后向上返回。返回的第一层是典型的发包代码:
6FAC4940 /$ 83EC 08 sub esp, 0x8
6FAC4943 |. 53 push ebx
6FAC4944 |. 8D5424 04 lea edx, dword ptr [esp+0x4]
6FAC4948 |. 52 push edx
6FAC4949 |. BB 05000000 mov ebx, 0x5
6FAC494E |. 884424 08 mov byte ptr [esp+0x8], al
6FAC4952 |. 894C24 09 mov dword ptr [esp+0x9], ecx
6FAC4956 |. E8 85FAFFFF call 6FAC43E0
6FAC495B |. 5B pop ebx
6FAC495C |. 83C4 08 add esp, 0x8
继续再向上返回一层后不要再返回了,因为暗黑2的大部分功能代码都是调用的导出函数,重点向上看几个调用导出函数的地方,其中可能性最大的一个是call <jmp.&D2Common.#10801>,另一个是call <jmp.&D2Common.#10107>,另外还有别的几个调用参数太少,明显就不对。在这两个函数上下断,然后重复拿起包裹物品的操作,可以看到断在了以下代码:
6FB46C53 |. 57 push edi
6FB46C54 |. 8D5424 28 lea edx, dword ptr [esp+0x28]
6FB46C58 |. 52 push edx
6FB46C59 |. 8B5424 20 mov edx, dword ptr [esp+0x20]
6FB46C5D |. 8D4C24 30 lea ecx, dword ptr [esp+0x30]
6FB46C61 |. 51 push ecx
6FB46C62 |. 50 push eax
6FB46C63 |. 52 push edx
6FB46C64 |. 56 push esi
6FB46C65 |. E8 F45CF7FF call <jmp.&D2Common.#10801>
6FB46C6A |. 8BE8 mov ebp, eax
6FB46C6C |. 85ED test ebp, ebp
在这个函数原型其实是有一个小陷阱的,进入D2Common.#10801可以看到这个函数结束后返回的代码是“retn 0x1C”,0x1C/4=7,所以#10801函数应该是有7个调用参数,但在原型上只有6个,所以还要继续向上看代码
6FB46B05 |. 53 push ebx
6FB46B06 |. 894424 18 mov dword ptr [esp+0x18], eax
6FB46B0A |. 8B4424 44 mov eax, dword ptr [esp+0x44]
6FB46B0E |. 2BC2 sub eax, edx
6FB46B10 |. 33D2 xor edx, edx
这儿的push ebx压入的才是第7个参数。以下是具体的参数说明:
ULONG Temp1=0,Temp2=0;
push PageId//这个参数应该是第几页,索引从0开始,最多应该是3
push BagId//包裹ID1,箱子ID9
lea edx,Temp1
push edx
lea edx,Temp2
push edx
push i//物品在第几行
push j//物品在第几列
push ItemBase
call uD2Common_10801
这个ItemBase用CE找吧,实在不记得是怎么找的了。
ULONG uBase=*(ULONG *)(uD2ClientAddr+0x11BBFC);
ULONG ItemBase=*(ULONG *)(uBase+0x60);
同样办法找腰带物品,总结后的代码:
_asm
{
pushad
push i; //在腰带中的索引
push ItemBase;// 自己的地址 + 0x60
call uD2Common_10455
mov Addr, eax
popad
}
腰带最多16格,i的取值范围为0≤i<16。
这个物品篇的内容太少,就这样草草结束了蛮虚的。一是内容虚,二是心虚。不过虚就虚吧,快四十的人了,不虚还能怎样:)