在上一篇的跟蹤中,調試后發現二次加密的密匙其實就是一個常量008B480C,分析一下整個二次加密的過程,以下代碼均在VC6.0中運行通過,加密后數據與客戶端實際發送數據一致。
函數1 - _declspec(naked) void _stdcall getEncryptMsg(long *nIdentity, char * dest)
nIdentity - 008B480C
dest - 二次加密明文
該函數負責生成二次加密后的明文,代碼如下
注意:第13行是原來的代碼,14行是自己加的,原因如下
在實際的客戶端中,mov al, byte ptr [eax] 取的是地址為008B480C的低8位,調試的時候該值為0,有可能二次解密后的解密掩碼會存放在這里,目前還未可知;而在該代碼中008B480C的地址是不可讀的,因此這里需要將AL置0
static long nIdentity = 0x008B480C;
1
_declspec(naked) void _stdcall getEncryptMsg(long *nIdentity, char * dest)
{
2
_asm
{
3
sub esp, 8
4
push ebx
5
push ebp
6
push esi
7
push edi
8
mov edi, dword ptr [esp+0x20]
9
inc edi
10
mov dword ptr [esp+0x14], 4
11
L008:
12
mov eax, dword ptr [esp+0x1C]
13
;mov al, byte ptr [eax]
14
xor al, al
15
xor al, 0x87
16
push 0x31
17
push 0
18
mov byte ptr [esp+0x1B], al
19
call ll401A60
20
add al, 0x0A
21
push 0x13
22
push 0
23
mov byte ptr [esp+0x30], al
24
call ll401A60
25
26
mov cl, byte ptr [esp+0x30]
27
28
mov ebx, eax
29
add bl, 0x0A
30
movzx eax, bl
31
add esp, 0x10
32
mov byte ptr [edi-1], cl
33
mov byte ptr [edi+8], bl
34
xor esi, esi
35
lea ebp, dword ptr [eax-1]
36
L029:
37
movzx eax, byte ptr [esp+0x13]
38
mov edx, 0x80
39
mov ecx, esi
40
sar edx, cl
41
push ebp
42
push 0
43
test eax, edx
44
jnz L039
45
call ll401A60
46
jmp L041
47
L039:
48
call ll401A60
49
add al, bl
50
L041:
51
add al, byte ptr [esp+0x28]
52
add esp, 8
53
mov byte ptr [edi+esi], al
54
inc esi
55
cmp esi, 8
56
jl L029
57
mov edx, dword ptr [esp+0x1C]
58
mov eax, dword ptr [esp+0x14]
59
inc edx
60
add edi, 0x0A
61
dec eax
62
mov dword ptr [esp+0x1C], edx
63
mov dword ptr [esp+0x14], eax
64
jnz L008
65
pop edi
66
pop esi
67
pop ebp
68
pop ebx
69
add esp, 8
70
retn 8
71
72
}
73
}
---------------------------------------------------------------------------------------------------------
函數2 - _declspec(naked) int _cdecl _ll401A60(int a1, int a2)
該函數負責生成一個偽隨機數
_declspec(naked) int _cdecl _ll401A60(int a1, int a2)


{


_asm
{
push esi
push edi
call ll4bb903
mov esi, eax
call ll4bb903
sub esi, eax
jns L008
neg esi
L008:
mov ecx, dword ptr [esp+0xC]
mov edi, dword ptr [esp+0x10]
mov eax, esi
sub edi, ecx
cdq
inc edi
idiv edi
pop edi
pop esi
mov eax, edx
add eax, ecx
retn
}
}
---------------------------------------------------------------------------------------------------------
函數3 - _declspec(naked) int _cdecl ll4bb903()
該函數根據客戶端啟動時生成的當前時間來進行隨機數生成(這個步驟調試2個小時才出來)
long int_4D4F78 = 0x484953AE; //客戶端啟動時的當前時間

_declspec(naked) int _cdecl ll4bb903()


{

_asm
{
mov eax, dword ptr [int_4D4F78]
imul eax, eax, 0x343FD
add eax, 0x269EC3
mov dword ptr [int_4D4F78], eax
xor eax, eax
mov ax, word ptr [int_4D4F78+2]
and eax, 0x7FFF
retn
}
}
運行的Main函數如下,客戶端在啟動時執行了5次ll4bb903,因此這里也執行5次,不過服務器端也不可能知道客戶端到底什么時候啟動的,所以未必一定要執行5次,這點還沒試

void encodeTest()
{

//執行5次ll4bb903()
ll4bb903();
ll4bb903();
ll4bb903();
ll4bb903();
ll4bb903();

long * ll = (long*)0x008b480c;
ll = 0;

char dest[40];
getEncryptMsg(&nIdentity, dest);
printf("%s\n", dest);

char idest[54];
fnEncode6BitBuf(dest, idest, 40, 54);
printf("%s\n", idest);
}
以上代碼轉成JAVA代碼如下:

public class DecodeMask
{

private static int int_4D4F78 = 0x484953AE; // 系統當前時間,不包含毫秒
private static long nIdentity = 0x008B480C; // 常量


private static int ll4bb903()
{
int_4D4F78 = int_4D4F78 * 0x343FD + 0x269EC3;
int r = (int_4D4F78 >> 16) & 0x7FFF; //這里取高16位
return r;
}


private static int ll401A60(int nFrom, int nTo)
{
int nRandNum = 0;
int nRand = (ll4bb903() - ll4bb903());
if (nRand < 0)
nRand = -nRand;
nRandNum = nRand % (nTo - nFrom + 1) + nFrom;
return nRandNum;
}


private static byte[] getEncryptMsg()
{
byte[] dest = new byte[40];
int pos = 1;

for (int i = 0; i < 4; i++)
{

byte bMax = (byte) (ll401A60(0, 0x31) + 0x0A);
byte bMin = (byte) (ll401A60(0, 0x13) + 0x0A);

dest[pos - 1] = bMax;
dest[pos + 8] = bMin;


for (int j = 0; j < 8; j++)
{
int bT = 0x80 >> j;
byte _b = (byte) ll401A60(0, bMin - 1);

if ((bT & 0x87) != 0)
{
_b += bMin;
}
dest[pos + j] = (byte) (_b + bMax);
}
nIdentity++;
pos += 0x0a;
}

return dest;
}


/** *//**
* 調試: 客戶端啟動時的當前時間為 0x484953AE
* 選擇角色進入游戲時,客戶端向服務器端實際發送數據為
* #3<<<<<Jx?<<<<<<<<E`\cFo<mO@Q?A=ToC]\YE_DnGMDfQ_Q@IPIOMqLW?oPS?mD_E>dtAL!
* 該方法運行后的正確輸出應為:
* E`\cFo<mO@Q?A=ToC]\YE_DnGMDfQ_Q@IPIOMqLW?oPS?mD_E>dtAL
*/

public static void doTest()
{
// 執行5次ll4bb903()
ll4bb903();
ll4bb903();
ll4bb903();
ll4bb903();
ll4bb903();
byte[] b = getEncryptMsg();
System.out.println("二次加密明文 - [" + new String(b) + "]");
String s = PacketEncode.fnEncode6BitBuf(b);
System.out.println("二次加密密文 - [" + s + "]");
}


/** *//**
* @param args
*/

public static void main(String[] args)
{
doTest();
}

}
posted on 2008-06-07 10:20
Phrancol Yang 閱讀(707)
評論(3) 編輯 收藏 所屬分類:
反匯編