Loading... # 一、可用资源 1. [GitHub](https://github.com/) 2. [WoWWiki | Fandom](https://wowwiki-archive.fandom.com/wiki/Portal:Main) 3. [ownedcore](https://www.ownedcore.com/) 4. [WoW.tools | Export](https://wow.tools/export/) 5. [TrinityCore](https://github.com/TrinityCore/TrinityCore) 6. [recastnavigation](https://github.com/recastnavigation/recastnavigation) 7. [articls show how to make bot](https://drewkestell.us/Article/6/Chapter/1) # 二、工具 1. [dumpwow](https://github.com/namreeb/dumpwow) 2. CheatEngine 3. X64Dbg 4. IDA/ghidra 5. ... # 三、分析过程 1. 通过相关网站获取信息。 2. 使用dump工具修复并dump可执行文件。 3. 使用IDA静态分析可执行文件,使用CheatEngine进行动态调试。 4. 使用VS2019 编写C++(c#)程序,验证数据准确性。 # 四、IDA分析示例 情景:需要分析游戏中背包物品及其信息存储方式。 通过查询API,发现`GetContainerItemInfo`返回了足够的内容:纹理、数量、ID等等。于是祭出IDA,导入可执行文件,通过字符串“GetContainerItemInfo”定位其对应的lua c函数。如下图所示:  其中,`sub_1417158F0`就是接下来需要分析的函数。 > lua函数参数的传递,是使用其lua堆栈(lua_state指针及序号)来进行的。 考虑到[API GetContainerItemInfo](https://wowwiki-archive.fandom.com/wiki/API_GetContainerItemInfo)的参数和返回值: > **Parameters** > > bagID:Number - number of the bag the item is in, e.g. 0 for your backpack > > slot:Number - slot number of the bag item you want the info for. > > **Returns** > texture:String - the texture for the item in the specified bag slot > > itemCount:Number - the number of items in the specified bag slot > > locked:Boolean - 1 if the item is locked by the server, nil otherwise. > > quality:Number - the numeric quality of the item > > readable:Boolean - 1 if the item can be "read" (as in a book) > > lootable:Boolean - 1 if the item is a temporary container containing items that can be looted; otherwise nil. > > itemLink:a hyperlink for the item. 因此,对于其F5分析后的伪代码,有了如下结果: ```c/c++ __int64 __fastcall sub_1417158F0(__int64 a1) { int Itemquality; // edi int slotIndex; // ebx int bagIndex; // eax __int64 v5; // rax __int64 itemPtr; // rbx unsigned int Itemtexture; // eax unsigned int v8; // ebp __int64 itemlocked; // rdx __int128 v10; // xmm1 __int128 v11; // xmm0 __int128 v12; // xmm1 __int64 v13; // r14 unsigned int v14; // eax unsigned int v15; // eax int v16; // edx int v17; // er8 int v18; // er9 __int64 v19; // rax unsigned __int8 Itemlootable; // al unsigned __int8 itemLink; // al __int64 result; // rax char v23; // [rsp+20h] [rbp-B8h] __int64 v24[6]; // [rsp+30h] [rbp-A8h] BYREF __int128 v25[4]; // [rsp+60h] [rbp-78h] BYREF __int64 v26; // [rsp+A0h] [rbp-38h] unsigned int v27; // [rsp+E8h] [rbp+10h] BYREF int v28; // [rsp+F0h] [rbp+18h] BYREF __int64 v29; // [rsp+F8h] [rbp+20h] BYREF if ( (unsigned int)sub_14045E150() && (Itemquality = 2, (unsigned int)sub_14045E150()) ) { //确定下面两行代码是获取 参数以后,同时也能明晰:sub_14045F500 为 lua_tonumber(),而且 a1 为lua_state指针。 slotIndex = sub_14045F500(a1, 2i64); //此处获取第二个参数,肯定是slot bagIndex = sub_14045F500(a1, 1i64); //此处获取第一个参数,肯定是bagID if ( sub_14171E500((unsigned int)(bagIndex - 1), slotIndex - 1, &v29, (int *)&v27, &v28) && (v5 = ItemLoc2Ptr(v29, v27), (itemPtr = v5) != 0) )//此处if判断语句,需要结合深层调用分析,发现v5为对应物品指针(objectmanager链表中obj指针),同时分析此处函数调用,又能获取物品在objectmanager链表中所属关系的表述:物品(guid)存放在背包(guid)中,背包(guid)属于玩家(guid)。 { //考虑到a1为lua_state指针,以及该函数正常需要返回8个参数,可知sub_14080ED20(a1, Itemtexture)开始将结果push到lua堆栈中。再根据返回值顺序,确定各值意义 Itemtexture = sub_1411A4200(v5, 0i64); //此处为获取 texture sub_14080ED20(a1, Itemtexture); lua_pushnumber(a1, (double)*(int *)(*(_QWORD *)(itemPtr + 0x188) + 0x40i64));//此处为itemNum //从而,*(int *)(*(_QWORD *)(itemPtr + 0x188) + 0x40i64)=>物品数量 v8 = 0; if ( (*(_DWORD *)(*(_QWORD *)(itemPtr + 0x188) + 0x5Ci64) & 0x800) != 0 || (itemlocked = 0i64, *(_WORD *)(itemPtr + 0x8D2)) ) // =>物品是否被服务器锁定 { itemlocked = 1i64; } sub_14045E590(a1, itemlocked); v10 = *(_OWORD *)(itemPtr + 0x950); v25[0] = *(_OWORD *)(itemPtr + 0x940); v11 = *(_OWORD *)(itemPtr + 0x960); v25[1] = v10; v12 = *(_OWORD *)(itemPtr + 0x970); v25[2] = v11; v26 = *(_QWORD *)(itemPtr + 0x980); v25[3] = v12; v13 = sub_140853290(v25); v14 = sub_14171E7C0(itemPtr, 4i64); //=》此处获取物品品质,同时根据下面switch语句,可知物品品质分为0->4共5个等级。 if ( v14 ) { switch ( HIBYTE(v14) ) { case 0u: Itemquality = 0; break; case 1u: Itemquality = 1; break; case 2u: break; case 3u: Itemquality = 3; break; case 4u: Itemquality = 4; break; case 5u: Itemquality = 5; break; default: goto LABEL_17; } } else if ( v13 ) { Itemquality = sub_1405B2130(v13, *(unsigned int *)(*(_QWORD *)(itemPtr + 16) + 16i64)); //=》此处获取物品品质 } else { LABEL_17: Itemquality = -1; } lua_pushnumber(a1, (double)Itemquality); v24[0] = 1i64; if ( (unsigned int)sub_1411A5660(itemPtr, v24) || (*(_DWORD *)(*(_QWORD *)(itemPtr + 392) + 92i64) & 0x200) != 0 ) v8 = 1; sub_14045E590(a1, v8); v15 = (**(__int64 (__fastcall ***)(__int64, _QWORD))(itemPtr + 384))(itemPtr + 384, 0i64); sub_14045E590(a1, (v15 >> 2) & 1); v19 = sub_141961CE0(itemPtr, v16, v17, v18, v23); sub_14045E860(a1, v19); Itemlootable = sub_14171F030(itemPtr); sub_14045E590(a1, Itemlootable); itemLink = sub_1411A7C90(itemPtr); sub_14045E590(a1, itemLink); if ( v13 ) sub_14045E750(a1, LODWORD(v25[0])); else sub_14045E820(a1); result = 10i64; } else { result = 0i64; } } else { sub_140460180(a1, "Usage: GetContainerItemInfo(index, slot)"); result = 0i64; } return result; } ``` 因此,在不进行动态分析的情况下,就完成了所需数据的获取。 最后修改:2021 年 09 月 22 日 11 : 37 AM © 禁止转载