申请会员ID:wangbeng1、申 请 I D: wangbeng
2、个人邮箱: wangbeng@sina.com
3、原创技术文章: https://www.cnblogs.com/wangbeng [size=1.25em]【原创】大航海时代ol(台服)找call - 人物背包物品信息及中文名称解密 大航海时代ol的老粉了,由于自己一直喜欢编程,也一直想学逆向,玩游戏也是边玩边学着做各种简单的按键类外挂 ,从按键精灵到seraph,也用Delphi+按键鼠标驱动写过图色识别的简单外挂 ,纯自己用,既方便游戏 ,又提高了编程水平,玩得不亦乐乎。曾经为了能直接在4096*2048的超大世界地图上自动寻路,搜遍了网上的自动寻路算法,什么A星、跳点、分层都看过,也写出了勉强能用的A星寻路,能自动导航世界各地。但由于水平有限,一直局限于模拟按键,最多就是读读游戏内存,传说中的找Call技术一直未能入门,始终是心中的一大遗憾。 大航海时代ol是线程发包,而网上的找Call大都是先找到发包函数,再找功能Call。近段时间,在网上找了好多资料学习,前段时候玩传奇3私服时,居然能找到寻路call,能找到包裹数组、怪物数组,还写了个全自动的练级挂,不由的信心大增。正好前几天开始回归台服,不由得又拿起了CE,走上了寻Call之路。
一、背包物品信息
![]()
打开持有物品界面,搜索第一个物品名称“寬鬆衫”(搜索类型为string utf-16),得地址唯一 183c4f48 再重新搜索这个地址,得唯一地址的地址 0493EB28,在此地址上:
find who access this address 关闭背包再重新打开:0095D878 - 8B 46 0C - mov eax,[esi+0C] 中断在此句上
| 查找序号 | 地址 | 描述 | | 下断点: | GVOnline.exe+55D878 | [esi+0c]=中文名称地址,[esi+08]=ID | | 返回1: | GVOnline.exe+47C1D3 | esi=ecx=edi=[eax+0c] | | 进入2: | GVOnline.exe+621D50 | esi=ecx=edi=[eax+0c] =[[eax+08]+0c] | | 进入3: | GVOnline.exe+9AAE03 | esi=ecx=edi=[eax+0c] =[[eax+08]+0c] =[ecx+04]+0]+0]+...+0]+08]+0c] | | ///-----------------------------------------------------------------------------
GVOnline.exe+55D7E0 - 55 - push ebp
GVOnline.exe+55D7E1 - 8B EC - mov ebp,esp
GVOnline.exe+55D7E3 - 83 EC 08 - sub esp,08 { 8 }
GVOnline.exe+55D7E6 - 56 - push esi
GVOnline.exe+55D7E7 - 8B F1 - mov esi,ecx           { esi = ecx }
GVOnline.exe+55D7E9 - 8B 46 08 - mov eax,[esi+08]
GVOnline.exe+55D7EC - 85 C0 - test eax,eax
GVOnline.exe+55D7EE - 75 1A - jne GVOnline.exe+55D80A
GVOnline.exe+55D7F0 - 38 86 3D010000 - cmp [esi+0000013D],al
GVOnline.exe+55D7F6 - 74 12 - je GVOnline.exe+55D80A
GVOnline.exe+55D7F8 - 68 85030000 - push 00000385 { 901 }
GVOnline.exe+55D7FD - E8 4EA0BBFF - call GVOnline.exe+117850
GVOnline.exe+55D802 - 83 C4 04 - add esp,04 { 4 }
GVOnline.exe+55D805 - 5E - pop esi
GVOnline.exe+55D806 - 8B E5 - mov esp,ebp
GVOnline.exe+55D808 - 5D - pop ebp
GVOnline.exe+55D809 - C3 - ret
GVOnline.exe+55D80A - 80 BE 3E010000 00 - cmp byte ptr [esi+0000013E],00 { 0 }
GVOnline.exe+55D811 - 74 0B - je GVOnline.exe+55D81E
GVOnline.exe+55D813 - 8B 86 9C000000 - mov eax,[esi+0000009C]
GVOnline.exe+55D819 - 5E - pop esi
GVOnline.exe+55D81A - 8B E5 - mov esp,ebp
GVOnline.exe+55D81C - 5D - pop ebp
GVOnline.exe+55D81D - C3 - ret
GVOnline.exe+55D81E - 50 - push eax
GVOnline.exe+55D81F - E8 CC0CC0FF - call GVOnline.exe+15E4F0
GVOnline.exe+55D824 - 83 C4 04 - add esp,04 { 4 }
GVOnline.exe+55D827 - 83 F8 04 - cmp eax,04 { 4 }
GVOnline.exe+55D82A - 77 54 - ja GVOnline.exe+55D880
GVOnline.exe+55D82C - FF 76 08 - push [esi+08]
GVOnline.exe+55D82F - E8 9C0CC0FF - call GVOnline.exe+15E4D0
GVOnline.exe+55D834 - 83 C4 04 - add esp,04 { 4 }
GVOnline.exe+55D837 - 83 F8 0C - cmp eax,0C { 12 }
GVOnline.exe+55D83A - 74 D7 - je GVOnline.exe+55D813
GVOnline.exe+55D83C - 8B 76 08 - mov esi,[esi+08] [esi+8] = ID
GVOnline.exe+55D83F - E8 3CECBFFF - call GVOnline.exe+15C480
GVOnline.exe+55D844 - 8D 4D FC - lea ecx,[ebp-04]
GVOnline.exe+55D847 - 51 - push ecx
GVOnline.exe+55D848 - 8D 4D F8 - lea ecx,[ebp-08]
GVOnline.exe+55D84B - 51 - push ecx
GVOnline.exe+55D84C - 56 - push esi                       { esi = ID }
GVOnline.exe+55D84D - 8D 88 843D0000 - lea ecx,[eax+00003D84] { ecx = 物品名称基址 1219664 }
GVOnline.exe+55D853 - E8 38DCBEFF - call GVOnline.exe+14B490 // >Tab选中NPC、活动场景等获取名称均从此call取得) 通用名称call
GVOnline.exe+55D858 - 85 C0 - test eax,eax
GVOnline.exe+55D85A - 74 24 - je GVOnline.exe+55D880
GVOnline.exe+55D85C - 8B 70 04 - mov esi,[eax+04] -------------> esi = [eax+04]
GVOnline.exe+55D85F - 85 F6 - test esi,esi
GVOnline.exe+55D861 - 74 1D - je GVOnline.exe+55D880
GVOnline.exe+55D863 - 83 7E 18 00 - cmp dword ptr [esi+18],00 { 0 }
GVOnline.exe+55D867 - 7E 0F - jle GVOnline.exe+55D878
GVOnline.exe+55D869 - FF 76 04 - push [esi+04]
GVOnline.exe+55D86C - 8D 46 08 - lea eax,[esi+08]
GVOnline.exe+55D86F - 50 - push eax
GVOnline.exe+55D870 - E8 BBD83A00 - call GVOnline.exe+90B130
GVOnline.exe+55D875 - 83 C4 08 - add esp,08 { 8 }
GVOnline.exe+55D878 - 8B 46 0C - mov eax,[esi+0C] { --------------> 断在此处 [esi+0C]= 宽松衫
GVOnline.exe+55D87B - 5E - pop esi
GVOnline.exe+55D87C - 8B E5 - mov esp,ebp
GVOnline.exe+55D87E - 5D - pop ebp
GVOnline.exe+55D87F - C3 - ret
//---------------------------------------------------------------
动态调试后 [esi+0c]=中文名称和[esi+8]=物品ID 中的esi不一致,按照ID来分析esi的来源。
esi = ecx , ecx上层函数调用的参数,返回1
//=============返回1===================================
GVOnline.exe+47C090 - 83 C4 14 - add esp,14 { 20 }
GVOnline.exe+47C093 - 8D 89 18080000 - lea ecx,[ecx+00000818]
GVOnline.exe+47C099 - E8 B25C1A00 - call GVOnline.exe+621D50 { 修改eax }-->进去看看
GVOnline.exe+47C09E - 85 C0 - test eax,eax
GVOnline.exe+47C0A0 - 0F84 5E050000 - je GVOnline.exe+47C604
GVOnline.exe+47C0A6 - 8B 78 0C - mov edi,[eax+0C] { edi = [eax+0c]}
GVOnline.exe+47C0A9 - 89 7D E8 - mov [ebp-18],edi
.....
.....
GVOnline.exe+47C1BF - 6A FF - push -01 { 255 }
GVOnline.exe+47C1C1 - 6A FF - push -01 { 255 }
GVOnline.exe+47C1C3 - 6A 04 - push 04 { 4 }
GVOnline.exe+47C1C5 - 6A 16 - push 16 { 22 }
GVOnline.exe+47C1C7 - 68 98010000 - push 00000198 { 408 }
GVOnline.exe+47C1CC - 8B CF - mov ecx,edi { ecx = edi ( [ecx+8]=id) }
GVOnline.exe+47C1CE - E8 0D160E00 - call GVOnline.exe+55D7E0
GVOnline.exe+47C1D3 - 50 - push eax ------------------------------>返回1
//---------------------------------------------------------------
esi=ecx=edi=[eax+0c] ,eax为call GVOnline.exe+621D50的返回值 ,追 进去看下//=====进入call GVOnline.exe+621D50 ======================================GVOnline.exe+621D50 - FF B1 94000000 - push [ecx+00000094] { 物品在背包中的序号 }
GVOnline.exe+621D56 - 81 C1 EC020000 - add ecx,000002EC { ecx为使用背包基址,链表一串。
GVOnline.exe+621D5C - E8 A2903800 - call GVOnline.exe+9AAE03 进去看看 eax
GVOnline.exe+621D61 - 85 C0 - test eax,eax { eax = 物品ID }
GVOnline.exe+621D63 - 74 04 - je GVOnline.exe+621D69
GVOnline.exe+621D65 - 8B 40 08 - mov eax,[eax+08] eax = [eax+08] = [ecx+04]+0]+0]+...+0]+08]
GVOnline.exe+621D68 - C3 - ret
GVOnline.exe+621D69 - 33 C0 - xor eax,eax
GVOnline.exe+621D6B - C3 - ret
//-------------------------------------
esi=ecx=edi=[eax+0c] =[[eax+08]+0c] , eax 为 call GVOnline.exe+9AAE03的返回值,追进去看下:
//-------------进入call GVOnline.exe+9AAE03-----------------------
GVOnline.exe+9AAE03 - 55 - push ebp
GVOnline.exe+9AAE04 - 8B EC - mov ebp,esp
GVOnline.exe+9AAE06 - 8B 55 08 - mov edx,[ebp+08] { 序号 }
GVOnline.exe+9AAE09 - 3B 51 0C - cmp edx,[ecx+0C] { 背包(可使用物品)总数量 }
GVOnline.exe+9AAE0C - 7D 10 - jnl GVOnline.exe+9AAE1E
GVOnline.exe+9AAE0E - 85 D2 - test edx,edx
GVOnline.exe+9AAE10 - 78 0C - js GVOnline.exe+9AAE1E
GVOnline.exe+9AAE12 - 8B 41 04 - mov eax,[ecx+04] eax = [ecx+4]
GVOnline.exe+9AAE15 - 74 09 - je GVOnline.exe+9AAE20
GVOnline.exe+9AAE17 - 8B 00 - mov eax,[eax] eax=[eax]指向下一个物品
GVOnline.exe+9AAE19 - 4A - dec edx
GVOnline.exe+9AAE1A - 75 FB - jne GVOnline.exe+9AAE17
GVOnline.exe+9AAE1C - EB 02 - jmp GVOnline.exe+9AAE20
GVOnline.exe+9AAE1E - 33 C0 - xor eax,eax
GVOnline.exe+9AAE20 - 5D - pop ebp
GVOnline.exe+9AAE21 - C2 0400 - ret 0004 { 4 }
//-------------------------------------------------------------------
经过调试,eax =[ecx+04]+0]+0]+...+0]
因此,esi=ecx=edi=[eax+0c] =[[eax+08]+0c] =[ecx+04]+0]+0]+...+0]+08]+0c]
,ECX再往上追了下,难度有点大,就直接Pointer scan for this address (add ecx,000002EC 之后的ECX地址)
最终:esi = [1291274]+2EC+04]+0]+...+0]+08]+0c] (背包物品信息,第N个物品 +0 N层)
物品ID = [esi+8]
物品数量 = [esi+28]
物品name := GetObjName(2, id); (Call GVOnline.exe+55D853 ,方法和Tab 选中 NPC时,由ID计算中文名称一样,基址为001219664)背包物品的数据结构及地址,在打开持有物品、露天地摊、使用物品时均有效。 二、已经解密的背包物品中文名称获取
上面的背包物品信息中已经获取了“寬鬆衫”物品的中文名称,在GVOnline.exe+55D853 - E8 38DCBEFF - call GVOnline.exe+14B490这个call中,具体分析下:GVOnline.exe+55D844 - 8D 4D FC - lea ecx,[ebp-04]
GVOnline.exe+55D847 - 51 - push ecx {参数3:堆栈地址1,作临时变量}
GVOnline.exe+55D848 - 8D 4D F8 - lea ecx,[ebp-08]
GVOnline.exe+55D84B - 51 - push ecx {参数2:堆栈地址2,作临时变量)
GVOnline.exe+55D84C - 56 - push esi {参数1: esi = 物品 ID }
GVOnline.exe+55D84D - 8D 88 843D0000 - lea ecx,[eax+00003D84] { ecx = 物品名称基址 1219664 }
GVOnline.exe+55D853 - E8 38DCBEFF - call GVOnline.exe+14B490 <------ 通用名称call . Tab选中NPC、活动场景等获取名称均从此call取得)
GVOnline.exe+55D85C - 8B 70 04 - mov esi,[eax+04]
GVOnline.exe+55D85F - 85 F6 - test esi,esi
GVOnline.exe+55D861 - 74 1D - je GVOnline.exe+55D880
GVOnline.exe+55D863 - 83 7E 18 00 - cmp dword ptr [esi+18],00 { 0 }
GVOnline.exe+55D867 - 7E 0F - jle GVOnline.exe+55D878
GVOnline.exe+55D869 - FF 76 04 - push [esi+04]
GVOnline.exe+55D86C - 8D 46 08 - lea eax,[esi+08]
GVOnline.exe+55D86F - 50 - push eax
GVOnline.exe+55D870 - E8 BBD83A00 - call GVOnline.exe+90B130 (<-----这里先提前预告下:此call为加密中文名称的解密call)
GVOnline.exe+55D875 - 83 C4 08 - add esp,08 { 8 }
GVOnline.exe+55D878 - 8B 46 0C - mov eax,[esi+0C] {[eax]=“寬鬆衫” }...//-------- 进入通用名称 call GVOnline.exe+14B490分析---------
GVOnline.exe+14B490 - 55 - push ebp
GVOnline.exe+14B491 - 8B EC - mov ebp,esp
GVOnline.exe+14B493 - 56 - push esi
GVOnline.exe+14B494 - 8B 75 08 - mov esi,[ebp+08] ----- 上层传入的参数1,物品ID
GVOnline.exe+14B497 - 57 - push edi
GVOnline.exe+14B498 - 68 1DF30100 - push 0001F31D { (0) }
GVOnline.exe+14B49D - 56 - push esi
GVOnline.exe+14B49E - 8B F9 - mov edi,ecx
GVOnline.exe+14B4A0 - E8 593F9500 - call GVOnline.exe+A9F3FE // --- ( id / 1f31d) eax = 商,edx = 余数
GVOnline.exe+14B4A5 - 69 D2 A7410000 - imul edx,edx,000041A7 { 16807 } 余数*41A7
GVOnline.exe+14B4AB - 69 C0 140B0000 - imul eax,eax,00000B14 { 2836 } 商*B14
GVOnline.exe+14B4B1 - 83 C4 08 - add esp,08 { 8 }
GVOnline.exe+14B4B4 - 2B D0 - sub edx,eax ------- edx = 余数41A7 - 商B14 ,记作HashID
GVOnline.exe+14B4B6 - 79 06 - jns GVOnline.exe+14B4BE <0?
GVOnline.exe+14B4B8 - 81 C2 FFFFFF7F - add edx,7FFFFFFF { 2147483647 } 调整下
GVOnline.exe+14B4BE - 8B 4D 10 - mov ecx,[ebp+10] --- 上层传入的参数3,存放 HashID
GVOnline.exe+14B4C1 - 8B C2 - mov eax,edx
GVOnline.exe+14B4C3 - 89 11 - mov [ecx],edx ---- 存入 HashID
GVOnline.exe+14B4C5 - 33 D2 - xor edx,edx
GVOnline.exe+14B4C7 - F7 77 08 - div [edi+08] -------EAX=HashID mod $11) >结果作为ID的Hash值,记作:HashKey [edi+8]=[基址ecx+8] =$11(哈希表条目数)
GVOnline.exe+14B4CA - 8B 45 0C - mov eax,[ebp+0C] 上层传入参数2
GVOnline.exe+14B4CD - 89 10 - mov [eax],edx -------存放 HashKey
GVOnline.exe+14B4CF - 8B 47 04 - mov eax,[edi+04] -----([基址ecx+4] = 哈希表首地址)
GVOnline.exe+14B4D2 - 85 C0 - test eax,eax
GVOnline.exe+14B4D4 - 74 1A - je GVOnline.exe+14B4F0
GVOnline.exe+14B4D6 - 8B 04 90 - mov eax,[eax+edx*4] ------- (哈希表首地址起,存有$11个条目的地址) eax=HashKey对应的条目地址
GVOnline.exe+14B4D9 - 85 C0 - test eax,eax
GVOnline.exe+14B4DB - 74 13 - je GVOnline.exe+14B4F0
GVOnline.exe+14B4DD - 8B 09 - mov ecx,[ecx] ---HashID
GVOnline.exe+14B4DF - 90 - nop
GVOnline.exe+14B4E0 - 39 48 0C - cmp [eax+0C],ecx ---与比较HashID
GVOnline.exe+14B4E3 - 75 04 - jne GVOnline.exe+14B4E9 ---不等跳,eax=[eax+08]
GVOnline.exe+14B4E5 - 39 30 - cmp [eax],esi ----相等,再比较ID是否一致
GVOnline.exe+14B4E7 - 74 09 - je GVOnline.exe+14B4F2 ---相等,找到。
GVOnline.exe+14B4E9 - 8B 40 08 - mov eax,[eax+08]
GVOnline.exe+14B4EC - 85 C0 - test eax,eax --- EAX=0? 没找到,跳出
GVOnline.exe+14B4EE - 75 F0 - jne GVOnline.exe+14B4E0
GVOnline.exe+14B4F0 - 33 C0 - xor eax,eax
GVOnline.exe+14B4F2 - 5F - pop edi
GVOnline.exe+14B4F3 - 5E - pop esi
GVOnline.exe+14B4F4 - 5D - pop ebp
GVOnline.exe+14B4F5 - C2 0C00 - ret 000C { 12 }... 整理下由ID获取中文名称的算法如下: ecx=0x1219664 (固定基址)
hashID = ((ID mod 1f31d)*41a7 - (ID div 1f31d) b14)
hashKey = hashID mod 0x11
addr = [[ecx]+haskKey*4];
while(addr)
{
  if (hashID == [addr+0c])
 {
  if(ID == [addr+0])
  {
   ItemChinese = [[addr+4]+0c]; //获取到中文名称
   return ItemChinese;
  }
 }
 addr = [addr+08] ;
}
...
物品的中文名称统一存放在一个哈希表中,哈希表中共有0x11个条目。哈希表的地址指针即为获取物品名称的基址ecx = 0x1219664 ,[+4]=哈希表地址0x0558BBA0,[+8]=条目数0x11
![]()
[哈希表地址0x0558BBA0]为0x11个条目的首地址。
由上面的通用call分析可知
hashKey即为这0x11个条目的序号,如ID=0x10,经计算hashKey = 6,所以ID为0x10的物品在第06个条目中,条目地址即为蓝框中的0x05601b94![]()
转到条目对应地址0x05601b94,由通用call分析可知,这里由一系列节点组成,每个节点长0x0c,其中:[+0]=ID,[+8]=下一个节点,[+0c]=hashID。
先判断[+0c] == haskID? ,相等再判断 ID==[+0];不相关则转到下一个节点继续判断直到相等。![]()
这是找到时的图,[+0] == 0x10(ID),hashID = 0x041a70 。[+04] =0x052458B4即为ID为0x10物品的详细信息地址。
![]()
[+4]=ID,[+8]=数量, [+0c]=068328C0 =中文名称地址
![]()
三、加密的背包物品中文名称的解密算法
根据上面获取背包物品已解密中文名称的分析,再结合背包物品数据结构,得到以下的获取背包物品内容的简易程序:(物品的objtype=2)//-------获取物品中文名称--------function GetObjName(objtype, id: integer): string;var base2: integer; objaddr: integer; objNameBase:Integer; temp: integer; name: string;begin name := ''; if objtype = 2 then // 物品 begin base2 := $001219664; //objtype = 2 的物品中文名称固定基址 objaddr := getObjAddr(id, base2); objNameBase:=objaddr ; objaddr := readmemoryint(players[0], objaddr + $C); name := readmemorystr(players[0], objaddr); log(0, Format('[base:%x] ID:[%0x] [nameAddr:%08x] name:[%s], ', [objnamebase,Id, objaddr,name])); end; result := name;end;//-------获取背包物品数据--------procedure TForm1.GetBagItems(Sender: TObject);var base: integer; tmp1, tmp2, tmp3, id, num: integer; name: string;begin base := $1291274; //背包物品基址 tmp1 := readmemoryint(players[0], base) + $2f0; while tmp1 > 0 do begin tmp2 := readmemoryint(players[0], tmp1) + 8; tmp3 := readmemoryint(players[0], tmp2)+$c; tmp3 := readmemoryint(players[0], tmp3); id := readmemoryint(players[0], tmp3 + 8); num := readmemoryint(players[0], tmp3 + $28); name := GetObjName(2, id); tmp1 := readmemoryint(players[0], tmp1); end;end; 从上图可知:只有第1个物品成功获取到了中文名称。后面的物品只有ID是正确的,中文名称均为空,中文名称的指针都相同均为:0x120BF18
进入CE,先到第1个物品“寬鬆衫”的节点地址(即上图的①处的base:48FEB1C)
![]()
[+04] = ID , [+08] = 数量 [+0c] = 中文名称地址指针0x06ADDFA8,转过去看下:![]()
![]()
确实就“宽松衫”的中文名称(utf-16)那第2个及后面的所有物品都没获取到中文名称,转到第2个物品的节点地址base:0x0493553C 看下:
![]()
可以看到[0x0493553C+0c] = 0120BF18 ,[0120BF18] = 0x0,没有中文名称。经测试,鼠标移动过背包物品后(移动到物品上时,会显示物品名称等信息),节点内容会发生变化 ,[0x0493553C+0c] 从原来的 0120BF18 变为 06815100 ,指向的内容 [06815100] = ”阿拉伯式包头巾“,可以读出中文名称来了。
![]()
![]()
如上面几个图所示,物品节点[0x0493553C+0c] = 06815100 ,为中文名称的地址。
加密中文名称的解密算法:解密思路:
1.在进入游戏打开背包后,在第2个物品的内存节点地址(设为obbj)的[+0c]地址处下写入硬断点,(物品节点地址可以参考前面的内容)
2.鼠标移动到物品上面,触发游戏解密物品名称。这样就可以断下来分析游戏解密的过程。实际加密后的中文名称需要经过二次解密过程,还是有点复杂。 对 obj+0c 地址处下硬件写断点,鼠标移到物品上面,断下:GVOnline.exe+1CB83 - 7F 08 - jg GVOnline.exe+1CB8DGVOnline.exe+1CB85 - 8B 0E - mov ecx,[esi]GVOnline.exe+1CB87 - 56 - push esiGVOnline.exe+1CB88 - 8B 01 - mov eax,[ecx]GVOnline.exe+1CB8A - FF 50 04 - call dword ptr [eax+04] //上面的是否在检查名称地址[esi+0c]是不是0? esi=obj1? 这call有点可疑GVOnline.exe+1CB8D - 89 3B - mov [ebx],edi ======》中断在此处。 edi = 物品中文名称地址 ebx = objaddr + 0c (将已经解密的中文名称写入物品数据)GVOnline.exe+1CB8F - 5F - pop edi此时堆栈如下:GVOnline.exe+1D001 - 06780B38,0493E5E0,00000006,0019FA94,(返回1)GVOnline.exe+1D13C - 00000006,0493E5DC,0493E5E4,1155BAE0,(返回2)GVOnline.exe+90B1ED - 1155BAE0,00000000,D11A1E86,116534D0,(返回3)GVOnline.exe+43CD09 - 0493E5DC,0007ED4C,116534D0,116B0838,(返回4)根据堆栈地址,在返回1、返回2中断测试,程序会一直中断停不下来,较难分析处理。当在返回3 GVOnline.exe+90B1ED 下断时,程序只在鼠标移到物品上面时才中断,这样就好分析了。GVOnline.exe+90B190 - 8D 45 E0 - lea eax,[ebp-20]GVOnline.exe+90B193 - 50 - push eaxGVOnline.exe+90B194 - 8D 7B 08 - lea edi,[ebx+08]GVOnline.exe+90B197 - 57 - push ediGVOnline.exe+90B198 - C7 45 FC 00000000 - mov [ebp-04],00000000 { 0 }GVOnline.exe+90B19F - E8 BC010000 - call GVOnline.exe+90B360 // [ebp-1c]在此 call变化,为解密重点callGVOnline.exe+90B1A4 - 8B 75 E4 - mov esi,[ebp-1C] --> esi = [ebp-1c]GVOnline.exe+90B1A7 - 33 D2 - xor edx,edxGVOnline.exe+90B1A9 - 83 C4 08 - add esp,08 { 8 }GVOnline.exe+90B1AC - 8B CE - mov ecx,esi GVOnline.exe+90B1AE - 39 55 E8 - cmp [ebp-18],edx GVOnline.exe+90B1B1 - 7E 14 - jle GVOnline.exe+90B1C7GVOnline.exe+90B1B3 - 8B C2 - mov eax,edxGVOnline.exe+90B1B5 - 83 E0 03 - and eax,03 { 3 } GVOnline.exe+90B1B8 - 42 - inc edxGVOnline.exe+90B1B9 - 8A 44 05 0C - mov al,[ebp+eax+0C] GVOnline.exe+90B1BD - 30 01 - xor [ecx],al GVOnline.exe+90B1BF - 8D 49 01 - lea ecx,[ecx+01]GVOnline.exe+90B1C2 - 3B 55 E8 - cmp edx,[ebp-18] GVOnline.exe+90B1C5 - 7C EC - jl GVOnline.exe+90B1B3GVOnline.exe+90B1C7 - 85 F6 - test esi,esiGVOnline.exe+90B1C9 - 75 04 - jne GVOnline.exe+90B1CFGVOnline.exe+90B1CB - 33 C9 - xor ecx,ecxGVOnline.exe+90B1CD - EB 14 - jmp GVOnline.exe+90B1E3GVOnline.exe+90B1CF - 8B CE - mov ecx,esiGVOnline.exe+90B1D1 - 8D 51 02 - lea edx,[ecx+02]GVOnline.exe+90B1D4 - 66 8B 01 - mov ax,[ecx]GVOnline.exe+90B1D7 - 83 C1 02 - add ecx,02 { 2 }GVOnline.exe+90B1DA - 66 85 C0 - test ax,axGVOnline.exe+90B1DD - 75 F5 - jne GVOnline.exe+90B1D4GVOnline.exe+90B1DF - 2B CA - sub ecx,edx GVOnline.exe+90B1E1 - D1 F9 - sar ecx,1 GVOnline.exe+90B1E3 - 51 - push ecxGVOnline.exe+90B1E4 - 56 - push esi [esi] = 物品中文名称GVOnline.exe+90B1E5 - 8D 4B 04 - lea ecx,[ebx+04]GVOnline.exe+90B1E8 - E8 031F71FF - call GVOnline.exe+1D0F0 //返回3 这里下断。断下来时,可以看到[esi] = 物品中文名称 //这个call执行后,物品节点地址+0c处已经是解密后中文的地址了,可以正常获取正确的中文名称了。GVOnline.exe+90B1ED - 8B 47 04 - mov eax,[edi+04]GVOnline.exe+90B1F0 - 85 C0 - test eax,eaxGVOnline.exe+90B1F2 - 74 10 - je GVOnline.exe+90B204GVOnline.exe+90B1F4 - 50 - push eax 从上面的分析可初步判断, call GVOnline.exe+90B360为解密 的重点call,下面重点分析下GVOnline.exe+90B190 - 8D 45 E0 - lea eax,[ebp-20]GVOnline.exe+90B193 - 50 - push eax // 参数2: 堆栈底(用于存放临时变量)GVOnline.exe+90B194 - 8D 7B 08 - lea edi,[ebx+08]GVOnline.exe+90B197 - 57 - push edi // 参数1: 物品基址+8 ( obj+10 即图一中的0x493554c )GVOnline.exe+90B198 - C7 45 FC 00000000 - mov [ebp-04],00000000 { 0 }GVOnline.exe+90B19F - E8 BC010000 - call GVOnline.exe+90B360 //解密call 进关键CALL看下中文名称是怎么解密出来的。GVOnline.exe+90B360 - 55 - push ebpGVOnline.exe+90B361 - 8B EC - mov ebp,espGVOnline.exe+90B363 - 51 - push ecxGVOnline.exe+90B364 - 8B 45 08 - mov eax,[ebp+08] eax = obj+10 = 0x493554c (obj=0x493553c )GVOnline.exe+90B367 - 53 - push ebxGVOnline.exe+90B368 - 56 - push esiGVOnline.exe+90B369 - 8B 75 0C - mov esi,[ebp+0C] esi= ebp-20 = 19fab4 (堆栈底部)GVOnline.exe+90B36C - 57 - push ediGVOnline.exe+90B36D - 8B 78 08 - mov edi,[eax+08] [obj+10+8] = $18GVOnline.exe+90B370 - 8B 40 04 - mov eax,[eax+04] [obj+10+4] = 04F6C2B8 (中文加密名称 encodeBytes 的地址) GVOnline.exe+90B373 - 89 45 08 - mov [ebp+08],eax [ebp+08] = 04F6C2B8GVOnline.exe+90B376 - 8D 04 7F - lea eax,[edi+edi*2] eax= edi*3=$18*3 =$48GVOnline.exe+90B379 - 99 - cdq GVOnline.exe+90B37A - 83 E2 03 - and edx,03 { 3 }GVOnline.exe+90B37D - 8D 1C 02 - lea ebx,[edx+eax] ebx = edx+eaxGVOnline.exe+90B380 - 8B 46 04 - mov eax,[esi+04] *** 返回变量result = [ebp-1c]GVOnline.exe+90B383 - C1 FB 02 - sar ebx,02 { 2 } ebx / 4 = 12GVOnline.exe+90B386 - 85 C0 - test eax,eaxGVOnline.exe+90B388 - 74 10 - je GVOnline.exe+90B39A 跳过GVOnline.exe+90B38A - 50 - push eaxGVOnline.exe+90B38B - E8 ECD10700 - call GVOnline.exe+98857CGVOnline.exe+90B390 - 83 C4 04 - add esp,04 { 4 }GVOnline.exe+90B393 - C7 46 04 00000000 - mov [esi+04],00000000 { 0 }GVOnline.exe+90B39A - 6A FF - push -01 { 255 }GVOnline.exe+90B39C - 53 - push ebxGVOnline.exe+90B39D - 8B CE - mov ecx,esiGVOnline.exe+90B39F - C7 46 0C 00000000 - mov [esi+0C],00000000 { 0 }GVOnline.exe+90B3A6 - C7 46 08 00000000 - mov [esi+08],00000000 { 0 }GVOnline.exe+90B3AD - E8 FE8D80FF - call GVOnline.exe+1141B0GVOnline.exe+90B3B2 - 8B C7 - mov eax,edi eax=edi=$18GVOnline.exe+90B3B4 - 99 - cdq GVOnline.exe+90B3B5 - 83 E2 03 - and edx,03 { 3 }GVOnline.exe+90B3B8 - 03 C2 - add eax,edxGVOnline.exe+90B3BA - C1 F8 02 - sar eax,02 { 2 } eax = $18 / 4 = 6 (中文名称数-1)GVOnline.exe+90B3BD - C7 45 0C 00000000 - mov [ebp+0C],00000000 { 0 }GVOnline.exe+90B3C4 - 89 45 FC - mov [ebp-04],eaxGVOnline.exe+90B3C7 - 85 C0 - test eax,eaxGVOnline.exe+90B3C9 - 0F8E CF000000 - jng GVOnline.exe+90B49EGVOnline.exe+90B3CF - 8B 7D 08 - mov edi,[ebp+08] edi=04F6C2B8 (加密中文名称地址)GVOnline.exe+90B3D2 - 83 C7 02 - add edi,02 { 2 } edi = edi+2GVOnline.exe+90B3D5 - 89 7D 08 - mov [ebp+08],ediGVOnline.exe+90B3D8 - BA 02000000 - mov edx,00000002 { 2 } edx = 2 每个中文2个字节?GVOnline.exe+90B3DD - 8D 49 00 - lea ecx,[ecx+00]GVOnline.exe+90B3E0 - 8A 4F FE - mov cl,[edi-02] //LOOP START 取第1个加密字符 edi-2 = 04F6C2B8GVOnline.exe+90B3E3 - 8A C1 - mov al,cl GVOnline.exe+90B3E5 - C0 E8 03 - shr al,03 { 3 } GVOnline.exe+90B3E8 - 8A E0 - mov ah,al GVOnline.exe+90B3EA - 80 E1 07 - and cl,07 { 7 } GVOnline.exe+90B3ED - C0 E4 03 - shl ah,03 { 3 } GVOnline.exe+90B3F0 - 2A E0 - sub ah,al GVOnline.exe+90B3F2 - 02 E1 - add ah,cl de0 = encodeBytes[0]>>3)*7 + encodeBytes[0]&07GVOnline.exe+90B3F4 - 8A 4F FF - mov cl,[edi-01] GVOnline.exe+90B3F7 - 8A C1 - mov al,cl GVOnline.exe+90B3F9 - C0 E8 03 - shr al,03 { 3 } GVOnline.exe+90B3FC - 8A F8 - mov bh,al GVOnline.exe+90B3FE - 80 E1 07 - and cl,07 { 7 } GVOnline.exe+90B401 - C0 E7 03 - shl bh,03 { 3 } GVOnline.exe+90B404 - 2A F8 - sub bh,al GVOnline.exe+90B406 - 02 F9 - add bh,cl de1 = encodeBytes[1]>>3)*7 + encodeBytes[1]&07GVOnline.exe+90B408 - 8A 0F - mov cl,[edi] GVOnline.exe+90B40A - 8A C1 - mov al,clGVOnline.exe+90B40C - C0 E8 03 - shr al,03 { 3 }GVOnline.exe+90B40F - 8A E8 - mov ch,alGVOnline.exe+90B411 - C0 E5 03 - shl ch,03 { 3 }GVOnline.exe+90B414 - 2A E8 - sub ch,alGVOnline.exe+90B416 - 80 E1 07 - and cl,07 { 7 }GVOnline.exe+90B419 - 02 E9 - add ch,cl de2 = encodeBytes[2]>>3)*7 + encodeBytes[2]&07GVOnline.exe+90B41B - 8A 4F 01 - mov cl,[edi+01] GVOnline.exe+90B41E - 8A C1 - mov al,clGVOnline.exe+90B420 - C0 E8 03 - shr al,03 { 3 }GVOnline.exe+90B423 - 8A D8 - mov bl,alGVOnline.exe+90B425 - C0 E3 03 - shl bl,03 { 3 }GVOnline.exe+90B428 - 2A D8 - sub bl,alGVOnline.exe+90B42A - 80 E1 07 - and cl,07 { 7 } de3 = encodeBytes[3]>>3)*7 + encodeBytes[3]&07GVOnline.exe+90B42D - 8D 7A FE - lea edi,[edx-02] 0GVOnline.exe+90B430 - 02 D9 - add bl,cl GVOnline.exe+90B432 - 85 FF - test edi,ediGVOnline.exe+90B434 - 78 6F - js GVOnline.exe+90B4A5GVOnline.exe+90B436 - 3B 7E 08 - cmp edi,[esi+08] { [esi+8]=12 }GVOnline.exe+90B439 - 7D 6A - jnl GVOnline.exe+90B4A5GVOnline.exe+90B43B - 8A CF - mov cl,bh GVOnline.exe+90B43D - C0 E9 04 - shr cl,04 { 4 } GVOnline.exe+90B440 - C0 E4 02 - shl ah,02 { 2 } de0 舍弃前2位取后6位,左移2位(如:0011 0101 => 1101 0100)GVOnline.exe+90B443 - 80 E1 03 - and cl,03 { 3 } de1 取舍前2位后的前2位,后面4位转入de2中(如:0010 1010 => 取10,后面1010转入de2处理)GVOnline.exe+90B446 - 0A CC - or cl,ah de0的后6位+de1前2位(de0...de3的8bit中的前2位均舍弃只用后6位, 前一字符的6位和后一字符的前2位组成8位,作为解密后的1个字符。有点类似BASE64的解码,4个字符解码成3个字符)GVOnline.exe+90B448 - 8B 46 04 - mov eax,[esi+04] eax = 返回地址GVOnline.exe+90B44B - 88 0C 07 - mov [edi+eax],cl 存入解密后的字符(后面还需要与物品ID进行xor解密一次)GVOnline.exe+90B44E - 8D 7A FF - lea edi,[edx-01] edi = edx(2)-- = 1GVOnline.exe+90B451 - 85 FF - test edi,ediGVOnline.exe+90B453 - 78 50 - js GVOnline.exe+90B4A5 不跳GVOnline.exe+90B455 - 3B 7E 08 - cmp edi,[esi+08] { [esi+8]=12 }GVOnline.exe+90B458 - 7D 4B - jnl GVOnline.exe+90B4A5 不跳GVOnline.exe+90B45A - 8B 46 04 - mov eax,[esi+04] GVOnline.exe+90B45D - 8A CD - mov cl,ch GVOnline.exe+90B45F - C0 E9 02 - shr cl,02 { 2 } GVOnline.exe+90B462 - 80 E1 0F - and cl,0F { 15 } GVOnline.exe+90B465 - C0 E7 04 - shl bh,04 { 4 } GVOnline.exe+90B468 - 0A CF - or cl,bh GVOnline.exe+90B46A - 88 0C 07 - mov [edi+eax],clGVOnline.exe+90B46D - 85 D2 - test edx,edxGVOnline.exe+90B46F - 78 34 - js GVOnline.exe+90B4A5 不跳GVOnline.exe+90B471 - 3B 56 08 - cmp edx,[esi+08]GVOnline.exe+90B474 - 7D 2F - jnl GVOnline.exe+90B4A5GVOnline.exe+90B476 - 8B 46 04 - mov eax,[esi+04]GVOnline.exe+90B479 - 8B 7D 0C - mov edi,[ebp+0C] GVOnline.exe+90B47C - 83 45 08 04 - add dword ptr [ebp+08],04 { 4 } GVOnline.exe+90B480 - 80 E3 3F - and bl,3F { 63 } GVOnline.exe+90B483 - C0 E5 06 - shl ch,06 { 6 } GVOnline.exe+90B486 - 0A DD - or bl,ch GVOnline.exe+90B488 - 47 - inc edi edi++ (0->1)GVOnline.exe+90B489 - 88 1C 02 - mov [edx+eax],blGVOnline.exe+90B48C - 83 C2 03 - add edx,03 { 3 } edx+=3 (2+3=5)GVOnline.exe+90B48F - 3B 7D FC - cmp edi,[ebp-04] [ebp-04] = 6GVOnline.exe+90B492 - 89 7D 0C - mov [ebp+0C],edi [ebp+0c] 为 ediGVOnline.exe+90B495 - 8B 7D 08 - mov edi,[ebp+08] GVOnline.exe+90B498 - 0F8C 42FFFFFF - jl GVOnline.exe+90B3E0 --> 循环,每次循环取4个加密数据,解密为3个存入eax,[esi+04] GVOnline.exe+90B49E - 5F - pop ediGVOnline.exe+90B49F - 5E - pop esiGVOnline.exe+90B4A0 - 5B - pop ebxGVOnline.exe+90B4A1 - 8B E5 - mov esp,ebpGVOnline.exe+90B4A3 - 5D - pop ebpGVOnline.exe+90B4A4 - C3 - ret //返回时 [ebp=1c] 存放的即为 第一次解密后的中文名称 接下来,我们再返回到上一层去看下,第二次解密过程 当在返回3 GVOnline.exe+90B1ED 下断时,程序只在鼠标移到物品上面时才中断,这样就好分析了。GVOnline.exe+90B190 - 8D 45 E0 - lea eax,[ebp-20]GVOnline.exe+90B193 - 50 - push eaxGVOnline.exe+90B194 - 8D 7B 08 - lea edi,[ebx+08]GVOnline.exe+90B197 - 57 - push ediGVOnline.exe+90B198 - C7 45 FC 00000000 - mov [ebp-04],00000000 { 0 }GVOnline.exe+90B19F - E8 BC010000 - call GVOnline.exe+90B360 // 此call即为上面分析的第1次解密call 。 GVOnline.exe+90B1A4 - 8B 75 E4 - mov esi,[ebp-1C] --> 这里 esi = [ebp-1c] 是第1次解密后的中文decode1GVOnline.exe+90B1A7 - 33 D2 - xor edx,edxGVOnline.exe+90B1A9 - 83 C4 08 - add esp,08 { 8 }GVOnline.exe+90B1AC - 8B CE - mov ecx,esi decode1 = [ecx]GVOnline.exe+90B1AE - 39 55 E8 - cmp [ebp-18],edx 不跳GVOnline.exe+90B1B1 - 7E 14 - jle GVOnline.exe+90B1C7GVOnline.exe+90B1B3 - 8B C2 - mov eax,edxGVOnline.exe+90B1B5 - 83 E0 03 - and eax,03 { 3 } eax = eax mod 3GVOnline.exe+90B1B8 - 42 - inc edx 计数GVOnline.exe+90B1B9 - 8A 44 05 0C - mov al,[ebp+eax+0C] [ebp+eax+0C]= 物品ID 0x000199C4GVOnline.exe+90B1BD - 30 01 - xor [ecx],al decode1[ecx++] xor char(ID[eax mod 3]) 第二次解密 GVOnline.exe+90B1BF - 8D 49 01 - lea ecx,[ecx+01]GVOnline.exe+90B1C2 - 3B 55 E8 - cmp edx,[ebp-18] [ebp-18]=12GVOnline.exe+90B1C5 - 7C EC - jl GVOnline.exe+90B1B3GVOnline.exe+90B1C7 - 85 F6 - test esi,esiGVOnline.exe+90B1C9 - 75 04 - jne GVOnline.exe+90B1CFGVOnline.exe+90B1CB - 33 C9 - xor ecx,ecxGVOnline.exe+90B1CD - EB 14 - jmp GVOnline.exe+90B1E3GVOnline.exe+90B1CF - 8B CE - mov ecx,esiGVOnline.exe+90B1D1 - 8D 51 02 - lea edx,[ecx+02]GVOnline.exe+90B1D4 - 66 8B 01 - mov ax,[ecx]GVOnline.exe+90B1D7 - 83 C1 02 - add ecx,02 { 2 }GVOnline.exe+90B1DA - 66 85 C0 - test ax,axGVOnline.exe+90B1DD - 75 F5 - jne GVOnline.exe+90B1D4GVOnline.exe+90B1DF - 2B CA - sub ecx,edx 计算字符数量GVOnline.exe+90B1E1 - D1 F9 - sar ecx,1 div 2 第个中文字符2字节GVOnline.exe+90B1E3 - 51 - push ecxGVOnline.exe+90B1E4 - 56 - push esiGVOnline.exe+90B1E5 - 8D 4B 04 - lea ecx,[ebx+04]GVOnline.exe+90B1E8 - E8 031F71FF - call GVOnline.exe+1D0F0 //返回3 这里下断。断下来时,可以看到[esi] = 物品中文名称 //这个call执行后,物品节点地址+0c处已经是解密后中文的地址了,可以正常获取正确的中文名称了。 可以正常获取物品名称了。 后续:上面的解密过程,再回上一层就到了:GVOnline.exe+43CCF1 - 50 - push eaxGVOnline.exe+43CCF2 - E8 5BC15300 - call GVOnline.exe+978E52GVOnline.exe+43CCF7 - 83 7B 18 00 - cmp dword ptr [ebx+18],00 { 0 } ---->判断[物品基址+18]=0?没解密:已解密GVOnline.exe+43CCFB - 7E 0F - jle GVOnline.exe+43CD0C //已解密,跳过,否则进行解密GVOnline.exe+43CCFD - FF 73 04 - push [ebx+04]GVOnline.exe+43CD00 - 8D 43 08 - lea eax,[ebx+08]GVOnline.exe+43CD03 - 50 - push eaxGVOnline.exe+43CD04 - E8 27E44C00 - call GVOnline.exe+90B130 ----->进去就是前面分析的解密callGVOnline.exe+43CD09 - 83 C4 08 - add esp,08 { 8 }GVOnline.exe+43CD0C - 8B 4F 08 - mov ecx,[edi+08] 所以只需要在通过物品ID经过通用call获取名称时,判断一下[物品节点地址+0c]是否为0,就可以判断是否中文名称解密了,没有的话,就自己解密出来中文名。或者更为简单点,就直接调用call GVOnline.exe+90B130 ----->进去就是前面分析的解密call,就可以了。
到此,完整的背包物品数组信息和物品中文名称解密及获取全部完成。
学是逆向新人,希望能向论坛各位前辈大佬学习、讨教,能和大家一起交流进步,也祝网站越办越好。(由于第一次发帖,不太懂格式、图片链接上传,如有差错请见谅) |