大航海时代ol台服找Call记(十二) 物品ID计算物品中文名称 (3)
在第十一篇中可知,背包中的物品名称,在没有鼠标移上去或点击前,在内存中是不存在真实的中文名称的,猜测要经过解密后才能获得。这样在实际游戏辅助中非常不实用,没法直接根据物品名称来使用、丢弃物品。
经过测试,只要打开背包鼠标移到物品上,游戏会显示物品名称等信息,然后就可以根据名称通用call获取中文名称了,只要不退出游戏,就一直可以。

图一

图二
上面第1张图为物品“阿拉伯式包头巾”(ID:0x000199c4)未解密中文名称时节点内存,其中[+0c]=0120BF18,[0120BF18]内容为0。
第2张图为鼠标移到物品上,名称解密后的节点内存。其中原来[+0c]=0120BF18, 在解密后,地址变为:064BF770,[064BF770]="阿拉伯式包頭巾"

图三
逆向解密思路:
1.在进入游戏打开背包后,在第2个物品的内存节点地址(设为obbj)的[+0c]地址处下写入硬断点,(物品节点地址可以参考第10篇的内容)
2.鼠标移动到物品上面,触发游戏解密物品名称。这样就可以断下来分析游戏解密的过程。
对 obj+0c 地址处下硬件写断点,鼠标移到物品上面,断下:
GVOnline.exe+1CB83 - 7F 08 - jg GVOnline.exe+1CB8D
GVOnline.exe+1CB85 - 8B 0E - mov ecx,[esi]
GVOnline.exe+1CB87 - 56 - push esi
GVOnline.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 = 物品中文名称地址 [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 eax
GVOnline.exe+90B194 - 8D 7B 08 - lea edi,[ebx+08]
GVOnline.exe+90B197 - 57 - push edi
GVOnline.exe+90B198 - C7 45 FC 00000000 - mov [ebp-04],00000000 { 0 }
GVOnline.exe+90B19F - E8 BC010000 - call GVOnline.exe+90B360 // [ebp-1c]在此 call变化,为解密重点call
GVOnline.exe+90B1A4 - 8B 75 E4 - mov esi,[ebp-1C] --> esi = [ebp-1c]
GVOnline.exe+90B1A7 - 33 D2 - xor edx,edx
GVOnline.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+90B1C7
GVOnline.exe+90B1B3 - 8B C2 - mov eax,edx
GVOnline.exe+90B1B5 - 83 E0 03 - and eax,03 { 3 }
GVOnline.exe+90B1B8 - 42 - inc edx
GVOnline.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+90B1B3
GVOnline.exe+90B1C7 - 85 F6 - test esi,esi
GVOnline.exe+90B1C9 - 75 04 - jne GVOnline.exe+90B1CF
GVOnline.exe+90B1CB - 33 C9 - xor ecx,ecx
GVOnline.exe+90B1CD - EB 14 - jmp GVOnline.exe+90B1E3
GVOnline.exe+90B1CF - 8B CE - mov ecx,esi
GVOnline.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,ax
GVOnline.exe+90B1DD - 75 F5 - jne GVOnline.exe+90B1D4
GVOnline.exe+90B1DF - 2B CA - sub ecx,edx
GVOnline.exe+90B1E1 - D1 F9 - sar ecx,1
GVOnline.exe+90B1E3 - 51 - push ecx
GVOnline.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,eax
GVOnline.exe+90B1F2 - 74 10 - je GVOnline.exe+90B204
GVOnline.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 ebp
GVOnline.exe+90B361 - 8B EC - mov ebp,esp
GVOnline.exe+90B363 - 51 - push ecx
GVOnline.exe+90B364 - 8B 45 08 - mov eax,[ebp+08] eax = obj+10 = 0x493554c (obj=0x493553c )
GVOnline.exe+90B367 - 53 - push ebx
GVOnline.exe+90B368 - 56 - push esi
GVOnline.exe+90B369 - 8B 75 0C - mov esi,[ebp+0C] esi= ebp-20 = 19fab4 (堆栈底部)
GVOnline.exe+90B36C - 57 - push edi
GVOnline.exe+90B36D - 8B 78 08 - mov edi,[eax+08] [obj+10+8] = $18
GVOnline.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] = 04F6C2B8
GVOnline.exe+90B376 - 8D 04 7F - lea eax,[edi+edi*2] eax= edi*3=$18*3 =$48
GVOnline.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+eax
GVOnline.exe+90B380 - 8B 46 04 - mov eax,[esi+04] *** 返回result = [ebp-1c]
GVOnline.exe+90B383 - C1 FB 02 - sar ebx,02 { 2 } ebx / 4 = 12
GVOnline.exe+90B386 - 85 C0 - test eax,eax
GVOnline.exe+90B388 - 74 10 - je GVOnline.exe+90B39A 跳过
GVOnline.exe+90B38A - 50 - push eax
GVOnline.exe+90B38B - E8 ECD10700 - call GVOnline.exe+98857C
GVOnline.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 ebx
GVOnline.exe+90B39D - 8B CE - mov ecx,esi
GVOnline.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+1141B0
GVOnline.exe+90B3B2 - 8B C7 - mov eax,edi eax=edi=$18
GVOnline.exe+90B3B4 - 99 - cdq
GVOnline.exe+90B3B5 - 83 E2 03 - and edx,03 { 3 }
GVOnline.exe+90B3B8 - 03 C2 - add eax,edx
GVOnline.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],eax
GVOnline.exe+90B3C7 - 85 C0 - test eax,eax
GVOnline.exe+90B3C9 - 0F8E CF000000 - jng GVOnline.exe+90B49E
GVOnline.exe+90B3CF - 8B 7D 08 - mov edi,[ebp+08] edi=04F6C2B8 (加密中文名称地址)
GVOnline.exe+90B3D2 - 83 C7 02 - add edi,02 { 2 } edi = edi+2
GVOnline.exe+90B3D5 - 89 7D 08 - mov [ebp+08],edi
GVOnline.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 = 04F6C2B8
GVOnline.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]&07
GVOnline.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]&07
GVOnline.exe+90B408 - 8A 0F - mov cl,[edi]
GVOnline.exe+90B40A - 8A C1 - mov al,cl
GVOnline.exe+90B40C - C0 E8 03 - shr al,03 { 3 }
GVOnline.exe+90B40F - 8A E8 - mov ch,al
GVOnline.exe+90B411 - C0 E5 03 - shl ch,03 { 3 }
GVOnline.exe+90B414 - 2A E8 - sub ch,al
GVOnline.exe+90B416 - 80 E1 07 - and cl,07 { 7 }
GVOnline.exe+90B419 - 02 E9 - add ch,cl de2 = encodeBytes[2]>>3)*7 + encodeBytes[2]&07
GVOnline.exe+90B41B - 8A 4F 01 - mov cl,[edi+01]
GVOnline.exe+90B41E - 8A C1 - mov al,cl
GVOnline.exe+90B420 - C0 E8 03 - shr al,03 { 3 }
GVOnline.exe+90B423 - 8A D8 - mov bl,al
GVOnline.exe+90B425 - C0 E3 03 - shl bl,03 { 3 }
GVOnline.exe+90B428 - 2A D8 - sub bl,al
GVOnline.exe+90B42A - 80 E1 07 - and cl,07 { 7 } de3 = encodeBytes[3]>>3)*7 + encodeBytes[3]&07
GVOnline.exe+90B42D - 8D 7A FE - lea edi,[edx-02] 0
GVOnline.exe+90B430 - 02 D9 - add bl,cl
GVOnline.exe+90B432 - 85 FF - test edi,edi
GVOnline.exe+90B434 - 78 6F - js GVOnline.exe+90B4A5
GVOnline.exe+90B436 - 3B 7E 08 - cmp edi,[esi+08] { [esi+8]=12 }
GVOnline.exe+90B439 - 7D 6A - jnl GVOnline.exe+90B4A5
GVOnline.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)-- = 1
GVOnline.exe+90B451 - 85 FF - test edi,edi
GVOnline.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],cl
GVOnline.exe+90B46D - 85 D2 - test edx,edx
GVOnline.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+90B4A5
GVOnline.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],bl
GVOnline.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] = 6
GVOnline.exe+90B492 - 89 7D 0C - mov [ebp+0C],edi [ebp+0c] 为 edi
GVOnline.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 edi
GVOnline.exe+90B49F - 5E - pop esi
GVOnline.exe+90B4A0 - 5B - pop ebx
GVOnline.exe+90B4A1 - 8B E5 - mov esp,ebp
GVOnline.exe+90B4A3 - 5D - pop ebp
GVOnline.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 eax
GVOnline.exe+90B194 - 8D 7B 08 - lea edi,[ebx+08]
GVOnline.exe+90B197 - 57 - push edi
GVOnline.exe+90B198 - C7 45 FC 00000000 - mov [ebp-04],00000000 { 0 }
GVOnline.exe+90B19F - E8 BC010000 - call GVOnline.exe+90B360 // [ebp-1c]在此 call变化,为解密重点call
GVOnline.exe+90B1A4 - 8B 75 E4 - mov esi,[ebp-1C] --> 回到这里,这是 esi = [ebp-1c] 已经是第1次解密后的中文decode1
GVOnline.exe+90B1A7 - 33 D2 - xor edx,edx
GVOnline.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+90B1C7
GVOnline.exe+90B1B3 - 8B C2 - mov eax,edx
GVOnline.exe+90B1B5 - 83 E0 03 - and eax,03 { 3 } eax = eax mod 3
GVOnline.exe+90B1B8 - 42 - inc edx 计数
GVOnline.exe+90B1B9 - 8A 44 05 0C - mov al,[ebp+eax+0C] [ebp+eax+0C]= 物品ID 0x000199C4
GVOnline.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]=12
GVOnline.exe+90B1C5 - 7C EC - jl GVOnline.exe+90B1B3
GVOnline.exe+90B1C7 - 85 F6 - test esi,esi
GVOnline.exe+90B1C9 - 75 04 - jne GVOnline.exe+90B1CF
GVOnline.exe+90B1CB - 33 C9 - xor ecx,ecx
GVOnline.exe+90B1CD - EB 14 - jmp GVOnline.exe+90B1E3
GVOnline.exe+90B1CF - 8B CE - mov ecx,esi
GVOnline.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,ax
GVOnline.exe+90B1DD - 75 F5 - jne GVOnline.exe+90B1D4
GVOnline.exe+90B1DF - 2B CA - sub ecx,edx 计算字符数量
GVOnline.exe+90B1E1 - D1 F9 - sar ecx,1 div 2 第个中文字符2字节
GVOnline.exe+90B1E3 - 51 - push ecx
GVOnline.exe+90B1E4 - 56 - push 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+43CCF1 - 50 - push eax
GVOnline.exe+43CCF2 - E8 5BC15300 - call GVOnline.exe+978E52
GVOnline.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 eax
GVOnline.exe+43CD04 - E8 27E44C00 - call GVOnline.exe+90B130 ----->进去就是前面分析的解密call
GVOnline.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,就可以了。
浙公网安备 33010602011771号