淺談游戲輔助程序的制作
作者:風藍
0、前言
本文僅限于技術交流,文中所附數據純屬虛構,如有雷同,實在是巧合!
本文簡單地探討了一款游戲輔助程序的分析、制作方法,希望能對那些對此感興趣的朋友們有些許幫助。
本人小菜鳥一只,水平有限,說得不對的地方,權當逗各位大蝦一笑 ^_^
1、切入點
在WSASend函數上下斷,移動一下人物,游戲會向服務器發送數據封包,程序斷在0042DE13這個函數調用處!
根據棧中的返回地址,逐級返回分析相關代碼如下:
00441991 |. E8 4AC3FEFF call Client.0042DCE0
// 該函數是一個公用函數,游戲中所有的數據包都經過這個函數 加密發送
{ //加密發送數據包
0042DCE0 /$ 55 push ebp
0042DCE1 |. 8BEC mov ebp,esp
0042DCE3 |. B8 0C240000 mov eax,240C
0042DCE8 |. E8 C3852F00 call Client.007262B0 //堆棧處理
{
007262B0 /$ 51 push ecx
007262B1 |. 3D 00100000 cmp eax,1000
007262B6 |. 8D4C24 08 lea ecx,dword ptr ss:[esp+8]
007262BA |. 72 14 jb short Client.007262D0
007262BC |> 81E9 00100000 /sub ecx,1000
007262C2 |. 2D 00100000 |sub eax,1000
007262C7 |. 8501 |test dword ptr ds:[ecx],eax
007262C9 |. 3D 00100000 |cmp eax,1000
007262CE |.^ 73 EC \jnb short Client.007262BC
007262D0 |> 2BC8 sub ecx,eax
007262D2 |. 8BC4 mov eax,esp
007262D4 |. 8501 test dword ptr ds:[ecx],eax
007262D6 |. 8BE1 mov esp,ecx
007262D8 |. 8B08 mov ecx,dword ptr ds:[eax]
007262DA |. 8B40 04 mov eax,dword ptr ds:[eax+4]
007262DD |. 50 push eax
007262DE \. C3 retn
}
0042DCED |. 8B41 10 mov eax,dword ptr ds:[ecx+10]
0042DCF0 |. 53 push ebx
0042DCF1 |. 56 push esi
0042DCF2 |. 83F8 FF cmp eax,-1
0042DCF5 |. 57 push edi
0042DCF6 |. 894D FC mov dword ptr ss:[ebp-4],ecx
0042DCF9 |. 0F84 29010000 je Client.0042DE28
0042DCFF |. 8079 14 01 cmp byte ptr ds:[ecx+14],1
0042DD03 |. 0F85 1F010000 jnz Client.0042DE28
0042DD09 |. 8B5D 08 mov ebx,dword ptr ss:[ebp+8]
0042DD0C |. 66:A1 F44B2F04 mov ax,word ptr ds:[42F4BF4] // 0x03A2
0042DD12 |. B9 00080000 mov ecx,800
0042DD17 |. 8DBD F4DBFFFF lea edi,dword ptr ss:[ebp-240C]
0042DD1D |. 66:8903 mov word ptr ds:[ebx],ax
0042DD20 |. 33C0 xor eax,eax
0042DD22 |. F3:AB rep stos dword ptr es:[edi] // edi 清零
0042DD24 |. 8B45 0C mov eax,dword ptr ss:[ebp+C]
0042DD27 |. 8BF3 mov esi,ebx
0042DD29 |. 8DBD F9DBFFFF lea edi,dword ptr ss:[ebp-2407] //數據開始地址
0042DD2F |. C685 F4DBFFFF AA mov byte ptr ss:[ebp-240C],0AA //數據開始標志
0042DD36 |. 8D48 09 lea ecx,dword ptr ds:[eax+9]
0042DD39 |. C685 F5DBFFFF 55 mov byte ptr ss:[ebp-240B],55 //數據結束標志
0042DD40 |. 888D F6DBFFFF mov byte ptr ss:[ebp-240A],cl //長度低8位
0042DD46 |. 8A0D A84D2F04 mov cl,byte ptr ds:[42F4DA8]
0042DD4C |. 88AD F7DBFFFF mov byte ptr ss:[ebp-2409],ch //長度高8位
0042DD52 |. 888D F8DBFFFF mov byte ptr ss:[ebp-2408],cl // 01 ? 什么東東
0042DD58 |. 8BC8 mov ecx,eax
0042DD5A |. C745 08 00000000 mov dword ptr ss:[ebp+8],0
0042DD61 |. 8BD1 mov edx,ecx
0042DD63 |. C1E9 02 shr ecx,2
0042DD66 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi]
0042DD68 |. 8BCA mov ecx,edx
0042DD6A |. 83E1 03 and ecx,3
0042DD6D |. F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[esi]
0042DD6F |. 8D70 05 lea esi,dword ptr ds:[eax+5]
0042DD72 |. 33C0 xor eax,eax
0042DD74 |. 8D8D F4DBFFFF lea ecx,dword ptr ss:[ebp-240C]
0042DD7A |. 898435 F4DBFFFF mov dword ptr ss:[ebp+esi-240C],eax
0042DD81 |. 51 push ecx
0042DD82 |. 898435 F8DBFFFF mov dword ptr ss:[ebp+esi-2408],eax
0042DD89 |. 83C6 08 add esi,8
0042DD8C |. C68435 F4DBFFFF 55 mov byte ptr ss:[ebp+esi-240C],55
0042DD94 |. 46 inc esi
0042DD95 |. C68435 F4DBFFFF AA mov byte ptr ss:[ebp+esi-240C],0AA //數據結束標志
0042DD9D |. E8 7ED42D00 call Client.0070B220 //數據加密??
{
//加密數據包子函數
0070B220 $ 55 push ebp
0070B221 . 8BEC mov ebp,esp
0070B223 . 83C4 EC add esp,-14
0070B226 . 53 push ebx
0070B227 . 57 push edi
0070B228 . 56 push esi
0070B229 . E8 00000000 call Client.0070B22E
0070B22E $ 5B pop ebx
0070B22F . 81EB 4E154000 sub ebx,Client.0040154E
0070B235 . 837D 08 00 cmp dword ptr ss:[ebp+8],0
0070B239 . 75 0A jnz short Client.0070B245
0070B23B . B8 FEFFFFFF mov eax,-2
0070B240 . E9 D5000000 jmp Client.0070B31A
0070B245 > 8B7D 08 mov edi,dword ptr ss:[ebp+8]
0070B248 . 8A47 04 mov al,byte ptr ds:[edi+4]
0070B24B . 0AC0 or al,al
0070B24D . 75 07 jnz short Client.0070B256
0070B24F . 33C0 xor eax,eax
0070B251 . E9 C4000000 jmp Client.0070B31A
0070B256 > 8A83 CD1B4000 mov al,byte ptr ds:[ebx+401BCD]
0070B25C . 0AC0 or al,al
0070B25E . 75 0A jnz short Client.0070B26A
0070B260 . B8 FFFFFFFF mov eax,-1
0070B265 . E9 B0000000 jmp Client.0070B31A
0070B26A > 0FB757 02 movzx edx,word ptr ds:[edi+2] // 0x37 len
0070B26E . 83FA 0F cmp edx,0F
0070B271 . 73 0A jnb short Client.0070B27D
0070B273 . B8 FDFFFFFF mov eax,-3
0070B278 . E9 9D000000 jmp Client.0070B31A
0070B27D > 8B45 08 mov eax,dword ptr ss:[ebp+8] // 起始地址
0070B280 . 53 push ebx
0070B281 . 81C3 AF154000 add ebx,Client.004015AF
0070B287 . 53 push ebx
0070B288 . C3 retn
0070B289 . 68 6572653F push 3F657265
0070B28E . 48 dec eax
0070B28F . 5B pop ebx
0070B290 . 83C0 05 add eax,5 // ptr to first byte 0xb0
0070B293 . 8945 F0 mov dword ptr ss:[ebp-10],eax
0070B296 . 03C2 add eax,edx
0070B298 . 83E8 01 sub eax,1
0070B29B . 83E8 08 sub eax,8
0070B29E . 8945 EC mov dword ptr ss:[ebp-14],eax
0070B2A1 . 83EA 01 sub edx,1
0070B2A4 . 83EA 02 sub edx,2
0070B2A7 . 66:8955 F4 mov word ptr ss:[ebp-C],dx
0070B2AB . 66:8B8B F31B4000 mov cx,word ptr ds:[ebx+401BF3]
0070B2B2 . 66:894D F6 mov word ptr ss:[ebp-A],cx
0070B2B6 . 66:C1E9 03 shr cx,3
0070B2BA . 66:83E1 07 and cx,7
0070B2BE . 66:898B E71B4000 mov word ptr ds:[ebx+401BE7],cx
0070B2C5 . EB 65 jmp short Client.0070B32C
0070B2C7 > C745 FC 00000000 mov dword ptr ss:[ebp-4],0
0070B2CE . 8BB3 D31B4000 mov esi,dword ptr ds:[ebx+401BD3]
0070B2D4 . 8B7D F0 mov edi,dword ptr ss:[ebp-10]
0070B2D7 . 83C7 02 add edi,2
0070B2DA . 74 02 je short Client.0070B2DE
0070B2DC . 75 00 jnz short Client.0070B2DE
0070B2DE > 0FB755 F4 movzx edx,word ptr ss:[ebp-C]
0070B2E2 . 83EA 02 sub edx,2
0070B2E5 . EB 2C jmp short Client.0070B313
//第二次算法
0070B2E7 > 8B45 FC mov eax,dword ptr ss:[ebp-4]
0070B2EA . 83E0 1F and eax,1F
0070B2ED . 33C9 xor ecx,ecx
0070B2EF . 8A8C18 A71B4000 mov cl,byte ptr ds:[eax+ebx+401BA7] //0x0E ?
0070B2F6 . EB 03 jmp short Client.0070B2FB
0070B2F8 77 db 77 // CHAR 'w'
0070B2F9 . B2 5E mov dl,5E
0070B2FB > 80F1 01 xor cl,1
0070B2FE . 324D F6 xor cl,byte ptr ss:[ebp-A]
0070B301 . C1E1 08 shl ecx,8
0070B304 . 33C0 xor eax,eax
0070B306 . 8A07 mov al,byte ptr ds:[edi]
0070B308 . 03C8 add ecx,eax
0070B30A . 8A0431 mov al,byte ptr ds:[ecx+esi]
0070B30D . 8807 mov byte ptr ds:[edi],al
0070B30F . 47 inc edi
0070B310 . FF45 FC inc dword ptr ss:[ebp-4]
0070B313 > 3955 FC cmp dword ptr ss:[ebp-4],edx
0070B316 .^ 72 CF jb short Client.0070B2E7
0070B318 . 33C0 xor eax,eax
0070B31A > 5E pop esi
0070B31B . 5F pop edi
0070B31C . 5B pop ebx
0070B31D . C9 leave
0070B31E . C2 0400 retn 4
0070B321 DD db DD
0070B322 . BB 0000476F mov ebx,6F470000
0070B327 . 2068 65 and byte ptr ds:[eax+65],ch
0070B32A . 6C ins byte ptr es:[edi],dx
0070B32B . 6C ins byte ptr es:[edi],dx
0070B32C > 8D93 01174000 lea edx,dword ptr ds:[ebx+401701]
0070B332 . 55 push ebp
0070B333 . FFD2 call edx // 70B3E1
0070B335 . EB 00 jmp short Client.0070B337
0070B337 > 2D A8319049 sub eax,499031A8
0070B33C . 8B7D EC mov edi,dword ptr ss:[ebp-14]
0070B33F . 8907 mov dword ptr ds:[edi],eax
0070B341 . 8B83 ED1B4000 mov eax,dword ptr ds:[ebx+401BED]
0070B347 . 0FB78B F11B4000 movzx ecx,word ptr ds:[ebx+401BF1]
0070B34E . 0BC9 or ecx,ecx
0070B350 . 75 06 jnz short Client.0070B358
0070B352 . 66:B8 0000 mov ax,0
0070B356 . EB 0B jmp short Client.0070B363
0070B358 > 8D93 4F184000 lea edx,dword ptr ds:[ebx+40184F]
0070B35E . 51 push ecx
0070B35F . 51 push ecx
0070B360 . 50 push eax
0070B361 . FFD2 call edx //70B52F
{
0070B52F . 55 push ebp
0070B530 . 8BEC mov ebp,esp
0070B532 . 83C4 F8 add esp,-8
0070B535 . 53 push ebx
0070B536 . 57 push edi
0070B537 . 56 push esi
0070B538 . E8 00000000 call Client.0070B53D
0070B53D /$ 5B pop ebx
0070B53E |. 81EB 5D184000 sub ebx,Client.0040185D
0070B544 |. 66:C745 FA 0C41 mov word ptr ss:[ebp-6],410C
0070B54A |. C745 FC 00000000 mov dword ptr ss:[ebp-4],0
0070B551 |. 8B75 08 mov esi,dword ptr ss:[ebp+8]
0070B554 |. 8B4D 0C mov ecx,dword ptr ss:[ebp+C]
0070B557 |. 33C0 xor eax,eax
0070B559 |. EB 08 jmp short Client.0070B563
0070B55B |> AC /lods byte ptr ds:[esi]
0070B55C |. 66:0145 FA |add word ptr ss:[ebp-6],ax
0070B560 |. FF45 FC |inc dword ptr ss:[ebp-4]
0070B563 |> 394D FC cmp dword ptr ss:[ebp-4],ecx
0070B566 |.^ 72 F3 \jb short Client.0070B55B
0070B568 |. 8D93 11184000 lea edx,dword ptr ds:[ebx+401811]
0070B56E |. 0FB745 FA movzx eax,word ptr ss:[ebp-6]
0070B572 |. FF75 10 push dword ptr ss:[ebp+10]
0070B575 |. 50 push eax
0070B576 |. FFD2 call edx // 70B4F1
{
0070B4F1 . 55 push ebp
0070B4F2 . 8BEC mov ebp,esp
0070B4F4 . 53 push ebx
0070B4F5 . 57 push edi
0070B4F6 . 56 push esi
0070B4F7 . E8 00000000 call Client.0070B4FC
0070B4FC /$ 5B pop ebx
0070B4FD |. 81EB 1C184000 sub ebx,Client.0040181C
0070B503 |. 33C0 xor eax,eax
0070B505 |. 66:8B45 08 mov ax,word ptr ss:[ebp+8]
0070B509 |. 66:8BC8 mov cx,ax
0070B50C |. 66:C1E8 10 shr ax,10
0070B510 |. 66:83E1 FF and cx,0FFFF
0070B514 |. 66:03C1 add ax,cx
0070B517 |. 66:0345 0C add ax,word ptr ss:[ebp+C]
0070B51B |. 66:8BC8 mov cx,ax
0070B51E |. 66:C1E9 10 shr cx,10
0070B522 |. 66:03C1 add ax,cx
0070B525 |. 66:F7D0 not ax
0070B528 |. 5E pop esi
0070B529 |. 5F pop edi
0070B52A |. 5B pop ebx
0070B52B |. C9 leave
0070B52C \. C2 0800 retn 8
}
0070B578 |. 74 02 je short Client.0070B57C
0070B57A |. 75 00 jnz short Client.0070B57C
0070B57C |> 5E pop esi
0070B57D |. 5F pop edi
0070B57E |. 5B pop ebx
0070B57F |. C9 leave
0070B580 \. C2 0C00 retn 0C
}
0070B363 > 66:8947 04 mov word ptr ds:[edi+4],ax
0070B367 . 66:8B45 F6 mov ax,word ptr ss:[ebp-A]
0070B36B . 66:8947 06 mov word ptr ds:[edi+6],ax
0070B36F . 66:40 inc ax
0070B371 . 66:8983 F31B4000 mov word ptr ds:[ebx+401BF3],ax
0070B378 . 8D93 A3184000 lea edx,dword ptr ds:[ebx+4018A3]
0070B37E . 57 push edi
0070B37F . FFD2 call edx //70B583
{
0070B583 /. 55 push ebp
0070B584 |. 8BEC mov ebp,esp
0070B586 |. 53 push ebx
0070B587 |. 57 push edi
0070B588 |. 56 push esi
0070B589 |. 5E pop esi
0070B58A |. 5F pop edi
0070B58B |. 5B pop ebx
0070B58C |. C9 leave
0070B58D \. C2 0400 retn 4
}
//第一次異或運算
0070B381 . 8B75 08 mov esi,dword ptr ss:[ebp+8]
0070B384 . 0FB756 02 movzx edx,word ptr ds:[esi+2] // 長度
0070B388 . 83EA 01 sub edx,1
0070B38B . 83EA 06 sub edx,6
0070B38E . 83EA 08 sub edx,8
0070B391 . 0BD2 or edx,edx
0070B393 . 75 05 jnz short Client.0070B39A
0070B395 .^ E9 2DFFFFFF jmp Client.0070B2C7
0070B39A > 8B75 F0 mov esi,dword ptr ss:[ebp-10]
0070B39D . 83C6 06 add esi,6
0070B3A0 . 8B7D EC mov edi,dword ptr ss:[ebp-14]
0070B3A3 . C745 FC 00000000 mov dword ptr ss:[ebp-4],0
0070B3AA . C745 F8 00000000 mov dword ptr ss:[ebp-8],0
0070B3B1 . EB 24 jmp short Client.0070B3D7
0070B3B3 > 8B4D F8 mov ecx,dword ptr ss:[ebp-8]
0070B3B6 . 83F9 08 cmp ecx,8
0070B3B9 . 72 09 jb short Client.0070B3C4
0070B3BB . C745 F8 00000000 mov dword ptr ss:[ebp-8],0
0070B3C2 . 33C9 xor ecx,ecx
0070B3C4 > 8BC7 mov eax,edi
0070B3C6 . 03C1 add eax,ecx
0070B3C8 . 8A08 mov cl,byte ptr ds:[eax]
0070B3CA . 8A06 mov al,byte ptr ds:[esi]
0070B3CC . 32C1 xor al,cl
0070B3CE . 8806 mov byte ptr ds:[esi],al
0070B3D0 . 46 inc esi
0070B3D1 . FF45 FC inc dword ptr ss:[ebp-4]
0070B3D4 . FF45 F8 inc dword ptr ss:[ebp-8]
0070B3D7 > 3955 FC cmp dword ptr ss:[ebp-4],edx
0070B3DA .^ 72 D7 jb short Client.0070B3B3
0070B3DC .^ E9 E6FEFFFF jmp Client.0070B2C7
0070B3E1 . 55 push ebp
0070B3E2 . 8BEC mov ebp,esp
0070B3E4 . 83C4 FC add esp,-4
0070B3E7 . 53 push ebx
0070B3E8 . 57 push edi
0070B3E9 . 56 push esi
0070B3EA . E8 00000000 call Client.0070B3EF
0070B3EF $ 5B pop ebx
0070B3F0 . 81EB 0F174000 sub ebx,Client.0040170F
0070B3F6 . 0FB78B F31B4000 movzx ecx,word ptr ds:[ebx+401BF3]
0070B3FD . 83E1 0F and ecx,0F
0070B400 . 66:83BB F51B4000 0>cmp word ptr ds:[ebx+401BF5],0
0070B408 . 74 22 je short Client.0070B42C
0070B40A . 0FB783 F51B4000 movzx eax,word ptr ds:[ebx+401BF5]
0070B411 . 3D 00010000 cmp eax,100
0070B416 . 73 0D jnb short Client.0070B425
0070B418 . 0BC9 or ecx,ecx
0070B41A . 75 09 jnz short Client.0070B425
0070B41C . 66:C783 F51B4000 0>mov word ptr ds:[ebx+401BF5],0
0070B425 > 5E pop esi
0070B426 . 5F pop edi
0070B427 . 5B pop ebx
0070B428 . C9 leave
0070B429 . C2 0400 retn 4
0070B42C > 66:83BB E71B4000 0>cmp word ptr ds:[ebx+401BE7],0
0070B434 . 75 0D jnz short Client.0070B443
0070B436 . 8B83 E91B4000 mov eax,dword ptr ds:[ebx+401BE9]
0070B43C . 5E pop esi
0070B43D . 5F pop edi
0070B43E . 5B pop ebx
0070B43F . C9 leave
0070B440 . C2 0400 retn 4
0070B443 > 66:83BB E71B4000 0>cmp word ptr ds:[ebx+401BE7],1
0070B44B . 75 0F jnz short Client.0070B45C
0070B44D . 8B4D 08 mov ecx,dword ptr ss:[ebp+8]
0070B450 . 83C1 04 add ecx,4
0070B453 . 8B01 mov eax,dword ptr ds:[ecx]
0070B455 . 5E pop esi
0070B456 . 5F pop edi
0070B457 . 5B pop ebx
0070B458 . C9 leave
0070B459 . C2 0400 retn 4
0070B45C > 66:8B8B E71B4000 mov cx,word ptr ds:[ebx+401BE7]
0070B463 . 66:894D FE mov word ptr ss:[ebp-2],cx
0070B467 . EB 47 jmp short Client.0070B4B0
0070B469 > 8B4D 08 mov ecx,dword ptr ss:[ebp+8]
0070B46C . 60 pushad
0070B46D . 8DB3 AC174000 lea esi,dword ptr ds:[ebx+4017AC]
0070B473 . 56 push esi
0070B474 . 64:FF35 00000000 push dword ptr fs:[0]
0070B47B . 64:8925 00000000 mov dword ptr fs:[0],esp
0070B482 . 8B09 mov ecx,dword ptr ds:[ecx]
0070B484 . 8B41 04 mov eax,dword ptr ds:[ecx+4]
0070B487 . 894D 08 mov dword ptr ss:[ebp+8],ecx
0070B48A . EB 16 jmp short Client.0070B4A2
0070B48C . 8B6424 08 mov esp,dword ptr ss:[esp+8]
0070B490 . 64:8F05 00000000 pop dword ptr fs:[0]
0070B497 . 83C4 04 add esp,4
0070B49A . 61 popad
0070B49B . B8 00000000 mov eax,0
0070B4A0 . EB 0A jmp short Client.0070B4AC
0070B4A2 > 64:8F05 00000000 pop dword ptr fs:[0]
0070B4A9 . 83C4 24 add esp,24
0070B4AC > 66:FF4D FE dec word ptr ss:[ebp-2]
0070B4B0 > 66:837D FE 01 cmp word ptr ss:[ebp-2],1
0070B4B5 .^ 77 B2 ja short Client.0070B469
0070B4B7 . 5E pop esi
0070B4B8 . 5F pop edi
0070B4B9 . 5B pop ebx
0070B4BA . C9 leave
0070B4BB . C2 0400 retn 4
}
0042DDA2 |. 85C0 test eax,eax
0042DDA4 |. 74 49 je short Client.0042DDEF // JMP 發送數據
0042DDA6 |. 0FBF53 02 movsx edx,word ptr ds:[ebx+2]
0042DDAA |. B9 00010000 mov ecx,100
0042DDAF |. 33C0 xor eax,eax
0042DDB1 |. 8DBD F4FBFFFF lea edi,dword ptr ss:[ebp-40C]
0042DDB7 |. 52 push edx // /Arg3
0042DDB8 |. F3:AB rep stos dword ptr es:[edi] // |
0042DDBA |. 8D85 F4FBFFFF lea eax,dword ptr ss:[ebp-40C] // |
0042DDC0 |. 68 68688700 push Client.00876868 // |Arg2 = 00876868 ASCII "_17Encryption Error: command %d"
0042DDC5 |. 50 push eax // |Arg1
0042DDC6 |. E8 35782F00 call Client.00725600 // \Client.00725600
0042DDCB |. 83C4 0C add esp,0C
0042DDCE |. 8D8D F4FBFFFF lea ecx,dword ptr ss:[ebp-40C]
0042DDD4 |. 6A 00 push 0 // /Style = MB_OK|MB_APPLMODAL
0042DDD6 |. 6A 00 push 0 // |Title = NULL
0042DDD8 |. 51 push ecx // |Text
0042DDD9 |. FF15 40157900 call dword ptr ds:[<&USER32.GetActiveWindow>] // |[GetActiveWindow
0042DDDF |. 50 push eax // |hOwner
0042DDE0 |. FF15 44157900 call dword ptr ds:[<&USER32.MessageBoxA>] // \MessageBoxA
0042DDE6 |. 5F pop edi
0042DDE7 |. 5E pop esi
0042DDE8 |. 5B pop ebx
0042DDE9 |. 8BE5 mov esp,ebp
0042DDEB |. 5D pop ebp
0042DDEC |. C2 0800 retn 8
//>>>
0042DDEF |> 8D95 F4DBFFFF lea edx,dword ptr ss:[ebp-240C]
0042DDF5 |. 6A 00 push 0 // /Callback = NULL
0042DDF7 |. 8955 F8 mov dword ptr ss:[ebp-8],edx // |
0042DDFA |. 8B55 FC mov edx,dword ptr ss:[ebp-4] // |
0042DDFD |. 6A 00 push 0 // |pOverlapped = NULL
0042DDFF |. 8D45 08 lea eax,dword ptr ss:[ebp+8] // |
0042DE02 |. 6A 00 push 0 // |Flags = 0
0042DE04 |. 50 push eax // |pBytesSent
0042DE05 |. 8B42 10 mov eax,dword ptr ds:[edx+10] // |
0042DE08 |. 8D4D F4 lea ecx,dword ptr ss:[ebp-C] // |
0042DE0B |. 6A 01 push 1 // |nBuffers = 1
0042DE0D |. 46 inc esi // |
0042DE0E |. 51 push ecx // |pBuffers
0042DE0F |. 50 push eax // |Socket
0042DE10 |. 8975 F4 mov dword ptr ss:[ebp-C],esi // |
0042DE13 |. FF15 D0157900 call dword ptr ds:[<&WS2_32.WSASend>] // \WSASend
// 發送數據
0042DE19 |. 83F8 FF cmp eax,-1
0042DE1C |. 74 04 je short Client.0042DE22
0042DE1E |. 85C0 test eax,eax
0042DE20 |. 74 06 je short Client.0042DE28
0042DE22 |> FF15 CC157900 call dword ptr ds:[<&WS2_32.#111>] // [WSAGetLastError
0042DE28 |> 5F pop edi
0042DE29 |. 5E pop esi
0042DE2A |. 5B pop ebx
0042DE2B |. 8BE5 mov esp,ebp
0042DE2D |. 5D pop ebp
0042DE2E \. C2 0800 retn 8
}
通過分析,可知0042DCE0處為游戲的公用函數,用途是對數據包進行加密并發送。在此函數處下斷,可以攔
截到游戲發給服務器的所有數據包(而且是未加密的數據包)。
該游戲的數據封包加密算法大致過程如下,(由于輔助工具不涉及到封包的加解密運算,其算法就不仔細分析了)
/*
1.原始數據
AA 55
37 00 01 B0 01 07 00 28 00 02 3B BA 3F EF 9C 51 44 00 00 70 41 29 5D DC 44 ED 52 53 44 EF 21 B6 C3 9F 72 D8 44 01 00 00 00 BC 45 00 42 FF FF 00 00
00 00 00 00 00 00 00 00
55 AA
2.生成密鑰
AA 55
37 00 01 B0 01 07 00 28 00 02 3B BA 3F EF 9C 51 44 00 00 70 41 29 5D DC 44 ED 52 53 44 EF 21 B6 C3 9F 72 D8 44 01 00 00 00 BC 45 00 42 FF FF 0E 00
FA AB B2 B6 D9 D6 0E 00
55 AA
3.用密鑰串與字節相異或
02 ^ FA = F8
3B ^ AB = 90
AA 55
37 00 01 B0 01 07 00 28 00 F8 90 08 89 36 4A 5F 44 FA AB C2 F7 F0 8B D2 44 17 F9 E1 F2 36 F7 B8 C3 65 D9 6A F2 D8 D6 0E 00 46 EE B2 F4 26 29 0E 00
FA AB B2 B6 D9 D6 0E 00
55 AA
4. 另一次運算 查表法
AA 55
37 00 01 B0 01 06 D0 49 C5 B4 DD 20 12 C2 E7 2E 0F 43 7C 8D 4E 67 01 81 81 01 60 83 BD E4 EA 7B 35 A7 5B 44 9D 67 ED 54 C5 3E 28 66 99 8D 21 02 50
43 7C C8 30 56 CC 0E 00
55 AA
*/
2、 功能分析
如果我們想分析游戲某項功能(如使用某種武功、補紅、補藍等)的實現,可以在此函數處下斷,并在游
戲中觸發相應的動作,當游戲斷下來后,根據堆棧逐級回溯,一般就可以找到與實現該功能相關的某個函數,
并分析這個函數的傳入參數,弄清楚其工作原理后,即可模擬調用該函數,實現該功能的自動化。
下面以拾取物品為例簡單說明:
1、在游戲中丟下一個物品,(當心中斷程序時,東西被別人撿走了^_^,最好找個朋友幫你看好東西)
2、在0042DCE0 處下斷
3、拾取物品,游戲斷下來,分析下面的代碼:
0042AE90 /$ 55 push ebp
0042AE91 |. 8BEC mov ebp,esp
0042AE93 |. 81EC 000C0000 sub esp,0C00
0042AE99 |. 8BD1 mov edx,ecx
0042AE9B |. 57 push edi
0042AE9C |. B9 FE020000 mov ecx,2FE
0042AEA1 |. 33C0 xor eax,eax
0042AEA3 |. 8DBD 06F4FFFF lea edi,dword ptr ss:[ebp-BFA]
0042AEA9 |. 66:C785 00F4FFFF 0>mov word ptr ss:[ebp-C00],0
0042AEB2 |. F3:AB rep stos dword ptr es:[edi]
0042AEB4 |. 8B4A 6C mov ecx,dword ptr ds:[edx+6C]
0042AEB7 |. 6A 0E push 0E // /Arg2 = 0000000E
0042AEB9 |. 66:AB stos word ptr es:[edi] // |
0042AEBB |. 8B42 68 mov eax,dword ptr ds:[edx+68] // |
0042AEBE |. 8D95 00F4FFFF lea edx,dword ptr ss:[ebp-C00] // |
0042AEC4 |. 898D 0AF4FFFF mov dword ptr ss:[ebp-BF6],ecx // |
0042AECA |. 8B0D A827BC00 mov ecx,dword ptr ds:[BC27A8] // |
0042AED0 |. 52 push edx // |Arg1
0042AED1 |. 66:C785 02F4FFFF 0>mov word ptr ss:[ebp-BFE],0B // |
0042AEDA |. 66:C785 04F4FFFF 0>mov word ptr ss:[ebp-BFC],8 // |
0042AEE3 |. 8985 06F4FFFF mov dword ptr ss:[ebp-BFA],eax // |
0042AEE9 |. E8 F22D0000 call Client.0042DCE0 // \Client.0042DCE0
0042AEEE |. 5F pop edi
0042AEEF |. 8BE5 mov esp,ebp
0042AEF1 |. 5D pop ebp
0042AEF2 \. C3 retn
通過跟蹤0042AE90函數的傳入參數發現,ecx是一個指針,ecx+68開始處的8個字節是該物品的ID標識,
通過構造這樣的緩沖區數據,可以直接CALL 0042AE90這個函數來自動拾取物品。
然后發現一個問題,用這種方法拾取物品(在一定范圍內),游戲中人物雖然拾到了物品,但卻沒有
跑過去撿的動作,需要更妥善的解決方法才行。
3、數據結構
現在能撿物品了,但面臨的問題是:怎么才能知道游戲中何時有物品出現,并獲取該物品的ID標識?
接下來要對游戲的數據結構進行分析。
在面向對象的設計時代,很多東東也變得好分析起來了。
游戲中有很多對象,如人物、怪物、物品等,要對這些進行處理,一般會在一個定時大循環中進行。
看游戲的導入函數,發現了mss32.AIL_stop_timer和mss32.AIL_release_timer_handle函數,也許和定時期有關
然后找到游戲的大定時循環函數:
004372E0 /$ A1 6C732F04 mov eax,dword ptr ds:[42F736C]
004372E5 |. C705 ECCE8700 00401CC6 mov dword ptr ds:[87CEEC],C61C4000
004372EF |. 83F8 01 cmp eax,1
004372F2 |. 75 30 jnz short Client.00437324
004372F4 |. A1 AC6A2F04 mov eax,dword ptr ds:[42F6AAC]
004372F9 |. 85C0 test eax,eax
004372FB |. 74 13 je short Client.00437310
004372FD |. 50 push eax
004372FE |. FF15 B4167900 call dword ptr ds:[<&mss32.ss32._AIL_stop>] // mss32.AIL_stop_timer
00437304 |. A1 AC6A2F04 mov eax,dword ptr ds:[42F6AAC]
00437309 |. 50 push eax
0043730A |. FF15 B8167900 call dword ptr ds:[<&mss32.ss32._AIL_release_timer_>] // mss32.AIL_release_timer_handle
//這個循環對對象數組內的所有對象 進行遍歷 操作
00437310 |> C705 6C732F04 02000000 mov dword ptr ds:[42F736C],2
0043731A |. C705 AC6A2F04 00000000 mov dword ptr ds:[42F6AAC],0
00437324 |> 56 push esi
00437325 |. 57 push edi
00437326 |. BF FFFF0000 mov edi,0FFFF
0043732B |. BE 886C1E01 mov esi,Client.011E6C88
00437330 |. 893D 58FFB000 mov dword ptr ds:[B0FF58],edi
00437336 |> 8B06 /mov eax,dword ptr ds:[esi] //指針
00437338 |. 85C0 |test eax,eax
0043733A |. 74 3A |je short Client.00437376 //如果是零 下一個
0043733C |. 3978 0C |cmp dword ptr ds:[eax+C],edi // 0xFFFF
0043733F |. 74 35 |je short Client.00437376
00437341 |. 8B0D 84172001 |mov ecx,dword ptr ds:[1201784] //此值為零 則不進行處理
00437347 |. 85C9 |test ecx,ecx
00437349 |. 74 1C |je short Client.00437367
0043734B |. 8B0D 04ED1F01 |mov ecx,dword ptr ds:[11FED04]
00437351 |. 83B9 90000000 01 |cmp dword ptr ds:[ecx+90],1 //此值不為1 則不進行處理
00437358 |. 75 0D |jnz short Client.00437367
0043735A |. 8B48 04 |mov ecx,dword ptr ds:[eax+4] //
0043735D |. 83F9 2D |cmp ecx,2D
00437360 |. 74 14 |je short Client.00437376 //youxi人物
00437362 |. 83F9 06 |cmp ecx,6
00437365 |. 74 0F |je short Client.00437376 //靜態咚咚?
00437367 |> 6A 00 |push 0 // /Arg4 = 00000000
00437369 |. 6A 00 |push 0 // |Arg3 = 00000000
0043736B |. 6A 08 |push 8 // |Arg2 = 00000008
0043736D |. 50 |push eax // |Arg1 //指向對象的指針
0043736E |. E8 DDFCFFFF |call Client.00437050 // \Client.00437050
{
00437050 /$ 55 push ebp
00437051 |. 8BEC mov ebp,esp
00437053 |. 8B45 0C mov eax,dword ptr ss:[ebp+C] // eax 0x08
00437056 |. 56 push esi
00437057 |. 3D 16040000 cmp eax,416 // Switch (cases 0..44E)
0043705C |. 7F 77 jg short Client.004370D5
0043705E |. 3D 11040000 cmp eax,411
00437063 |. 0F8D 86000000 jge Client.004370EF
00437069 |. 83F8 0A cmp eax,0A
0043706C |. 7F 48 jg short Client.004370B6
0043706E |. 74 14 je short Client.00437084
00437070 |. 83F8 08 cmp eax,8
00437073 |. 77 48 ja short Client.004370BD
00437075 |. 33C9 xor ecx,ecx
00437077 |. 8A88 10714300 mov cl,byte ptr ds:[eax+437110] // cl = byte ptr [437118] //索引
0043707D |. FF248D 08714300 jmp dword ptr ds:[ecx*4+437108] //跳到 8 那里
00437084 |> 8B75 08 mov esi,dword ptr ss:[ebp+8] // Case A of switch 00437057
00437087 |. 8B45 10 mov eax,dword ptr ss:[ebp+10]
0043708A |. 57 push edi
0043708B |. 8B7D 14 mov edi,dword ptr ss:[ebp+14]
0043708E |. 8B16 mov edx,dword ptr ds:[esi]
00437090 |. 57 push edi
00437091 |. 50 push eax
00437092 |. 6A 0A push 0A
00437094 |. 8BCE mov ecx,esi
00437096 |. FF52 04 call dword ptr ds:[edx+4]
00437099 |. 81FF FF000000 cmp edi,0FF
0043709F |. 5F pop edi
004370A0 |. 75 5E jnz short Client.00437100
004370A2 |. 85F6 test esi,esi
004370A4 |. 74 5A je short Client.00437100
004370A6 |. 8B16 mov edx,dword ptr ds:[esi]
004370A8 |. 6A 01 push 1
004370AA |. 8BCE mov ecx,esi
004370AC |. FF12 call dword ptr ds:[edx]
004370AE |. B8 01000000 mov eax,1
004370B3 |. 5E pop esi
004370B4 |. 5D pop ebp
004370B5 |. C3 retn
004370B6 |> 3D F9030000 cmp eax,3F9
004370BB |. 74 32 je short Client.004370EF
004370BD |> 8B4D 14 mov ecx,dword ptr ss:[ebp+14] // Default case of switch 00437057
004370C0 |. 8B55 10 mov edx,dword ptr ss:[ebp+10]
004370C3 |. 51 push ecx // /Arg4
004370C4 |. 52 push edx // |Arg3
004370C5 |. 50 push eax // |Arg2
004370C6 |. 8B45 08 mov eax,dword ptr ss:[ebp+8] // |
004370C9 |. 50 push eax // |Arg1
004370CA |. E8 C1B2FFFF call Client.00432390 // \Client.00432390
004370CF |. 83C4 10 add esp,10
004370D2 |. 5E pop esi
004370D3 |. 5D pop ebp
004370D4 |. C3 retn
004370D5 |> 8D88 E7FBFFFF lea ecx,dword ptr ds:[eax-419]
004370DB |. 83F9 35 cmp ecx,35
004370DE |.^ 77 DD ja short Client.004370BD
004370E0 |. 33D2 xor edx,edx
004370E2 |. 8A91 24714300 mov dl,byte ptr ds:[ecx+437124]
004370E8 |. FF2495 1C714300 jmp dword ptr ds:[edx*4+43711C] // Cases 0,1,2,3,6,7,8,3F9,411,412,413,414,415,416,419,42F,430,43A,44D,44E of sw>
//調到這里
004370EF |> 8B75 14 mov esi,dword ptr ss:[ebp+14] // 0
004370F2 |. 8B4D 08 mov ecx,dword ptr ss:[ebp+8] // 指向對象的指針
004370F5 |. 56 push esi //
004370F6 |. 8B75 10 mov esi,dword ptr ss:[ebp+10] // 0
004370F9 |. 8B11 mov edx,dword ptr ds:[ecx] // edx 是指向這個處理對象數據的函數指針
004370FB |. 56 push esi // 0
004370FC |. 50 push eax // 8
004370FD |. FF52 04 call dword ptr ds:[edx+4] // 調用這個函數
{
ecx = 指向對象的指針
func(8,0,0)
}
00437100 |> B8 01000000 mov eax,1
00437105 |. 5E pop esi
00437106 |. 5D pop ebp
00437107 \. C3 retn
}
00437373 |. 83C4 10 |add esp,10
00437376 |> 83C6 04 |add esi,4
00437379 |. 81FE 88AC1E01 |cmp esi,Client.011EAC88
0043737F |.^ 7C B5 \jl short Client.00437336
00437381 |. A1 745A1E01 mov eax,dword ptr ds:[11E5A74]
00437386 |. 85C0 test eax,eax
00437388 |. 7E 2C jle short Client.004373B6
0043738A |. 8BF0 mov esi,eax
0043738C |> E8 9FB0FFFF /call Client.00432430
00437391 |. 85C0 |test eax,eax
00437393 |. 74 1E |je short Client.004373B3
00437395 |. 8B10 |mov edx,dword ptr ds:[eax]
00437397 |. 8B0C95 886C1E01 |mov ecx,dword ptr ds:[edx*4+11E6C88]
0043739E |. 85C9 |test ecx,ecx
004373A0 |. 74 11 |je short Client.004373B3
004373A2 |. 8B78 0C |mov edi,dword ptr ds:[eax+C]
004373A5 |. 8B11 |mov edx,dword ptr ds:[ecx]
004373A7 |. 57 |push edi
004373A8 |. 8B78 08 |mov edi,dword ptr ds:[eax+8]
004373AB |. 8B40 04 |mov eax,dword ptr ds:[eax+4]
004373AE |. 57 |push edi
004373AF |. 50 |push eax
004373B0 |. FF52 04 |call dword ptr ds:[edx+4]
004373B3 |> 4E |dec esi
004373B4 |.^ 75 D6 \jnz short Client.0043738C
004373B6 |> 5F pop edi
004373B7 |. 5E pop esi
004373B8 \. C3 retn
通過對此處代碼的分析知:對象存放在011E6C88地址開始處的一個數組內,該數組的最大值為0x1000,
接下來我們要對各種對象的數據進行分析,找出我們感興趣的數據:
設pObject為一個游戲對象指針,則*(DWORD*)(pObject+0x04)為該物體的類型,如人物是0x2D,0x2F是
物品,0x2C是怪物等等(后來發現NPC也是0x2C,但另有一個值來區別于怪物)。。。
還如*(*DWORD*)(pObject+0x10)為該物體在數組內的索引值,游戲通過一個公用函數以索引值為參數對
大多數我們感興趣的對象進行操作。。。
在對各種對象的數據結構進行分析后,下一步就相對容易了。
繼續以自動拾取物品為例:
通過對類型是0x2F的對象的數據結構進行分析,知pObject+0x68處為該物品的id,由此也可知,0042AE90
這個函數的傳入參數就是物品對象的指針。
現在我們可以對整個對象數組進行掃描,找到類型為0x2F的對象(物品),然后根據其名稱,位置等信息
用個定時器就可以實現自動撿物品了!
4、操作函數
游戲基于面向對象思想設計,對對象的操作是通過pObject指針指向的一個函數實現的,分析發現,許多動
作(如攻擊怪物、拾取物品等)的操作函數是一致的(0043BC10),通過對該函數的調用關系進行分析寫出
該函數的模擬調用函數DoObject如下:(idx是對象的索引)
void DoObject(long idx)
{
unsigned char * pPlayer = (unsigned char *)(*(long *)0x11EaC88);
(*(long *) 0xB0FF58) = idx;
long addr = 0x43BC10;
_asm
{
mov ecx,pPlayer
push 0
push 0x78
push 3
call addr
}
}
有了這個函數,很多事情就好辦多了,例如:對怪物DoObject一次是鎖定,第二次就可進行攻擊,對物體DoObject
一次,即可自動拾取物品等等。。。
現在自動拾取物品已經完美解決了。
5、自動輔助
有了上面的函數,可以用定時器實現自動搜索打怪(物理攻擊)和自動拾取物品了。。。
接下來該干什么了?對,武功、補紅藍、組隊。。。(暈了-_-)
武功的分析方法可以用與前面的一樣思路,根據發送武功數據包的函數回溯到指定的函數處。
游戲中的武功有兩種,分別存放在兩個指針數組中,好像還是指向了游戲對象數組中去的(記不大清楚了),游戲中
是通過按鍵F1-F10來實現的,這個更簡單了,對鍵盤消息下斷,然后慢慢跟,發現游戲調用武功的函數,通過對這個
函數的傳入參數跟蹤發現,該函數的傳入參數是武功在快捷欄中的索引,下面我們要對這個函數的調用進行小小的調整
使我們能夠直接從武功數組中獲取可用的武功進行調用:(將該函數的前半部分改造成可直接根據武功對象指針調用)
void __declspec(naked) DoKongFu ()
{
static unsigned long addr = 0x0050C11B;
_asm
{
push ebp
mov ebp,esp
sub esp,0x0C94
push ebx
push esi
push edi
xor ebx,ebx
mov ecx,0x2FE
xor eax,eax
lea edi,dword ptr ss:[ebp-0xC8E]
mov word ptr ss:[ebp-0xC90],bx
mov word ptr ss:[ebp-0xC92],bx
mov word ptr ss:[ebp-0xC94],bx
rep stos dword ptr es:[edi]
stos word ptr es:[edi]
mov eax,dword ptr ds:[0x1201774]
mov dword ptr ds:[eax+0x1B4],ebx
mov ecx,dword ptr ds:[0x1201774]
mov eax,dword ptr ss:[ebp+8]
mov byte ptr ds:[ecx+0x1BC],bl
mov edx,dword ptr ds:[0x1201774]
mov dword ptr ds:[edx+0x1B8],-1
jmp addr
}
}
void UseKongFu(long attr)
{
unsigned char * pKongFu =GetKongFuPtr(attr); // 根據武功ID獲取其對象指針
if(pKongFu) //指針正確
{
_asm
{
mov eax,pKongFu //武功對象指針
push eax
call DoKongFu //調用
add esp,4
}
}
}
有了這些函數,可以使用武功了,如0x92C0D是種可以讓人屁股冒煙的武功,就可以直接UseKongFu(0x92C0D)
自動補紅藍和這個的分析基本類似,物品也存在一個指針數組內,找到相應的操作函數,調用就行了,人物的
生命了、武功之類的位置相對固定,也很容易分析出來的。
組隊也類似,有個指針數組存放各個隊友,想給隊友補紅,鎖定使用相應的武功就OK了。
什么?還要自動行走???算法了吧,游戲輔助程序可不是機器人。。。
6、編制程序
有了以上的數據,再利用幾個基本的編程技術,就可以制作一款私家游戲輔助工具了:
1)注入到游戲進程:全局鉤子最簡單、安全,用WH_GETMESSAGE就行。
2)HOOK游戲:為了安全起見最好不要對游戲代碼進行HOOK。
3)創建新線程:在游戲內創建一個新線程,用個大循環來進行處理。
4)增強穩定性:新線程對游戲內部函數的直接調用,極有可能給游戲造成不穩定,用try catch補補償一下吧。
5)不要散發給別人,否則,你知道的。。。
7、更新支持
游戲經常會升級,導致以前分析過的的內存地址發生變化,需要對這些地址進行更新才行,也很簡單,用OD分
別打開兩個程序,根據舊版本地址附近的一些不變特征數據,在新版中找到相應的位置即可,常量的處理與此
類似,有些實在變化大,就用OD慢慢跟吧...