首页
社区
课程
招聘
[原创]Lesco's Keygenme 逆向分析 附注册机
发表于: 2013-1-10 16:20 6282

[原创]Lesco's Keygenme 逆向分析 附注册机

2013-1-10 16:20
6282
【文章标题】: 【原创】Lesco's Keygenme 分析 附注册机
【文章作者】: lifestill
【作者邮箱】: zhong_sf@sina.com
【软件名称】: Lesco's Keygenme
【附件下载】: kgme.zip

这个KeygenMe是得到登陆名szAcctount与PC用户名szUserName之后.
1.   调用 _CalcRetStr(szUserName.....) 得到  lpRetStr1 及 _CalcRetStr(szAccount)得到 lpRetstr2,到这是第一步骤.

2.   调用 _CalcRetstrCmb(lpRetStr1 ,lpRetStr2....)以一定的方式组合lpRetStr1 与lpRetStr2得到 lpRetStrCmb.到这是第二步骤,

3.  调用 _CalcEbx(szAccount......)计算得到Ebx这是第三步骤,

4.  在这一步骤中是根据第二步骤计算得到的lpRetStrCmb调用  _CalcCode(lpRetStrCmb.....)   
计算组合了一份加密用的机器码lpCode, 再让程序跳到lpCode这段代码中去运行进行最后   的加 密.加密的对象就是将你输入的serial转化为16进制的nSerial 加密之后得到nSerialEncrypted    ,最后将第三步骤计算得到的Ebx与nSerialEncrypted比较,相等则Crake OK!

总体大概就是这样,经过上面的过程分析,思路应该是比较清晰的...    哈哈

注:上面所提到的_Calc....()之类的函数在真正的程序中并未出现,在这里只是为是分析的方便而将一系列加密过程模块化,便于思路整理 ,便于理解 ,同时下面的讲解与注册机 也是基于这种模块的划分而进行的 . 如有不正确的地方 ,肯请看雪的各位大侠 赐教 ,

下面我们一步步来看:
  

1.首先是进攻的入口, 程序比较简单,因此大可不必通过下断找入口.
  下面这段代码主要得到登陆名(szAccount)与序列号(szSerial),转而调用_CalcKernel(....),进  行主要加密过程,上面所说的所有步骤都包含这个函数中,这个函数返回(在Eax中)的是 将nSerialEncrypted与Ebx比较的结果,往下就是根据二者是否相等 MessageBox ,这是宏观的过程
   

0040158D   > \8B7C24 14     mov edi,dword ptr ss:[esp+0x14]          ;  Case 3EA of switch 0040155C
00401591   .  6A 00         push 0x0                                 ; /lParam = 0
00401593   .  6A 00         push 0x0                                 ; |wParam = 0
00401595   .  6A 0E         push 0xE                                 ; |Message = WM_GETTEXTLENGTH
00401597   .  68 E8030000   push 0x3E8                               ; |ControlID = 3E8 (1000.)
0040159C   .  57            push edi                                 ; |hWnd
0040159D   .  FF15 B4504000 call dword ptr ds:[<&USER32.SendDlgItemM>; \SendDlgItemMessageA
004015A3   .  8BF0          mov esi,eax
004015A5   .  85F6          test esi,esi
004015A7   .  75 1A         jnz Xkgme.004015C3
004015A9   .  50            push eax                                 ; /Style
004015AA   .  50            push eax                                 ; |Title
004015AB   .  68 6C614000   push kgme.0040616C                       ; |Text = "No name entered"
004015B0   .  57            push edi                                 ; |hOwner
004015B1   .  FF15 B0504000 call dword ptr ds:[<&USER32.MessageBoxA>>; \MessageBoxA
004015B7   .  5F            pop edi
004015B8   .  5E            pop esi
004015B9   .  5D            pop ebp
004015BA   .  B8 01000000   mov eax,0x1
004015BF   .  5B            pop ebx
004015C0   .  C2 1000       retn 0x10
004015C3   >  A1 C0664000   mov eax,dword ptr ds:[0x4066C0]
004015C8   .  8B2D 5C504000 mov ebp,dword ptr ds:[<&KERNEL32.HeapAll>;  ntdll.RtlAllocateHeap
004015CE   .  46            inc esi
004015CF   .  56            push esi                                 ; /HeapSize
004015D0   .  6A 08         push 0x8                                 ; |Flags = HEAP_ZERO_MEMORY
004015D2   .  50            push eax                                 ; |hHeap => 00290000
004015D3   .  FFD5          call ebp                                 ; \HeapAlloc
004015D5   .  8BD8          mov ebx,eax
004015D7   .  56            push esi                                 ; /Count
004015D8   .  53            push ebx                                 ; |Buffer
004015D9   .  68 E8030000   push 0x3E8                               ; |ControlID = 3E8 (1000.)
004015DE   .  57            push edi                                 ; |hWnd
004015DF   .  FF15 A8504000 call dword ptr ds:[<&USER32.GetDlgItemTe>; \GetDlgItemText()      得到登陆名szAccount
004015E5   .  6A 00         push 0x0                                 ; /lParam = 0
004015E7   .  6A 00         push 0x0                                 ; |wParam = 0
004015E9   .  6A 0E         push 0xE                                 ; |Message = WM_GETTEXTLENGTH
004015EB   .  68 E9030000   push 0x3E9                               ; |ControlID = 3E9 (1001.)
004015F0   .  57            push edi                                 ; |hWnd
004015F1   .  FF15 B4504000 call dword ptr ds:[<&USER32.SendDlgItemM>; \SendDlgItemMessageA
004015F7   .  8BF0          mov esi,eax
004015F9   .  85F6          test esi,esi
004015FB   .  75 1A         jnz Xkgme.00401617
004015FD   .  50            push eax                                 ; /Style
004015FE   .  50            push eax                                 ; |Title
004015FF   .  68 58614000   push kgme.00406158                       ; |Text = "No serial entered"
00401604   .  57            push edi                                 ; |hOwner
00401605   .  FF15 B0504000 call dword ptr ds:[<&USER32.MessageBoxA>>; \MessageBoxA
0040160B   .  5F            pop edi
0040160C   .  5E            pop esi
0040160D   .  5D            pop ebp
0040160E   .  B8 01000000   mov eax,0x1
00401613   .  5B            pop ebx
00401614   .  C2 1000       retn 0x10
00401617   >  8B0D C0664000 mov ecx,dword ptr ds:[0x4066C0]
0040161D   .  46            inc esi
0040161E   .  56            push esi
0040161F   .  6A 08         push 0x8
00401621   .  51            push ecx
00401622   .  FFD5          call ebp
00401624   .  8BE8          mov ebp,eax
00401626   .  56            push esi                                 ; /Count
00401627   .  55            push ebp                                 ; |Buffer
00401628   .  68 E9030000   push 0x3E9                               ; |ControlID = 3E9 (1001.)
0040162D   .  57            push edi                                 ; |hWnd
0040162E   .  FF15 A8504000 call dword ptr ds:[<&USER32.GetDlgItemTe>; \GetDlgItemText()  得到序列号szSerial
00401634   .  55            push ebp                                 ;  --------------------------------------------------------
00401635   .  53            push ebx
00401636   .  E8 A5FCFFFF   call kgme.004012E0                       ;  _CalcKernel(AcctBuf ,PswBuf)所有的加密处理都在这里进行
0040163B   .  83C4 08       add esp,0x8                              ;  eax返回的是上面说的nSerialEncrypted与Ebx的比较结果,相同则非0
0040163E   .  84C0          test al,al                               ;  ----这里测试比较结果,al = 0则wrong,
00401640   .  74 0E         je Xkgme.00401650                        ;  可见,爆破是相当简单的
00401642   .  6A 40         push 0x40
00401644   .  68 50614000   push kgme.00406150                       ;  ASCII "Great!"
00401649   .  68 F4604000   push kgme.004060F4                       ;  ASCII "Congratulations! You made it! I hope you didn't patch me!
Now write a keygen and a tutorial"
0040164E   .  EB 0C         jmp Xkgme.0040165C
00401650   >  6A 10         push 0x10
00401652   .  68 EC604000   push kgme.004060EC                       ;  ASCII "Wrong"
00401657   .  68 CC604000   push kgme.004060CC                       ;  ASCII "No, that's not it. Try again"
0040165C   >  57            push edi                                 ; |hOwner
0040165D   .  FF15 B0504000 call dword ptr ds:[<&USER32.MessageBoxA>>; \MessageBoxA

2.上面的都不是重点,这时要做什么应该很清楚吧,没错, F7跟进_CalcKernel(.....),因为这个函数比较长,我们模块来看它,模块划分是基于上述步骤:

2.1.这段主要是上述步骤的第一步 ,GetUserName()得到 用户名(szUserName),  接着调用_CalcRetStr(szUserName..)计算得到一个szUserName返回字符串lpRetStr1 ,及_CalcRetStr(szAccount....)计算得到一个szAccount返回字符串lpRetStr2.    上代码

004012E0  /$  81EC 14010000 sub esp,0x114
004012E6  |.  53            push ebx                                 ;  ebx = AcctBuf
004012E7  |.  55            push ebp                                 ;  ebp = PswBuf
004012E8  |.  56            push esi                                 ;  esi = nPswLen
004012E9  |.  8D4424 0C     lea eax,dword ptr ss:[esp+0xC]
004012ED  |.  57            push edi
004012EE  |.  8D4C24 24     lea ecx,dword ptr ss:[esp+0x24]
004012F2  |.  50            push eax                                 ; /pBufCount
004012F3  |.  51            push ecx                                 ; |Buffer
004012F4  |.  C74424 18 000>mov dword ptr ss:[esp+0x18],0x100        ; |
004012FC  |.  FF15 00504000 call dword ptr ds:[<&ADVAPI32.GetUserNam>; \GetUserName() 得到szUserName
00401302  |.  85C0          test eax,eax
00401304  |.  75 37         jnz Xkgme.0040133D
00401306  |.  BF A8604000   mov edi,kgme.004060A8                    ;  ASCII "your username is definitly too long"
0040130B  |.  83C9 FF       or ecx,0xFFFFFFFF
0040130E  |.  F2:AE         repne scas byte ptr es:[edi]
00401310  |.  F7D1          not ecx
00401312  |.  2BF9          sub edi,ecx
00401314  |.  8D5424 24     lea edx,dword ptr ss:[esp+0x24]
00401318  |.  8BC1          mov eax,ecx
0040131A  |.  8BF7          mov esi,edi
0040131C  |.  8BFA          mov edi,edx
0040131E  |.  C1E9 02       shr ecx,0x2
00401321  |.  F3:A5         rep movs dword ptr es:[edi],dword ptr ds>
00401323  |.  8BC8          mov ecx,eax
00401325  |.  33C0          xor eax,eax
00401327  |.  83E1 03       and ecx,0x3
0040132A  |.  F3:A4         rep movs byte ptr es:[edi],byte ptr ds:[>
0040132C  |.  8D7C24 24     lea edi,dword ptr ss:[esp+0x24]
00401330  |.  83C9 FF       or ecx,0xFFFFFFFF
00401333  |.  F2:AE         repne scas byte ptr es:[edi]
00401335  |.  F7D1          not ecx
00401337  |.  894C24 10     mov dword ptr ss:[esp+0x10],ecx
0040133B  |.  EB 04         jmp Xkgme.00401341
0040133D  |>  8B4C24 10     mov ecx,dword ptr ss:[esp+0x10]
00401341  |>  49            dec ecx
00401342  |.  51            push ecx                                 ;  ecx = UserNameLen
00401343  |.  8D4C24 28     lea ecx,dword ptr ss:[esp+0x28]
00401347  |.  51            push ecx                                 ;  ecx = UserNameBuf
00401348  |.  E8 13040000   call kgme.00401760                       ;  _SubCalcProc1(szUserName ,UserNameLen)返回字符串lpRetStr1
0040134D  |.  8BAC24 300100>mov ebp,dword ptr ss:[esp+0x130]
00401354  |.  8BF0          mov esi,eax                              ;  esi = lpRetStr1
00401356  |.  8BFD          mov edi,ebp                              ;  edi = szAccount
00401358  |.  83C9 FF       or ecx,0xFFFFFFFF
0040135B  |.  33C0          xor eax,eax
0040135D  |.  F2:AE         repne scas byte ptr es:[edi]
0040135F  |.  F7D1          not ecx
00401361  |.  49            dec ecx
00401362  |.  51            push ecx
00401363  |.  55            push ebp
00401364  |.  E8 F7030000   call kgme.00401760                       ;  _CalcRetStr (szAccount,nAcctLen)返回字符串lpRetStr2
00401369  |.  894424 28     mov dword ptr ss:[esp+0x28],eax

2.1.1.趁热打铁,  我们来分析下_CalcRetStr(....)过程, F7跟进.....
   

0040175E      90            nop
0040175F      90            nop                                      ;  _CalcRetStr (szBuf ,szBufLen)
00401760  /$  55            push ebp                                 ;  {
00401761  |.  8B6C24 0C     mov ebp,dword ptr ss:[esp+0xC]           ;         ebx =szBuf
00401765  |.  56            push esi
00401766  |.  8D442D 01     lea eax,dword ptr ss:[ebp+ebp+0x1]
0040176A  |.  50            push eax
0040176B  |.  E8 1D030000   call kgme.00401A8D                       ;         lpRetStr =  Malloc (nSize)
00401770  |.  83C4 04       add esp,0x4
00401773  |.  33C9          xor ecx,ecx
00401775  |.  33D2          xor edx,edx
00401777  |.  8BF0          mov esi,eax                              ;         esi = lpRetStr
00401779  |.  85ED          test ebp,ebp
0040177B  |.  76 3A         jbe Xkgme.004017B7
0040177D  |.  57            push edi
0040177E  |.  8B7C24 10     mov edi,dword ptr ss:[esp+0x10]          ;          edi = szBuf       edx = ecx = Counter = 0 开始
00401782  |>  8A0439        /mov al,byte ptr ds:[ecx+edi]            ;      while (ecx < nBufLen)
00401785  |.  83C2 02       |add edx,0x2                             ;      {
00401788  |.  C1F8 04       |sar eax,0x4
0040178B  |.  83E0 0F       |and eax,0xF                             ;            eax = Byte szBuf[ecx] 的高4位
0040178E  |.  8A80 F0504000 |mov al,byte ptr ds:[eax+0x4050F0]       ;           以eax 作下标 得: al = byte RandStr[eax]
00401794  |.  884416 FE     |mov byte ptr ds:[esi+edx-0x2],al        ;           lpRetStr[edx-2] = al
00401798  |.  8A0439        |mov al,byte ptr ds:[ecx+edi]
0040179B  |.  83E0 0F       |and eax,0xF                             ;           eax = Byte UserNameBuf[ecx] 的低4位
0040179E  |.  41            |inc ecx
0040179F  |.  3BCD          |cmp ecx,ebp
004017A1  |.  8A80 F0504000 |mov al,byte ptr ds:[eax+0x4050F0]       ;           al = RandStr[eax];
004017A7  |.  884416 FF     |mov byte ptr ds:[esi+edx-0x1],al        ;          lpRetStr[edx-1] = al
004017AB  |.^ 72 D5         \jb Xkgme.00401782                       ;      }
004017AD  |.  C60432 00     mov byte ptr ds:[edx+esi],0x0            ;  字符串末尾写入0
004017B1  |.  8BC6          mov eax,esi
004017B3  |.  5F            pop edi
004017B4  |.  5E            pop esi
004017B5  |.  5D            pop ebp
004017B6  |.  C3            retn                                     ;  }

同时给出 对应的C语言源码吧,方便对应 :
代码中的  szRand1 是程序中全局的一份字符串 "6Ghd3iHRaSkL,;-Z";

char* _CalcRetstr(
        char*  szBuf,
        int    nBufLen
        )
{
        char szTmp;
        char* lpBufRet = new char[nBufLen*2+1];
        for (int i = 0 ;i < nBufLen ;i++)
        {
                szTmp = (szBuf[i] >> 4) & 0xF;
                szTmp = szRand1[szTmp];
                lpBufRet[i*2] = szTmp;

                szTmp = szBuf[i] & 0xF;
                szTmp = szRand1[szTmp];
                lpBufRet[i*2+1] = szTmp;
        }

        lpBufRet[nBufLen*2] = 0;
        return lpBufRet;
}

2.2  我们再往下看吧, 接下来的这部分当然就是上述步骤的第2步骤了,这部分调用  _CalcRetstrCmb()来按一定规则来组合第1步骤得到的2份返回字符串(lpRetStr1 ,lpRetStr2) 来得到 第3份数据  lpRetStCmb, 好,上代码

0040136D  |.  8BF8          mov edi,eax
0040136F  |.  83C9 FF       or ecx,0xFFFFFFFF
00401372  |.  33C0          xor eax,eax
00401374  |.  83C4 10       add esp,0x10
00401377  |.  F2:AE         repne scas byte ptr es:[edi]
00401379  |.  F7D1          not ecx
0040137B  |.  49            dec ecx
0040137C  |.  8BFE          mov edi,esi
0040137E  |.  8BD1          mov edx,ecx
00401380  |.  83C9 FF       or ecx,0xFFFFFFFF
00401383  |.  F2:AE         repne scas byte ptr es:[edi]
00401385  |.  F7D1          not ecx
00401387  |.  49            dec ecx
00401388  |.  03D1          add edx,ecx                              ;  edx = PNewAddrRet1Len + PNewAddrRet2Len2
0040138A  |.  895424 20     mov dword ptr ss:[esp+0x20],edx
0040138E  |.  52            push edx                                 ; /dwBytes
0040138F  |.  8B15 C0664000 mov edx,dword ptr ds:[0x4066C0]          ; |
00401395  |.  6A 40         push 0x40                                ; |dwFlags = 40
00401397  |.  52            push edx                                 ; |hHeap => 00290000
00401398  |.  FF15 5C504000 call dword ptr ds:[<&KERNEL32.HeapAlloc>>; \RtlAllocateHeap
0040139E  |.  8BD0          mov edx,eax                              ;  edx = lpRetStrCmb
004013A0  |.  8BFE          mov edi,esi
004013A2  |.  83C9 FF       or ecx,0xFFFFFFFF
004013A5  |.  33C0          xor eax,eax
004013A7  |.  33DB          xor ebx,ebx
004013A9  |.  895424 14     mov dword ptr ss:[esp+0x14],edx
004013AD  |.  F2:AE         repne scas byte ptr es:[edi]
004013AF  |.  F7D1          not ecx
004013B1  |.  49            dec ecx
004013B2  |.  74 39         je Xkgme.004013ED                        ;  这个循环根据lpRetStr1 填写新分配的lpRetStrCmb前部分
004013B4  |.  8BFE          mov edi,esi                              ;  edi = esi = lpRetStr1
004013B6  |.  8BC2          mov eax,edx                              ;  eax = edx = lpRetStrCmb
004013B8  |.  2BF8          sub edi,eax                              ;  edi = lpRetStr1 - lpRetStrCmb
004013BA  |.  897C24 1C     mov dword ptr ss:[esp+0x1C],edi
004013BE  |.  EB 04         jmp Xkgme.004013C4                       ;  while(ebx < lpRetStr1Len)
004013C0  |>  8B7C24 1C     /mov edi,dword ptr ss:[esp+0x1C]         ;  {
004013C4  |>  8A0C17         mov cl,byte ptr ds:[edi+edx]            ;     cl = lpRetStr1[i1]
004013C7  |.  33C0          |xor eax,eax
004013C9  |>  3888 C0504000 |/cmp byte ptr ds:[eax+0x4050C0],cl      ;     while( szRand[eax] != cl)
004013CF  |.  74 06         ||je Xkgme.004013D7                      ;     {
004013D1  |.  40            ||inc eax                                ;          eax++
004013D2  |.  83F8 10       ||cmp eax,0x10                           ;          if (eax >= 0x10) Break;
004013D5  |.^ 72 F2         |\jb Xkgme.004013C9                      ;     }
004013D7  |>  34 23         |xor al,0x23                             ;     最终下标 al ^= 0x23
004013D9      43            inc ebx
004013DA      8802          mov byte ptr ds:[edx],al                 ;     lpRetStrCmb[i2] = al
004013DC      8BFE          mov edi,esi
004013DE      83C9 FF       or ecx,0xFFFFFFFF
004013E1      33C0          xor eax,eax
004013E3      42            inc edx                                  ;     edx++     ebx++
004013E4  |.  F2:AE         |repne scas byte ptr es:[edi]
004013E6  |.  F7D1          |not ecx
004013E8  |.  49            |dec ecx
004013E9  |.  3BD9          |cmp ebx,ecx
004013EB  |.^ 72 D3         \jb Xkgme.004013C0                       ;  }
004013ED  |>  8B7424 18     mov esi,dword ptr ss:[esp+0x18]          ;  esi = lpRetStr2
004013F1  |.  83C9 FF       or ecx,0xFFFFFFFF
004013F4  |.  8BFE          mov edi,esi
004013F6  |.  33C0          xor eax,eax
004013F8  |.  33D2          xor edx,edx
004013FA  |.  F2:AE         repne scas byte ptr es:[edi]
004013FC  |.  F7D1          not ecx
004013FE  |.  49            dec ecx
004013FF  |.  74 2F         je Xkgme.00401430                        ;  这个循环根据lpRetStr2 填写新分配的lpRetStrCmb后部分
00401401  |.  8B4424 14     mov eax,dword ptr ss:[esp+0x14]          ;  eax = lpRetStrCmb
00401405  |.  03D8          add ebx,eax                              ;  ebx = lpRetStrCmb+ lpRetStr1Len
00401407  |>  8A0C32        /mov cl,byte ptr ds:[edx+esi]            ;  while(edx < PNewAddrRet2Len){
0040140A  |.  33C0          |xor eax,eax                             ;       cl = PNewAddrRet2[edx]
0040140C  |>  3888 C0504000 |/cmp byte ptr ds:[eax+0x4050C0],cl      ;       while (cl != RandStr2[eax])
00401412  |.  74 06         ||je Xkgme.0040141A                      ;       {
00401414  |.  40            ||inc eax                                ;         eax ++;
00401415  |.  83F8 10       ||cmp eax,0x10                           ;         if (eax >= 0x10)   Break;
00401418  |.^ 72 F2         |\jb Xkgme.0040140C                      ;       }
0040141A  |>  34 23         |xor al,0x23                             ;       最终下标 al ^= 0x23
0040141C  |.  8BFE          |mov edi,esi
0040141E  |.  8803          |mov byte ptr ds:[ebx],al                ;       lpRetStrCmb[PNewAddrRet1Len + i] = al
00401420  |.  43            |inc ebx
00401421  |.  83C9 FF       |or ecx,0xFFFFFFFF
00401424  |.  33C0          |xor eax,eax
00401426  |.  42            |inc edx                                 ;        edx++    ebx++
00401427  |.  F2:AE         |repne scas byte ptr es:[edi]
00401429  |.  F7D1          |not ecx
0040142B  |.  49            |dec ecx
0040142C  |.  3BD1          |cmp edx,ecx
0040142E  |.^ 72 D7         \jb Xkgme.

对应C语言代码 如下:

int  _CalcRetComb(
        char* lpRet1,
        char* lpRet2,
        int   nLenRet1,
        int   nLenRet2,
        char** lppRet
        )
{
        int i ,j;
        char* lpBufRet = new char[nLenRet1+nLenRet2];

        for (i = 0 ;i < nLenRet1 ;i++)
        {
                j = 0;
                while (lpRet1[i] != szRand1[j])
                {
                        if (++j >= 0x10)
                                break;
                }
               
                lpBufRet[i] = j ^ 0x23;
        }

        for (i = 0 ;i < nLenRet2 ;i++)
        {
                j = 0;
                while (lpRet2[i] != szRand1[j])
                {
                        if (++j >= 0x10)
                                break;
                }

                lpBufRet[i+nLenRet1] = j ^ 0x23;
        }

        *lppRet = lpBufRet;
        return nLenRet1+nLenRet2;
}

2.3 下面就到了第3步了, 目标是计算Ebx ,分两步(两个循环)计算, 第2次计算接着使用上前次结果Ebx , 最终结果在Ebx上

00401430  |> \8BFD          mov edi,ebp
00401432  |.  83C9 FF       or ecx,0xFFFFFFFF
00401435  |.  33C0          xor eax,eax
00401437  |.  33F6          xor esi,esi
00401439  |.  F2:AE         repne scas byte ptr es:[edi]
0040143B  |.  F7D1          not ecx
0040143D  |.  49            dec ecx
0040143E  |.  BB EA7D3862   mov ebx,0x62387DEA
00401443      74 46         je Xkgme.0040148B                        ;  while(esi < AcctBufLen){
00401445      0FBE042E      movsx eax,byte ptr ds:[esi+ebp]
00401449  |.  0FAFC0        |imul eax,eax                            ;         eax *= AcctBuf[esi] * AcctBuf[esi]
0040144C  |.  33D2          |xor edx,edx
0040144E  |.  BF 07000000   |mov edi,0x7
00401453  |.  8D0C40        |lea ecx,dword ptr ds:[eax+eax*2]        ;         ecx = 3*eax
00401456  |.  C1E1 03       |shl ecx,0x3
00401459  |.  2BC8          |sub ecx,eax                             ;         ecx = (ecx<<3) - eax
0040145B  |.  8BC6          |mov eax,esi
0040145D  |.  F7F7          |div edi                                 ;         edx = esi % 7
0040145F  |.  8BC1          |mov eax,ecx
00401461  |.  8BFD          |mov edi,ebp
00401463  |.  F7D0          |not eax
00401465  |.  0FAFC1        |imul eax,ecx
00401468  |.  C1E0 02       |shl eax,0x2                             ;         eax = (ecx * ~ecx)<<2
0040146B  |.  8B1495 D45040>|mov edx,dword ptr ds:[edx*4+0x4050D4]
00401472  |.  03D1          |add edx,ecx                             ;         edx = Dword RandStr3[edx*4] + ecx
00401474  |.  83C9 FF       |or ecx,0xFFFFFFFF
00401477  |.  33D0          |xor edx,eax
00401479  |.  33C0          |xor eax,eax
0040147B  |.  33D3          |xor edx,ebx
0040147D  |.  33D6          |xor edx,esi                             ;         edx = edx ^ eax ^ ebx ^ esi
0040147F  |.  46            |inc esi
00401480  |.  F2:AE         |repne scas byte ptr es:[edi]
00401482  |.  F7D1          |not ecx
00401484  |.  49            |dec ecx
00401485  |.  8BDA          |mov ebx,edx                             ;         ebx = edx
00401487  |.  3BF1          |cmp esi,ecx
00401489  |.^ 72 BA         \jb Xkgme.00401445                       ;  }
0040148B  |>  8B4C24 10     mov ecx,dword ptr ss:[esp+0x10]          ;  ecx = UserNameLen+1
0040148F  |.  33F6          xor esi,esi
00401491  |.  8D41 FF       lea eax,dword ptr ds:[ecx-0x1]           ;  eax = UserNameLen
00401494  |.  85C0          test eax,eax
00401496  |.  894424 18     mov dword ptr ss:[esp+0x18],eax
0040149A  |.  76 46         jbe Xkgme.004014E2
0040149C  |.  EB 07         jmp Xkgme.004014A5                       ;  while (esi < UserNameLen)
0040149E  |>  8BAC24 280100>/mov ebp,dword ptr ss:[esp+0x128]        ;  {
004014A5  |>  0FBE0C2E       movsx ecx,byte ptr ds:[esi+ebp]         ;        ecx = byte AcctBuf[esi]
004014A9  |.  8D7E 42       |lea edi,dword ptr ds:[esi+0x42]         ;        edi = esi + 0x42
004014AC  |.  8BC6          |mov eax,esi
004014AE  |.  33D2          |xor edx,edx
004014B0  |.  BD 07000000   |mov ebp,0x7
004014B5  |.  F7F5          |div ebp                                 ;        edx = esi % 7
004014B7  |.  0FAFC9        |imul ecx,ecx
004014BA  |.  0FAFC9        |imul ecx,ecx
004014BD  |.  C1E1 03       |shl ecx,0x3                             ;        ecx = (ecx * ecx * ecx * ecx) >> 3
004014C0  |.  8BC1          |mov eax,ecx
004014C2  |.  F7D0          |not eax
004014C4  |.  0FAFC1        |imul eax,ecx
004014C7  |.  8B1495 D45040>|mov edx,dword ptr ds:[edx*4+0x4050D4]
004014CE  |.  03D1          |add edx,ecx                             ;        edx = RandStr3[edx*4] + ecx
004014D0  |.  C1E0 02       |shl eax,0x2                             ;        eax = (ecx * ~ecx) >> 2
004014D3  |.  33D0          |xor edx,eax
004014D5  |.  8B4424 18     |mov eax,dword ptr ss:[esp+0x18]
004014D9  |.  33D7          |xor edx,edi                             ;         edx = edx ^ eax ^ edi
004014DB  |.  33DA          |xor ebx,edx                             ;         ebx ^= edx
004014DD  |.  46            |inc esi
004014DE  |.  3BF0          |cmp esi,eax
004014E0  |.^ 72 BC         \jb Xkgme.0040149E                       ;  }

同样,C语言代码也来一份:

int _CalcEbx(
        char* szAcct,
        int   nAcctLen,
        int   nUserNameLen
        )
{
        unsigned int nEbx = 0x62387DEA ,i ,nEax ,nEcx ,nEdx;
        for (i = 0 ;i < nAcctLen ;i++)
        {
                nEax = szAcct[i]*szAcct[i];
                nEcx = ((3*nEax)<<3) - nEax;

                nEdx = i % 0x7;
                nEdx = PnRand[nEdx] + nEcx;

                nEax = (nEcx * ~nEcx)<<2;
                nEdx = nEdx ^ nEax ^ nEbx ^ i;

                nEbx = nEdx;
        }

        for (i = 0 ;i < nUserNameLen ;i++)
        {
                nEcx = (szAcct[i]*szAcct[i]*szAcct[i]*szAcct[i])<<0x3;
                nEax = (nEcx * ~nEcx) << 2;

                nEdx = i % 0x7;
                nEdx = PnRand[nEdx] + nEcx;

                nEdx = nEdx ^ nEax ^ (i+0x42);
                nEbx ^= nEdx;
        }

        return nEbx;
}

2.4 这下Ebx也得到了 ,但第3步中计算得到的lpRetStrCmb还没有用上呢, 它将达步中用到, 这里主要是它(lpRetStrCmb) 来计算组合出用于你输入的szSerial转化成16进制的nSerial加密用 ,上代码

004014E2      8B8C24 2C0100>mov ecx,dword ptr ss:[esp+0x12C]
004014E9  |.  6A 10         push 0x10
004014EB  |.  6A 00         push 0x0
004014ED  |.  51            push ecx
004014EE  |.  E8 D5040000   call kgme.004019C8                       ;  strtoul (szSerial ,char ,base)将szSerial转化为nSerial
004014F3  |.  8B5424 2C     mov edx,dword ptr ss:[esp+0x2C]          ;  edx =lpRetStrCmbLen
004014F7  |.  50            push eax                                 ;  eax = nSerial
004014F8  |.  8B4424 24     mov eax,dword ptr ss:[esp+0x24]          ;  eax = lpRetStrCmb
004014FC  |.  52            push edx                                 ;  _CalcCode(...) 计算用于加密nSerial用的机器码lpCode
004014FD  |.  50            push eax                                 ;  并转而执行lpCode ,加密nSerial
004014FE  |.  E8 FDFAFFFF   call kgme.00401000                       ;  _CalcCode(lpRetStrCmb ,lpRetStrCmbLen ,nSerial)
00401503  |.  83C4 18       add esp,0x18
00401506  |.  3BC3          cmp eax,ebx                              ;  这里将加密之后的nSerial(在eax中)与前面算出的Ebx比较
00401508  |.  0F94C0        sete al                                  ;  相等则返回 0
0040150B  |.  5F            pop edi
0040150C  |.  5E            pop esi
0040150D  |.  5D            pop ebp
0040150E  |.  5B            pop ebx
0040150F  |.  81C4 14010000 add esp,0x114
00401515  \.  C3            retn

我们行F7跟进 _CalcCode(....)这个函数,看看里面怎么组织加密机器码lpCode的,这段比较长些


00401000  /$  55            push ebp
00401001  |.  8BEC          mov ebp,esp
00401003  |.  83EC 08       sub esp,0x8
00401006  |.  8B0D C0664000 mov ecx,dword ptr ds:[0x4066C0]
0040100C  |.  53            push ebx
0040100D  |.  8B5D 0C       mov ebx,[arg.2]
00401010  |.  56            push esi
00401011  |.  57            push edi
00401012  |.  8D449B 01     lea eax,dword ptr ds:[ebx+ebx*4+0x1]     ;  nbyte = PNewAddrRet3Len * 5 + 1
00401016  |.  50            push eax                                 ; /dwBytes
00401017  |.  6A 40         push 0x40                                ; |dwFlags = 40
00401019  |.  51            push ecx                                 ; |hHeap => 00290000
0040101A  |.  FF15 5C504000 call dword ptr ds:[<&KERNEL32.HeapAlloc>>; \RtlAllocateHeap
00401020  |.  8B55 10       mov edx,[arg.3]                          ;  edx = nPsw
00401023  |.  33FF          xor edi,edi
00401025  |.  8955 0C       mov [arg.2],edx                          ;  arg_2 = arg_3
00401028  |.  33D2          xor edx,edx
0040102A  |.  85DB          test ebx,ebx
0040102C  |.  8945 FC       mov [local.1],eax                        ;  local.1 = ecx = lpCode
0040102F  |.  0F86 43020000 jbe kgme.00401278
00401035  |.  8BC8          mov ecx,eax
00401037  |>  8B45 08       /mov eax,[arg.1]                         ;  while (edi < lpRetStrCmb) {
0040103A  |.  0FBE3407      |movsx esi,byte ptr ds:[edi+eax]
0040103E  |.  83F6 23       |xor esi,0x23                            ;  esi = lpRetStrCmb[edi] ^ 0x23
00401041  |.  83FE 0F       |cmp esi,0xF                             ;  Switch (cases 0..F)
00401044  |.  0F87 1C020000 |ja kgme.00401266
0040104A  |.  FF24B5 941240>|jmp dword ptr ds:[esi*4+0x401294]
00401051  |>  8B35 A0604000 |mov esi,dword ptr ds:[0x4060A0]         ;  Case 0 of switch 00401041
00401057  |.  8BC1          |mov eax,ecx                             ;  {
00401059  |.  83C2 05       |add edx,0x5                             ;  edx += 5
0040105C  |.  8930          |mov dword ptr ds:[eax],esi              ;  *lpCode = Dword [0x4060A0]
0040105E  |.  8BF1          |mov esi,ecx
00401060  |.  8945 F8       |mov [local.2],eax
00401063  |.  A0 A4604000   |mov al,byte ptr ds:[0x4060A4]
00401068  |.  8846 04       |mov byte ptr ds:[esi+0x4],al            ;  *(lpCode + 4) = byte[0x4060A4]
0040106B  |.  83C1 05       |add ecx,0x5                             ;  lpCode += 5
0040106E  |.  E9 F9010000   |jmp kgme.0040126C                       ;  }
00401073  |>  8B35 98604000 |mov esi,dword ptr ds:[0x406098]         ;  Case 1 of switch 00401041
00401079  |.  8BC1          |mov eax,ecx                             ;  {
0040107B  |.  83C2 05       |add edx,0x5
0040107E  |.  8930          |mov dword ptr ds:[eax],esi              ;  *lpCode = Dword [0x406098]
00401080  |.  8BF1          |mov esi,ecx
00401082  |.  8945 F8       |mov [local.2],eax
00401085  |.  A0 9C604000   |mov al,byte ptr ds:[0x40609C]
0040108A  |.  8846 04       |mov byte ptr ds:[esi+0x4],al            ;  *(lpCode+4) = byte[0x40609c]
0040108D  |.  83C1 05       |add ecx,0x5                             ;  lpCode += 5
00401090  |.  E9 D7010000   |jmp kgme.0040126C                       ;  }
00401095  |>  8B35 90604000 |mov esi,dword ptr ds:[0x406090]         ;  Case 2 of switch 00401041
0040109B  |.  8BC1          |mov eax,ecx
0040109D  |.  83C2 05       |add edx,0x5
004010A0  |.  8930          |mov dword ptr ds:[eax],esi              ;  *lpCode = Dword [0x406090]
004010A2  |.  8BF1          |mov esi,ecx
004010A4  |.  8945 F8       |mov [local.2],eax
004010A7  |.  A0 94604000   |mov al,byte ptr ds:[0x406094]
004010AC  |.  8846 04       |mov byte ptr ds:[esi+0x4],al            ;  *(lpCode + 4) = byte [0x406094]
004010AF  |.  83C1 05       |add ecx,0x5                             ;  lpCode  += 5
004010B2  |.  E9 B5010000   |jmp kgme.0040126C
004010B7  |>  66:8B35 8C604>|mov si,word ptr ds:[0x40608C]           ;  Case 3 of switch 00401041
004010BE  |.  8BC1          |mov eax,ecx
004010C0  |.  83C2 03       |add edx,0x3
004010C3  |.  66:8930       |mov word ptr ds:[eax],si                ;  *lpCode = word [0x40608c]
004010C6  |.  8BF1          |mov esi,ecx
004010C8  |.  8945 F8       |mov [local.2],eax
004010CB  |.  A0 8E604000   |mov al,byte ptr ds:[0x40608E]
004010D0  |.  8846 02       |mov byte ptr ds:[esi+0x2],al            ;  *(lpCode+2) = byte [0x40608E]
004010D3  |.  83C1 03       |add ecx,0x3
004010D6  |.  E9 91010000   |jmp kgme.0040126C
004010DB  |>  66:A1 8860400>|mov ax,word ptr ds:[0x406088]           ;  Case 4 of switch 00401041
004010E1  |.  83C2 02       |add edx,0x2
004010E4  |.  66:8901       |mov word ptr ds:[ecx],ax
004010E7  |.  83C1 02       |add ecx,0x2
004010EA  |.  E9 7D010000   |jmp kgme.0040126C
004010EF  |>  8B35 80604000 |mov esi,dword ptr ds:[0x406080]         ;  Case 5 of switch 00401041
004010F5  |.  8BC1          |mov eax,ecx
004010F7  |.  83C2 05       |add edx,0x5
004010FA  |.  8930          |mov dword ptr ds:[eax],esi
004010FC  |.  8BF1          |mov esi,ecx
004010FE  |.  8945 F8       |mov [local.2],eax
00401101  |.  A0 84604000   |mov al,byte ptr ds:[0x406084]
00401106  |.  8846 04       |mov byte ptr ds:[esi+0x4],al
00401109  |.  83C1 05       |add ecx,0x5
0040110C  |.  E9 5B010000   |jmp kgme.0040126C
00401111  |>  8B35 78604000 |mov esi,dword ptr ds:[0x406078]         ;  Case 6 of switch 00401041
00401117  |.  8BC1          |mov eax,ecx
00401119  |.  83C2 05       |add edx,0x5
0040111C  |.  8930          |mov dword ptr ds:[eax],esi
0040111E  |.  8BF1          |mov esi,ecx
00401120  |.  8945 F8       |mov [local.2],eax
00401123  |.  A0 7C604000   |mov al,byte ptr ds:[0x40607C]
00401128  |.  8846 04       |mov byte ptr ds:[esi+0x4],al
0040112B  |.  83C1 05       |add ecx,0x5
0040112E  |.  E9 39010000   |jmp kgme.0040126C
00401133  |>  8B45 0C       |mov eax,[arg.2]                         ;  Case 7 of switch 00401041
00401136  |.  8B35 70604000 |mov esi,dword ptr ds:[0x406070]
0040113C  |.  35 DFED0D00   |xor eax,0xDEDDF
00401141  |.  83C2 05       |add edx,0x5
00401144  |.  8945 0C       |mov [arg.2],eax
00401147  |.  8BC1          |mov eax,ecx
00401149  |.  8930          |mov dword ptr ds:[eax],esi
0040114B  |.  8BF1          |mov esi,ecx
0040114D  |.  8945 F8       |mov [local.2],eax
00401150  |.  A0 74604000   |mov al,byte ptr ds:[0x406074]
00401155  |.  8846 04       |mov byte ptr ds:[esi+0x4],al
00401158  |.  83C1 05       |add ecx,0x5
0040115B  |.  E9 0C010000   |jmp kgme.0040126C
00401160  |>  8B35 68604000 |mov esi,dword ptr ds:[0x406068]         ;  Case 8 of switch 00401041
00401166  |.  8BC1          |mov eax,ecx
00401168  |.  83C2 05       |add edx,0x5
0040116B  |.  8930          |mov dword ptr ds:[eax],esi
0040116D  |.  8BF1          |mov esi,ecx
0040116F  |.  8945 F8       |mov [local.2],eax
00401172  |.  A0 6C604000   |mov al,byte ptr ds:[0x40606C]
00401177  |.  8846 04       |mov byte ptr ds:[esi+0x4],al
0040117A  |.  83C1 05       |add ecx,0x5
0040117D  |.  E9 EA000000   |jmp kgme.0040126C
00401182  |>  66:8B35 64604>|mov si,word ptr ds:[0x406064]           ;  Case 9 of switch 00401041
00401189  |.  8BC1          |mov eax,ecx
0040118B  |.  83C2 03       |add edx,0x3
0040118E  |.  66:8930       |mov word ptr ds:[eax],si
00401191  |.  8BF1          |mov esi,ecx
00401193  |.  8945 F8       |mov [local.2],eax
00401196  |.  A0 66604000   |mov al,byte ptr ds:[0x406066]
0040119B  |.  8846 02       |mov byte ptr ds:[esi+0x2],al
0040119E  |.  83C1 03       |add ecx,0x3
004011A1  |.  E9 C6000000   |jmp kgme.0040126C
004011A6  |>  8B35 5C604000 |mov esi,dword ptr ds:[0x40605C]         ;  Case A of switch 00401041
004011AC  |.  8BC1          |mov eax,ecx
004011AE  |.  83C2 05       |add edx,0x5
004011B1  |.  8930          |mov dword ptr ds:[eax],esi
004011B3  |.  8BF1          |mov esi,ecx
004011B5  |.  8945 F8       |mov [local.2],eax
004011B8  |.  A0 60604000   |mov al,byte ptr ds:[0x406060]
004011BD  |.  8846 04       |mov byte ptr ds:[esi+0x4],al
004011C0  |.  83C1 05       |add ecx,0x5
004011C3  |.  E9 A4000000   |jmp kgme.0040126C
004011C8  |>  8B35 54604000 |mov esi,dword ptr ds:[0x406054]         ;  Case B of switch 00401041
004011CE  |.  8BC1          |mov eax,ecx
004011D0  |.  83C2 05       |add edx,0x5
004011D3  |.  8930          |mov dword ptr ds:[eax],esi
004011D5  |.  8BF1          |mov esi,ecx
004011D7  |.  8945 F8       |mov [local.2],eax
004011DA  |.  A0 58604000   |mov al,byte ptr ds:[0x406058]
004011DF  |.  8846 04       |mov byte ptr ds:[esi+0x4],al
004011E2  |.  83C1 05       |add ecx,0x5
004011E5  |.  E9 82000000   |jmp kgme.0040126C
004011EA  |>  8B35 4C604000 |mov esi,dword ptr ds:[0x40604C]         ;  Case C of switch 00401041
004011F0  |.  8BC1          |mov eax,ecx
004011F2  |.  83C2 05       |add edx,0x5
004011F5  |.  8930          |mov dword ptr ds:[eax],esi
004011F7  |.  8BF1          |mov esi,ecx
004011F9  |.  8945 F8       |mov [local.2],eax
004011FC  |.  A0 50604000   |mov al,byte ptr ds:[0x406050]
00401201  |.  8846 04       |mov byte ptr ds:[esi+0x4],al
00401204  |.  83C1 05       |add ecx,0x5
00401207  |.  EB 63         |jmp Xkgme.0040126C
00401209  |>  8B35 44604000 |mov esi,dword ptr ds:[0x406044]         ;  Case D of switch 00401041
0040120F  |.  8BC1          |mov eax,ecx
00401211  |.  83C2 05       |add edx,0x5
00401214  |.  8930          |mov dword ptr ds:[eax],esi
00401216  |.  8BF1          |mov esi,ecx
00401218  |.  8945 F8       |mov [local.2],eax
0040121B  |.  A0 48604000   |mov al,byte ptr ds:[0x406048]
00401220  |.  8846 04       |mov byte ptr ds:[esi+0x4],al
00401223  |.  83C1 05       |add ecx,0x5
00401226  |.  EB 44         |jmp Xkgme.0040126C
00401228  |>  8B35 3C604000 |mov esi,dword ptr ds:[0x40603C]         ;  Case E of switch 00401041
0040122E  |.  8BC1          |mov eax,ecx
00401230  |.  83C2 05       |add edx,0x5
00401233  |.  8930          |mov dword ptr ds:[eax],esi
00401235  |.  8BF1          |mov esi,ecx
00401237  |.  8945 F8       |mov [local.2],eax
0040123A  |.  A0 40604000   |mov al,byte ptr ds:[0x406040]
0040123F  |.  8846 04       |mov byte ptr ds:[esi+0x4],al
00401242  |.  83C1 05       |add ecx,0x5
00401245  |.  EB 25         |jmp Xkgme.0040126C
00401247  |>  8B35 34604000 |mov esi,dword ptr ds:[0x406034]         ;  Case F of switch 00401041
0040124D  |.  8BC1          |mov eax,ecx
0040124F  |.  83C2 05       |add edx,0x5
00401252  |.  8930          |mov dword ptr ds:[eax],esi
00401254  |.  8BF1          |mov esi,ecx
00401256  |.  8945 F8       |mov [local.2],eax
00401259  |.  A0 38604000   |mov al,byte ptr ds:[0x406038]
0040125E  |.  8846 04       |mov byte ptr ds:[esi+0x4],al
00401261  |.  83C1 05       |add ecx,0x5
00401264  |.  EB 06         |jmp Xkgme.0040126C
00401266  |>  68 3284FF0F   |push 0xFFF8432                          ;  Default case of switch 00401041
0040126B  |.  C3            |retn
0040126C  |>  47            |inc edi
0040126D  |.  3BFB          |cmp edi,ebx
0040126F  |.^ 0F82 C2FDFFFF \jb kgme.00401037
00401275  |.  8B45 FC       mov eax,[local.1]
00401278  |>  8A0D 30604000 mov cl,byte ptr ds:[0x406030]            ;  最后写入指令 ret 的机器码 0xC3
0040127E  |.  880C02        mov byte ptr ds:[edx+eax],cl             ;  lpCode[edx] = byte [0x406030]
00401281  |.  8B45 10       mov eax,[arg.3]
00401284  |.  FF55 FC       call [local.1]                           ;  call lpCode     跳到 lpCode 执行对nSerial的加密
00401287  |.  8945 0C       mov [arg.2],eax
0040128A  |.  8B45 0C       mov eax,[arg.2]
0040128D  |.  5F            pop edi
0040128E  |.  5E            pop esi
0040128F  |.  5B            pop ebx
00401290  |.  8BE5          mov esp,ebp
00401292  |.  5D            pop ebp
00401293  \.  C3            retn

计算出来的代码都是些数值运算指令,如( add ,sub ,rol ,ror ,not ,......)

因为上面这段代码是计算出机器码供 你输入的nSerial 加密用的,  加密之后得 nSerialEncrypted与 用登陆名(Account) 与 PC用户名(szUserName) 计算出来的Ebx 比较 来判断 szSerial是正确与否 ,   因此我们要想 根据我们的 Ebx 得到 nSerial , 就必须用Ebx来反向执行这段加密机器码, 当然这还是不够的, 还必须修改一些指令为其对应的逆向操作指令. 如 add -- sub  ,rol -- ror .....not 与 xor 指令不变. 就是这样

下面计算逆向指令代码的对应C语言表示 ,因为得反向执行计算出来的机器码,所以,计算前得让 lpRetStrCmb反向.

int _CalcCode(
        char*  lpRet3,
        int    nRet3Len,
        char** lppRet
        )
{
        char* lpCode = new char[nRet3Len*5+1];
        memset(lpCode ,0x90 ,nRet3Len*5+1);

        int*   Pdword ,i ,j;
        short* Pword;
        char*  Pbyte;
        for (i = 0 ,j = 0 ;i < nRet3Len ;i++)
        {
                switch(lpRet3[i] ^ 0x23)
                {
                case 0x0:  
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x32792835;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0;
                        j += 5;
                        break;
               
                case 0x1:  
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xD743D2D;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0;
                        j += 5;
                        break;

                case 0x2:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xDEFFFF35;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0xC0;
                        j += 5;
                        break;

                case 0x3:   
                        Pword = (short*)(lpCode+j);
                        *Pword = 0xC8C1;
                        Pbyte = (char*)(lpCode+j+2);
                        *Pbyte = 0x13;
                        j += 3;
                        break;

                case 0x4:  
                        Pword = (short*)(lpCode+j);
                        *Pword = 0xD0F7;
                        j += 2;
                        break;

                case 0x5:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x3478342D;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x02;
                        j += 5;
                        break;

                case 0x6:     
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x85545435;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0x7:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xDEDDF35;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0x8:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x3472352D;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0x9:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xC0C1;
                        Pbyte = (char*)(lpCode+j+2);
                        *Pbyte = 0x23;
                        j += 3;
                        break;

                case 0xA:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x34FF5305;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x38;
                        j += 5;
                        break;

                case 0xB:  
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xDEAD35;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0xC:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x2374305;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0xD:
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xDEFE342D;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0xE:
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x485FD35;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0xF:  
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x236FFA05;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                default:
                        return 0;
                }
               
        }
        lpCode[j] = 0xc3;   //最后写入 ret指令
        *lppRet = lpCode;
        return nRet3Len*5+1;
}

到这里分析算了完成了,下面来一份完整的 注册机代码吧.

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

unsigned long nPsw;
char* szRand1 = "6Ghd3iHRaSkL,;-Z";
int   PnRand[] = {0x43275  ,0xAED2384  ,0xD377AE7,0xD54837D,
                 0xFE53743 ,0x3472389 ,0x23488 };

char* _CalcRetstr(
        char*  szBuf,
        int    nBufLen
        )
{
        char szTmp;
        char* lpBufRet = new char[nBufLen*2+1];
        for (int i = 0 ;i < nBufLen ;i++)
        {
                szTmp = (szBuf[i] >> 4) & 0xF;
                szTmp = szRand1[szTmp];
                lpBufRet[i*2] = szTmp;

                szTmp = szBuf[i] & 0xF;
                szTmp = szRand1[szTmp];
                lpBufRet[i*2+1] = szTmp;
        }

        lpBufRet[nBufLen*2] = 0;
        return lpBufRet;
}

int  _CalcRetComb(
        char* lpRet1,
        char* lpRet2,
        int   nLenRet1,
        int   nLenRet2,
        char** lppRet
        )
{
        int i ,j;
        char* lpBufRet = new char[nLenRet1+nLenRet2];

        for (i = 0 ;i < nLenRet1 ;i++)
        {
                j = 0;
                while (lpRet1[i] != szRand1[j])
                {
                        if (++j >= 0x10)
                                break;
                }
               
                lpBufRet[i] = j ^ 0x23;
        }

        for (i = 0 ;i < nLenRet2 ;i++)
        {
                j = 0;
                while (lpRet2[i] != szRand1[j])
                {
                        if (++j >= 0x10)
                                break;
                }

                lpBufRet[i+nLenRet1] = j ^ 0x23;
        }

        *lppRet = lpBufRet;
        return nLenRet1+nLenRet2;
}

int _CalcEbx(
        char* szAcct,
        int   nAcctLen,
        int   nUserNameLen
        )
{
        unsigned int nEbx = 0x62387DEA ,i ,nEax ,nEcx ,nEdx;
        for (i = 0 ;i < nAcctLen ;i++)
        {
                nEax = szAcct[i]*szAcct[i];
                nEcx = ((3*nEax)<<3) - nEax;

                nEdx = i % 0x7;
                nEdx = PnRand[nEdx] + nEcx;

                nEax = (nEcx * ~nEcx)<<2;
                nEdx = nEdx ^ nEax ^ nEbx ^ i;

                nEbx = nEdx;
        }

        for (i = 0 ;i < nUserNameLen ;i++)
        {
                nEcx = (szAcct[i]*szAcct[i]*szAcct[i]*szAcct[i])<<0x3;
                nEax = (nEcx * ~nEcx) << 2;

                nEdx = i % 0x7;
                nEdx = PnRand[nEdx] + nEcx;

                nEdx = nEdx ^ nEax ^ (i+0x42);
                nEbx ^= nEdx;
        }

        return nEbx;
}

int _CalcCode(
        char*  lpRet3,
        int    nRet3Len,
        char** lppRet
        )
{
        char* lpCode = new char[nRet3Len*5+1];
        memset(lpCode ,0x90 ,nRet3Len*5+1);

        int*   Pdword ,i ,j;
        short* Pword;
        char*  Pbyte;
        for (i = 0 ,j = 0 ;i < nRet3Len ;i++)
        {
                switch(lpRet3[i] ^ 0x23)
                {
                case 0x0:  
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x32792835;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0;
                        j += 5;
                        break;
               
                case 0x1:  
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xD743D2D;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0;
                        j += 5;
                        break;

                case 0x2:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xDEFFFF35;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0xC0;
                        j += 5;
                        break;

                case 0x3:   
                        Pword = (short*)(lpCode+j);
                        *Pword = 0xC8C1;
                        Pbyte = (char*)(lpCode+j+2);
                        *Pbyte = 0x13;
                        j += 3;
                        break;

                case 0x4:  
                        Pword = (short*)(lpCode+j);
                        *Pword = 0xD0F7;
                        j += 2;
                        break;

                case 0x5:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x3478342D;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x02;
                        j += 5;
                        break;

                case 0x6:     
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x85545435;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0x7:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xDEDDF35;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0x8:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x3472352D;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0x9:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xC0C1;
                        Pbyte = (char*)(lpCode+j+2);
                        *Pbyte = 0x23;
                        j += 3;
                        break;

                case 0xA:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x34FF5305;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x38;
                        j += 5;
                        break;

                case 0xB:  
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xDEAD35;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0xC:   
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x2374305;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0xD:
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0xDEFE342D;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0xE:
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x485FD35;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                case 0xF:  
                        Pdword = (int*)(lpCode+j);
                        *Pdword = 0x236FFA05;
                        Pbyte = (char*)(lpCode+j+4);
                        *Pbyte = 0x00;
                        j += 5;
                        break;

                default:
                        return 0;
                }
               
        }
        lpCode[j] = 0xc3;
        *lppRet = lpCode;
        return nRet3Len*5+1;
}

int main()
{
        int i = 0 ,j;

        char szAcct[100] = {0};
        printf("Enter Account:");
        scanf("%s" ,szAcct);
        char* lpRetstr2 = _CalcRetstr(szAcct ,lstrlen(szAcct));
       
        int  nTmp = 100;
        char szUserName[100] = {0};
        GetUserName(szUserName ,(unsigned long*)&nTmp);
        char* lpRetstr1 = _CalcRetstr(szUserName ,lstrlen(szUserName));

        char* lpRetCmb = NULL;
        int nLenRetCmb = _CalcRetComb(lpRetstr1 ,lpRetstr2 ,lstrlen(lpRetstr1),
                lstrlen(lpRetstr2) ,&lpRetCmb);
       
        int nEbx = _CalcEbx(szAcct ,lstrlen(szAcct) ,lstrlen(szUserName));

        char* lpRetCmbRevs = new char[nLenRetCmb+1];
        for (i = 0 ,j = nLenRetCmb - 1 ;i < nLenRetCmb ;i++ ,j--)
                lpRetCmbRevs[i] = lpRetCmb[j];

        unsigned char* lpCodeRevs = NULL;
        int  nLenCodeRevs = _CalcCode(lpRetCmbRevs ,nLenRetCmb ,(char**)&lpCodeRevs);

        __asm
        {
                mov eax ,nEbx
                call lpCodeRevs
                mov nPsw ,eax
        }

        printf("Serial: %x\n" ,nPsw);

        delete[] lpRetstr1;
        delete[] lpRetstr2;
        delete[] lpRetCmb;
        delete[] lpRetCmbRevs;
        delete[] lpCodeRevs;

        return 0;
}

:


[课程]Android-CTF解题方法汇总!

上传的附件:
收藏
免费 6
支持
分享
最新回复 (5)
雪    币: 57
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
学习下  没见神器
2013-1-10 16:29
0
雪    币: 458
活跃值: (306)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
3
不错,学习了。
2013-1-10 21:14
0
雪    币: 219
活跃值: (1634)
能力值: ( LV9,RANK:410 )
在线值:
发帖
回帖
粉丝
4
精彩,学习下
2013-1-11 18:47
0
雪    币: 93944
活跃值: (200229)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
5
Thanks for share.
2013-1-12 08:02
0
雪    币: 270
活跃值: (117)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
分析的非常精彩啊,表述很专业,嘿嘿
2013-1-12 17:10
0
游客
登录 | 注册 方可回帖
返回
//