在上一篇的跟踪中,调试后发现二次加密的密匙其实就是一个常量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;
static long nIdentity = 0x008B480C; 1
 _declspec(naked) void _stdcall getEncryptMsg(long *nIdentity, char * dest)
_declspec(naked) void _stdcall getEncryptMsg(long *nIdentity, char * dest) {
{
 2
 _asm
    _asm {
{
 3 sub     esp, 8
          sub     esp, 8
 4 push    ebx
  push    ebx
 5 push    ebp
  push    ebp
 6 push    esi
  push    esi
 7 push    edi
  push    edi
 8 mov     edi, dword ptr [esp+0x20]
  mov     edi, dword ptr [esp+0x20]  
 9 inc     edi
  inc     edi                        
10 mov     dword ptr [esp+0x14], 4
  mov     dword ptr [esp+0x14], 4    
11 L008:
L008:
12 mov     eax, dword ptr [esp+0x1C]
  mov     eax, dword ptr [esp+0x1C]  
13 ;mov     al, byte ptr [eax]
  ;mov     al, byte ptr [eax]         
14 xor     al, al
  xor     al, al
15 xor     al, 0x87
  xor     al, 0x87                   
16 push    0x31
  push    0x31    
17 push    0
  push    0
18 mov     byte ptr [esp+0x1B], al
  mov     byte ptr [esp+0x1B], al    
19 call    ll401A60
  call    ll401A60                   
20 add     al, 0x0A
  add     al, 0x0A                   
21 push    0x13
  push    0x13
22 push    0
  push    0
23 mov     byte ptr [esp+0x30], al
  mov     byte ptr [esp+0x30], al    
24 call    ll401A60
  call    ll401A60                   
25
26 mov     cl, byte ptr [esp+0x30]
  mov     cl, byte ptr [esp+0x30]    
27
28 mov     ebx, eax
  mov     ebx, eax                   
29 add     bl, 0x0A
  add     bl, 0x0A                   
30 movzx   eax, bl
  movzx   eax, bl                    
31 add     esp, 0x10
  add     esp, 0x10                  
32 mov     byte ptr [edi-1], cl
  mov     byte ptr [edi-1], cl       
33 mov     byte ptr [edi+8], bl
  mov     byte ptr [edi+8], bl       
34 xor     esi, esi
  xor     esi, esi
35 lea     ebp, dword ptr [eax-1]
  lea     ebp, dword ptr [eax-1]     
36 L029:
L029:
37 movzx   eax, byte ptr [esp+0x13]
  movzx   eax, byte ptr [esp+0x13]   
38 mov     edx, 0x80
  mov     edx, 0x80                  
39 mov     ecx, esi
  mov     ecx, esi                   
40 sar     edx, cl
  sar     edx, cl                    
41 push    ebp
  push    ebp
42 push    0
  push    0
43 test    eax, edx
  test    eax, edx                   
44 jnz L039
  jnz L039
45 call    ll401A60
  call    ll401A60
46 jmp L041
  jmp L041
47 L039:
L039:
48 call    ll401A60
  call    ll401A60                   
49 add     al, bl
  add     al, bl                     
50 L041:
L041:
51 add     al, byte ptr [esp+0x28]
  add     al, byte ptr [esp+0x28]    
52 add     esp, 8
  add     esp, 8
53 mov     byte ptr [edi+esi], al
  mov     byte ptr [edi+esi], al     
54 inc     esi
  inc     esi                        
55 cmp     esi, 8
  cmp     esi, 8                     
56 jl L029
  jl L029
57 mov     edx, dword ptr [esp+0x1C]
  mov     edx, dword ptr [esp+0x1C]  
58 mov     eax, dword ptr [esp+0x14]
  mov     eax, dword ptr [esp+0x14]  
59 inc     edx
  inc     edx                        
60 add     edi, 0x0A
  add     edi, 0x0A                  
61 dec     eax
  dec     eax
62 mov     dword ptr [esp+0x1C], edx
  mov     dword ptr [esp+0x1C], edx
63 mov     dword ptr [esp+0x14], eax
  mov     dword ptr [esp+0x14], eax
64 jnz L008
  jnz L008
65 pop     edi
  pop     edi
66 pop     esi
  pop     esi
67 pop     ebp
  pop     ebp
68 pop     ebx
  pop     ebx
69 add     esp, 8
  add     esp, 8
70 retn    8
  retn    8
71
72 }
    }
73 }
} 
---------------------------------------------------------------------------------------------------------
函数2 - _declspec(naked) int _cdecl _ll401A60(int a1, int a2)
该函数负责生成一个伪随机数
 _declspec(naked) int _cdecl _ll401A60(int a1, int a2)
_declspec(naked) int _cdecl _ll401A60(int a1, int a2)


 {
{


 _asm
    _asm {
{
 push    esi
            push    esi
 push    edi
            push    edi
 call    ll4bb903
            call    ll4bb903
 mov     esi, eax
            mov     esi, eax
 call    ll4bb903
            call    ll4bb903
 sub     esi, eax
            sub     esi, eax
 jns L008
            jns L008
 neg     esi
            neg     esi
 L008:
L008:
 mov     ecx, dword ptr [esp+0xC]
            mov     ecx, dword ptr [esp+0xC]  
 mov     edi, dword ptr [esp+0x10]
            mov     edi, dword ptr [esp+0x10] 
 mov     eax, esi
            mov     eax, esi                  
 sub     edi, ecx
            sub     edi, ecx                  
 cdq
            cdq                               
 inc     edi
            inc     edi                       
 idiv    edi
            idiv    edi
 pop     edi
            pop     edi
 pop     esi
            pop     esi
 mov     eax, edx
            mov     eax, edx
 add     eax, ecx
            add     eax, ecx
 retn
            retn
 }
    }
 }
}
---------------------------------------------------------------------------------------------------------
函数3 - _declspec(naked) int _cdecl ll4bb903()
该函数根据客户端启动时生成的当前时间来进行随机数生成(这个步骤调试2个小时才出来)
 long int_4D4F78 = 0x484953AE; //客户端启动时的当前时间
long int_4D4F78 = 0x484953AE; //客户端启动时的当前时间

 _declspec(naked) int _cdecl ll4bb903()
_declspec(naked) int _cdecl ll4bb903()


 {
{

 _asm
    _asm {
{
 mov     eax, dword ptr [int_4D4F78]
        mov     eax, dword ptr [int_4D4F78]
 imul    eax, eax, 0x343FD
        imul    eax, eax, 0x343FD
 add     eax, 0x269EC3
        add     eax, 0x269EC3
 mov     dword ptr [int_4D4F78], eax
        mov     dword ptr [int_4D4F78], eax
 xor     eax, eax
        xor     eax, eax
 mov     ax, word ptr [int_4D4F78+2]
        mov     ax, word ptr [int_4D4F78+2]
 and     eax, 0x7FFF
        and     eax, 0x7FFF
 retn
        retn
 }
    }
 }
}
运行的Main函数如下,客户端在启动时执行了5次ll4bb903,因此这里也执行5次,不过服务器端也不可能知道客户端到底什么时候启动的,所以未必一定要执行5次,这点还没试

 void encodeTest()
void encodeTest() {
{

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

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

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

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

 public class DecodeMask
public class DecodeMask  {
{

 private static int int_4D4F78 = 0x484953AE; // 系统当前时间,不包含毫秒
    private static int int_4D4F78 = 0x484953AE; // 系统当前时间,不包含毫秒
 private static long nIdentity = 0x008B480C; // 常量
    private static long nIdentity = 0x008B480C; // 常量


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


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


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

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

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

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


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

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

 return dest;
        return dest;
 }
    }


 /** *//**
    /** *//**
 * 调试: 客户端启动时的当前时间为 0x484953AE
     * 调试: 客户端启动时的当前时间为 0x484953AE 
 * 选择角色进入游戏时,客户端向服务器端实际发送数据为
     * 选择角色进入游戏时,客户端向服务器端实际发送数据为 
 * #3<<<<<Jx?<<<<<<<<E`\cFo<mO@Q?A=ToC]\YE_DnGMDfQ_Q@IPIOMqLW?oPS?mD_E>dtAL!
     * #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
     * E`\cFo<mO@Q?A=ToC]\YE_DnGMDfQ_Q@IPIOMqLW?oPS?mD_E>dtAL
 */
     */

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


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

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

 }
}posted on 2008-06-07 10:20 
Phrancol Yang 阅读(722) 
评论(3)  编辑  收藏  所属分类: 
反汇编