以封神榜爲例,(適合金山絕大部分遊戲,原理相同)
先脫殼(由於脫很簡單,不介紹了)
用IDA看下這遊戲從ws2_32導入了哪些函數..網絡遊戲通迅一般用到的是send,recv,WSASend,WSARe
cv這四個API函數.發現用到了recv,WSASend,WSARecv,遊戲中時發現並未用recv,所以有可能登陸用到
了,初步分析是遊戲過程中用WSASend和WSARecv通訊,recv用來登陸收包.
進遊戲後下斷bp WSASend,遊戲中按V(坐下),遊戲被斷下,看堆棧區:
0012F1B8 0056616A /CALL 到 WSASend 來自 GAME1_.00566164
0012F1BC 00000318 |Socket = 318
0012F1C0 03E9B07C |pBuffers = 03E9B07C
0012F1C4 00000001 |nBuffers = 1
0012F1C8 0012F1E8 |pBytesSent = 0012F1E8
0012F1CC 00000000 |Flags = 0
0012F1D0 00000000 |pOverlapped = NULL
0012F1D4 00000000 \Callback = NULL
WSASend的第二個參數buffer指向加密後的包結構,
03E9B07C 04 00 00 00 E8 0B 2E 01 DC C3 E9 03 01 00 00 00 ...?. 苊? ...
03E9B08C 00 04 00 00 00 00 00 00 E8 0B 2E 01 51 00 00 00 . ......?. Q...
觀察發現 03E9B080的地址不變,dd 012E0BE8查看發現此地址存放着好像包的內容..
012E0BE8 E7FF0004
一般遊戲函數調用流程是這樣的:
功能函數(打坐)->明文發包函數(明文包)->加密函數(密文包)->通訊函數(send等通訊函數發送密文包..)
通訊函數(recv等通訊函數收到密文包..)->解密函數(密文包)->解密明文包(解密後的明文包)..
所以012E0BE8地址存放的是密文包.再次下斷bp WSASend,按V斷下,連續兩次CRTL+F9,加密過程要
往回找(解密過程往下找);
005605B0 A1 A4F25C00 mov eax, dword ptr [5CF2A4]//F2下斷單步調試,看012E0BE8何時
生成
005605B5 53 push ebx
005605B6 83F8 02 cmp eax, 2
005605B9 55 push ebp
005605BA 0F84 CE000000 je 0056068E
005605C0 83F8 03 cmp eax, 3
005605C3 0F84 C5000000 je 0056068E
005605C9 83F8 04 cmp eax, 4
005605CC 0F84 BC000000 je 0056068E
005605D2 83F8 05 cmp eax, 5
005605D5 0F84 B3000000 je 0056068E
005605DB 83F8 06 cmp eax, 6
005605DE 0F84 AA000000 je 0056068E
005605E4 83F8 07 cmp eax, 7
005605E7 0F84 A1000000 je 0056068E
005605ED 83F8 08 cmp eax, 8
005605F0 0F84 98000000 je 0056068E
005605F6 8B6C24 10 mov ebp, dword ptr [esp+10]
005605FA 85ED test ebp, ebp
005605FC 0F84 93000000 je 00560695
00560602 8B5C24 14 mov ebx, dword ptr [esp+14]
00560606 833B 00 cmp dword ptr [ebx], 0
00560609 0F84 86000000 je 00560695
0056060F 56 push esi
00560610 57 push edi
00560611 8B7C24 14 mov edi, dword ptr [esp+14]
00560615 8D4F 0C lea ecx, dword ptr [edi+C]
00560618 E8 83640000 call 00566AA0
0056061D 8BF0 mov esi, eax
0056061F 8B03 mov eax, dword ptr [ebx]
00560621 8D4C24 18 lea ecx, dword ptr [esp+18]
00560625 6A 02 push 2
00560627 83C0 02 add eax, 2
0056062A 51 push ecx
0056062B 8BCE mov ecx, esi
0056062D 894424 20 mov dword ptr [esp+20], eax
00560631 E8 3A610000 call 00566770
00560636 8B13 mov edx, dword ptr [ebx]
00560638 8BCE mov ecx, esi
0056063A 52 push edx
0056063B 55 push ebp
0056063C E8 2F610000 call 00566770
00560641 8B8F D4020000 mov ecx, dword ptr [edi+2D4]
00560647 85C9 test ecx, ecx
00560649 75 1B jnz short 00560666
0056064B 8B4E 44 mov ecx, dword ptr [esi+44]
0056064E 8B13 mov edx, dword ptr [ebx]
00560650 8D87 D8010000 lea eax, dword ptr [edi+1D8]
00560656 83C1 02 add ecx, 2
00560659 50 push eax
0056065A 51 push ecx
0056065B 52 push edx
0056065C E8 AF700000 call 00567710 //發現經過這個CALL後,12E0BE8中的包生成,所以
這有可能是加密函數..重新在此處下斷,去掉原先斷點,F7跟進.
00560661 83C4 0C add esp, 0C
00560664 EB 16 jmp short 0056067C
00560666 8D97 D8010000 lea edx, dword ptr [edi+1D8]
0056066C 8B01 mov eax, dword ptr [ecx]
0056066E 52 push edx
0056066F 8B56 44 mov edx, dword ptr [esi+44]
00560672 83C2 02 add edx, 2
00560675 52 push edx
00560676 8B13 mov edx, dword ptr [ebx]
00560678 52 push edx
00560679 FF50 08 call dword ptr [eax+8]
0056067C 56 push esi
0056067D 8D4F 04 lea ecx, dword ptr [edi+4]
00560680 E8 4B5A0000 call 005660D0
00560685 8BCE mov ecx, esi
00560687 E8 24620000 call 005668B0
0056068C 5F pop edi
0056068D 5E pop esi
0056068E 5D pop ebp
0056068F 33C0 xor eax, eax
00560691 5B pop ebx
00560692 C2 0C00 retn 0C
00567710 8B4424 0C mov eax, dword ptr [esp+C]
00567714 8D5424 0C lea edx, dword ptr [esp+C]
00567718 52 push edx
00567719 8B08 mov ecx, dword ptr [eax]
0056771B 8B4424 0C mov eax, dword ptr [esp+C]
0056771F 894C24 10 mov dword ptr [esp+10], ecx
00567723 8B4C24 08 mov ecx, dword ptr [esp+8]
00567727 50 push eax
00567728 51 push ecx //包長
00567729 E8 82FFFFFF call 005676B0 //繼續F7跟進
005676B0 53 push ebx
005676B1 8B4424 0C mov eax, dword ptr [esp+C]//明文包地址
005676B5 56 push esi
005676B6 8B7424 0C mov esi, dword ptr [esp+C]//包長度
005676BA 57 push edi
005676BB 8B7C24 18 mov edi, dword ptr [esp+18]//加密密鑰
005676BF 8BD6 mov edx, esi
005676C1 8B0F mov ecx, dword ptr [edi]
005676C3 83E2 03 and edx, 3
005676C6 C1EE 02 shr esi, 2
005676C9 74 0D je short 005676D8
005676CB 8B18 mov ebx, dword ptr [eax]
005676CD 83C0 04 add eax, 4
005676D0 33D9 xor ebx, ecx
005676D2 4E dec esi
005676D3 8958 FC mov dword ptr [eax-4], ebx
005676D6 ^ 75 F3 jnz short 005676CB
005676D8 85D2 test edx, edx
005676DA 76 0D jbe short 005676E9
005676DC 8A18 mov bl, byte ptr [eax]
005676DE 32D9 xor bl, cl
005676E0 8818 mov byte ptr [eax], bl
005676E2 40 inc eax
005676E3 C1E9 08 shr ecx, 8
005676E6 4A dec edx
005676E7 ^ 75 F3 jnz short 005676DC
005676E9 8B07 mov eax, dword ptr [edi]
005676EB 8BC8 mov ecx, eax
005676ED C1E1 05 shl ecx, 5
005676F0 2BC8 sub ecx, eax
005676F2 B8 01000000 mov eax, 1
005676F7 81C1 05840808 add ecx, 8088405
005676FD 890F mov dword ptr [edi], ecx
005676FF 5F pop edi
00567700 5E pop esi
00567701 5B pop ebx
00567702 C3 retn
在單步調試的時候發現數據段中的數據是4字節4字節在變的..走完這段,密文包也就出來了..又因爲這段沒
調用別的什麼模塊..所以斷定這是加密函數..(希望大家學的是方法,加密往前跟,解密往後跟,,你會發現這遊
戲調用的加解密是同一個函數,只是密鑰不同,所以解密過程就不分析了.)
CString EncAndDec(CString datestr,CString key,int len) //加解密函數
{
int j,nprev,nkey,nxor;
CString strxor,nxor1;
j=0;
strxor=NULL;
for(int i=0;i<len,i++)
{
if (i<2)
{
strxor=strxor+copy(datastr,i*2+1,2);
continue;
}
nprev=(long int)((int)("0x"+copy(datastr,i*2+1,2)));
nkey=(long int)((int)("0x"+copy(key,i*2+1,2)));
j++;
if (j>3)
{
j=0;
}
nxor=nprev ^ nkey;
strxor=strxor+nxor1.Format("%x",nxor);
}
return strxor;
}
密鑰的查找:
退出遊戲,在選擇服務器前下斷:bp recv;選擇服務器後斷下:
0012F928 00566447 /CALL 到 recv 來自 GAME1_.00566445
0012F92C 00000360 |Socket = 360
0012F930 04C5983C |Buffer = 04C5983C
0012F934 00000022 |BufSize = 22 (34.)
0012F938 00000000 \Flags = 0
dd 04C5983C,ALT+F9看收到的數據:
04C5983C 22 00 20 00 D4 47 EE F9 D8 3B 99 89 F0 01 6E AC ". .訥銖?檳?n
04C5984C 62 7B 1A 75 64 97 FE C9 68 8B 22 5D AC BF 86 31 b{ ud楟蒱?]