首页
论坛
专栏
课程

[调试逆向] [原创]APISpy v2.5 Crack过程分享

2009-1-7 21:57 4492

[调试逆向] [原创]APISpy v2.5 Crack过程分享

2009-1-7 21:57
4492
【文章标题】: APISpy v2.5 Crack过程分享
【文章作者】: 秋风寒
【软件名称】: APISpy v2.5
【软件大小】: 69k
【下载地址】: 自己搜索下载
【加壳方式】: Petite 1.2 -> (c)1998 Ian Luck (h) *
【保护方式】: 注册码
【编写语言】: VC++6.0
【使用工具】: OD, PEid
【软件介绍】: 能够监控应用程序执行API函数。
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  最近使用到了该软件,每次启动都提示注册,保存结果时,只能保存前10条,很是郁闷,决定拿他开个刀,练练手。
  1、用PEid查看,显示是Petite 1.2 -> (c)1998 Ian Luck (h) * 加的壳, 用Peid的通用脱壳插件脱壳后,再次用Peid
     查看,显示为VC++6.0编写的,呵呵,我的最爱啊。
  2、执行脱壳后的程序,程序能正常运行,但是OD载入后,点注册对话框,填了注册信息后,按确定,OD报内存不可读错误,
     然后程序退出,怀疑有反调试。
  3、决定代壳调试试试。
  4、OD载入源程序,填注册码,确定,发现一切正常,开来没有凡调试。
  5、查找当前模块中的名称,然后在GetDlgItemTextA, GetWindowTextA的每个参考上下断点,
     然后填注册码,确定后停在下面这个函数处(在这里可能需要在CPU窗口单击右键,选择分析->分析代码,来让代码显示正常),
  004051D0  /$  8B4424 08     mov     eax, dword ptr [esp+8]
  004051D4  |.  53            push    ebx
  004051D5  |.  56            push    esi
  004051D6  |.  83F8 01       cmp     eax, 1
  004051D9  |.  57            push    edi
  004051DA  |.  0F85 81000000 jnz     00405261
  004051E0  |.  8B7424 10     mov     esi, dword ptr [esp+10]
  004051E4  |.  8B1D D0914000 mov     ebx, dword ptr [<&USER32.GetDlgI>;  USER32.GetDlgItemTextA        
  004051EA  |.  6A 4E         push    4E                               ; /Count = 4E (78.)
  004051EC  |.  68 C0C34000   push    0040C3C0                         ; |Buffer = apis32.0040C3C0
  004051F1  |.  68 F1030000   push    3F1                              ; |ControlID = 3F1 (1009.)
  004051F6  |.  56            push    esi                              ; |hWnd
  004051F7  |.  FFD3          call    ebx                              ; \GetDlgItemTextA            ;断在这里
  004051F9  |.  85C0          test    eax, eax                        
  004051FB  |.  74 76         je      short 00405273                   ;检查注册码长度
  004051FD  |.  BF C0C34000   mov     edi, 0040C3C0                    ;  ASCII "qiufenghan"
  00405202  |.  83C9 FF       or      ecx, FFFFFFFF
  00405205  |.  33C0          xor     eax, eax
  00405207  |.  F2:AE         repne   scas byte ptr es:[edi]
  00405209  |.  F7D1          not     ecx
  0040520B  |.  49            dec     ecx
  0040520C  |.  51            push    ecx
  0040520D  |.  68 C0C34000   push    0040C3C0                         ;  ASCII "qiufenghan"
  00405212  |.  68 88A64000   push    0040A688                         ;  ASCII "UserKey"
  00405217  |.  E8 D4010000   call    004053F0                         ;  把注册码保存在注册表中,键名为UserKey
  0040521C  |.  83C4 0C       add     esp, 0C
  0040521F  |.  6A 4E         push    4E
  00405221  |.  68 C0C34000   push    0040C3C0                         ;  ASCII "qiufenghan"
  00405226  |.  68 F0030000   push    3F0
  0040522B  |.  56            push    esi
  0040522C  |.  FFD3          call    ebx
  0040522E  |.  85C0          test    eax, eax                         ; 检测用户名长度
  00405230  |.  74 41         je      short 00405273
  00405232  |.  BF C0C34000   mov     edi, 0040C3C0                    ;  ASCII "qiufenghan"
  00405237  |.  83C9 FF       or      ecx, FFFFFFFF
  0040523A  |.  33C0          xor     eax, eax
  0040523C  |.  F2:AE         repne   scas byte ptr es:[edi]
  0040523E  |.  F7D1          not     ecx
  00405240  |.  49            dec     ecx
  00405241  |.  51            push    ecx
  00405242  |.  68 C0C34000   push    0040C3C0                         ;  ASCII "qiufenghan"
  00405247  |.  68 78A64000   push    0040A678                         ;  ASCII "UserName"
  0040524C  |.  E8 9F010000   call    004053F0                         ; 把用户名保存在注册表理,键名为UserName
  00405251  |.  83C4 0C       add     esp, 0C
  00405254  |.  6A 01         push    1                                ; /Result = 1
  00405256  |.  56            push    esi                              ; |hWnd
  00405257  |.  FF15 68914000 call    dword ptr [<&USER32.EndDialog>]  ; \EndDialog
  0040525D  |.  5F            pop     edi
  0040525E  |.  5E            pop     esi
  0040525F  |.  5B            pop     ebx
  00405260  |.  C3            retn
  00405261  |>  83F8 02       cmp     eax, 2
  00405264  |.  75 0D         jnz     short 00405273
  00405266  |.  8B4424 10     mov     eax, dword ptr [esp+10]
  0040526A  |.  6A 00         push    0                                ; /Result = 0
  0040526C  |.  50            push    eax                              ; |hWnd
  0040526D  |.  FF15 68914000 call    dword ptr [<&USER32.EndDialog>]  ; \EndDialog
  00405273  |>  5F            pop     edi
  00405274  |.  5E            pop     esi
  00405275  |.  5B            pop     ebx
  00405276  \.  C3            retn
  
  这时发现把用户把注册信息保存在注册表中后关闭了对话框,然后跟踪开始进入事件处理循环,把代码跟丢了。
  不过既然知道注册信息存在注册表里,呵呵就容易多了。找出注册算法的很重要的一步就是找到注册信息是怎么存放的。
  在继续处理以前我们先来看看函数  004053F0的内容, 很显然是个写注册表的功能。
        004053F0  /$  56            push    esi
        004053F1  |.  68 20B74000   push    0040B720                         ; /pHandle = apis32.0040B720
        004053F6  |.  68 3F000F00   push    0F003F                           ; |Access = KEY_ALL_ACCESS
        004053FB  |.  6A 00         push    0                                ; |Reserved = 0
        004053FD  |.  68 90A64000   push    0040A690                         ; |Subkey = "SOFTWARE\APIS32"
        00405402  |.  68 02000080   push    80000002                         ; |hKey = HKEY_LOCAL_MACHINE
        00405407  |.  FF15 08904000 call    dword ptr [<&ADVAPI32.RegOpenKey>; \RegOpenKeyExA
        0040540D  |.  85C0          test    eax, eax
        0040540F  |.  74 32         je      short 00405443
        00405411  |.  68 24B74000   push    0040B724                         ; /pDisposition = apis32.0040B724
        00405416  |.  68 20B74000   push    0040B720                         ; |pHandle = apis32.0040B720
        0040541B  |.  6A 00         push    0                                ; |pSecurity = NULL
        0040541D  |.  68 3F000F00   push    0F003F                           ; |Access = KEY_ALL_ACCESS
        00405422  |.  6A 00         push    0                                ; |Options = REG_OPTION_NON_VOLATILE
        00405424  |.  68 90A64000   push    0040A690                         ; |Class = "SOFTWARE\APIS32"
        00405429  |.  6A 00         push    0                                ; |Reserved = 0
        0040542B  |.  68 90A64000   push    0040A690                         ; |Subkey = "SOFTWARE\APIS32"
        00405430  |.  68 02000080   push    80000002                         ; |hKey = HKEY_LOCAL_MACHINE
        00405435  |.  FF15 10904000 call    dword ptr [<&ADVAPI32.RegCreateK>; \RegCreateKeyExA
        0040543B  |.  85C0          test    eax, eax
        0040543D  |.  74 04         je      short 00405443
        0040543F  |.  33C0          xor     eax, eax
        00405441  |.  5E            pop     esi
        00405442  |.  C3            retn
        00405443  |>  8B7424 10     mov     esi, dword ptr [esp+10]
        00405447  |.  8B4424 0C     mov     eax, dword ptr [esp+C]
        0040544B  |.  8B4C24 08     mov     ecx, dword ptr [esp+8]
        0040544F  |.  8B15 20B74000 mov     edx, dword ptr [40B720]
        00405455  |.  56            push    esi                              ; /BufSize
        00405456  |.  50            push    eax                              ; |Buffer
        00405457  |.  6A 00         push    0                                ; |ValueType = REG_NONE
        00405459  |.  6A 00         push    0                                ; |Reserved = 0
        0040545B  |.  51            push    ecx                              ; |ValueName
        0040545C  |.  52            push    edx                              ; |hKey => 88
        0040545D  |.  FF15 0C904000 call    dword ptr [<&ADVAPI32.RegSetValu>; \RegSetValueExA
        00405463  |.  A1 20B74000   mov     eax, dword ptr [40B720]
        00405468  |.  50            push    eax                              ; /hKey => 00000088 (window)
        00405469  |.  FF15 00904000 call    dword ptr [<&ADVAPI32.RegCloseKe>; \RegCloseKey
        0040546F  |.  8BC6          mov     eax, esi
        00405471  |.  5E            pop     esi
        00405472  \.  C3            retn
6、为了一劳永逸的找到注册算法,决定不再在填写注册码的对话框的地方下功夫,因为有些程序是在填写的时候只
   做验证部分,在启动的时候做全部验证。
   这次用OD载入脱壳后的程序,先在RegQueryValueExA上下断点。
   当参数ValueName的值为userCode时停下(可以对RegQueryValueExA下条件断点),连续按Ctrl+F9《按3次》直到程序返回到
   00402460  |.  68 2000CC00   push    0CC0020                          ; /ROP = SRCCOPY
        00402465  |.  6A 00         push    0                                ; |YSrc = 0
        00402467  |.  6A 00         push    0                                ; |XSrc = 0
        00402469  |.  8B55 DC       mov     edx, dword ptr [ebp-24]          ; |
        0040246C  |.  52            push    edx                              ; |hSrcDC
        0040246D  |.  8B45 F0       mov     eax, dword ptr [ebp-10]          ; |
        00402470  |.  50            push    eax                              ; |Height
        00402471  |.  8B4D EC       mov     ecx, dword ptr [ebp-14]          ; |
        00402474  |.  51            push    ecx                              ; |Width
        00402475  |.  8B55 08       mov     edx, dword ptr [ebp+8]           ; |
        00402478  |.  8B42 04       mov     eax, dword ptr [edx+4]           ; |
        0040247B  |.  50            push    eax                              ; |YDest
        0040247C  |.  8B4D 08       mov     ecx, dword ptr [ebp+8]           ; |
        0040247F  |.  8B11          mov     edx, dword ptr [ecx]             ; |
        00402481  |.  52            push    edx                              ; |XDest
        00402482  |.  8B45 E0       mov     eax, dword ptr [ebp-20]          ; |
        00402485  |.  50            push    eax                              ; |hDestDC
        00402486  |.  FF15 28904000 call    dword ptr [<&GDI32.BitBlt>]      ; \BitBlt
        0040248C  |.  E8 AF2B0000   call    00405040                         ;  判断是否注册
        ;连续按CTRL+F9程序回到这里,感觉这里可能就要做最后的跳转了
        00402491  |.  EB 01         jmp     short 00402494                   ;    <<==
        00402493  |   B8            db      B8
        00402494  |>  0AC0          or      al, al
        ;其实这段函数要被执行3次,如果这里只是改标志寄存器的位置,然后step by来查看,在后面执行sleep后
        ;会再次跟进Window消息处理过程中,如果你在此处没有下断点,按F9执行后,程序还是报注册失败。
        00402496  |.  74 02         je      short 0040249A                   ;  爆破点
        00402498  |.  EB 09         jmp     short 004024A3
        0040249A  |>  C745 D0 D4A04>mov     dword ptr [ebp-30], 0040A0D4     ;  unregistered
        004024A1  |.  EB 61         jmp     short 00402504
        004024A3  |>  BF 4CA04000   mov     edi, 0040A04C                    ;  registered to
        004024A8  |.  BA 20BD4000   mov     edx, 0040BD20                    ;  this  copy  of  apis32  is\n\nu n r e g i s t e r e d\n\nregistration info can be found in file reginfo.txt
        004024AD  |.  83C9 FF       or      ecx, FFFFFFFF
        004024B0  |.  33C0          xor     eax, eax
        004024B2  |.  F2:AE         repne   scas byte ptr es:[edi]
        004024B4  |.  F7D1          not     ecx
        004024B6  |.  2BF9          sub     edi, ecx
        004024B8  |.  8BF7          mov     esi, edi
        004024BA  |.  8BC1          mov     eax, ecx
        004024BC  |.  8BFA          mov     edi, edx
        004024BE  |.  C1E9 02       shr     ecx, 2
        004024C1  |.  F3:A5         rep     movs dword ptr es:[edi], dword p>
        004024C3  |.  8BC8          mov     ecx, eax
        004024C5  |.  83E1 03       and     ecx, 3
        004024C8  |.  F3:A4         rep     movs byte ptr es:[edi], byte ptr>
        004024CA  |.  BF C0C34000   mov     edi, offset <用户名>                ;  a
        004024CF  |.  BA 20BD4000   mov     edx, 0040BD20                    ;  this  copy  of  apis32  is\n\nu n r e g i s t e r e d\n\nregistration info can be found in file reginfo.txt
        004024D4  |.  83C9 FF       or      ecx, FFFFFFFF
        004024D7  |.  33C0          xor     eax, eax
        004024D9  |.  F2:AE         repne   scas byte ptr es:[edi]
        004024DB  |.  F7D1          not     ecx
        004024DD  |.  2BF9          sub     edi, ecx
        004024DF  |.  8BF7          mov     esi, edi
        004024E1  |.  8BD9          mov     ebx, ecx
        004024E3  |.  8BFA          mov     edi, edx
        004024E5  |.  83C9 FF       or      ecx, FFFFFFFF
        004024E8  |.  33C0          xor     eax, eax
        004024EA  |.  F2:AE         repne   scas byte ptr es:[edi]
        004024EC  |.  83C7 FF       add     edi, -1
        004024EF  |.  8BCB          mov     ecx, ebx
        004024F1  |.  C1E9 02       shr     ecx, 2
        004024F4  |.  F3:A5         rep     movs dword ptr es:[edi], dword p>
        004024F6  |.  8BCB          mov     ecx, ebx
        004024F8  |.  83E1 03       and     ecx, 3
        004024FB  |.  F3:A4         rep     movs byte ptr es:[edi], byte ptr>
        004024FD  |.  C745 D0 20BD4>mov     dword ptr [ebp-30], 0040BD20     ;  this  copy  of  apis32  is\n\nu n r e g i s t e r e d\n\nregistration info can be found in file reginfo.txt
        00402504  |>  6A 00         push    0                                ; /Alignment = TA_LEFT|TA_TOP
        00402506  |.  8B45 E0       mov     eax, dword ptr [ebp-20]          ; |
        00402509  |.  50            push    eax                              ; |hDC
        0040250A  |.  FF15 30904000 call    dword ptr [<&GDI32.SetTextAlign>>; \SetTextAlign

7、先在我们看看00405040函数,来找到注册算法。
        00405040  /$  51            push    ecx
        00405041  |.  53            push    ebx
        00405042  |.  55            push    ebp
        00405043  |.  56            push    esi
        00405044  |.  57            push    edi
        00405045  |.  6A 50         push    50
        00405047  |.  68 40B74000   push    offset <序列号>                     ;  b
        0040504C  |.  68 88A64000   push    0040A688                         ;  userkey
        00405051  |.  E8 1A030000   call    00405370
        00405056  |.  83C4 0C       add     esp, 0C
        00405059  |.  83F8 10       cmp     eax, 10                          ;  注册码长度为>=16
        0040505C  |.  7D 08         jge     short 00405066
        0040505E  |.  33C0          xor     eax, eax
        00405060  |.  5F            pop     edi
        00405061  |.  5E            pop     esi
        00405062  |.  5D            pop     ebp
        00405063  |.  5B            pop     ebx
        00405064  |.  59            pop     ecx
        00405065  |.  C3            retn
        00405066  |>  6A 2F         push    2F
        00405068  |.  68 C0C34000   push    offset <用户名>                     ;  a
        0040506D  |.  68 78A64000   push    0040A678                         ;  username
        00405072  |.  E8 F9020000   call    00405370
        00405077  |.  83C4 0C       add     esp, 0C
        0040507A  |.  83F8 05       cmp     eax, 5                           ;  用户名长度>=5
        0040507D  |.  7D 08         jge     short 00405087
        0040507F  |.  33C0          xor     eax, eax
        00405081  |.  5F            pop     edi
        00405082  |.  5E            pop     esi
        00405083  |.  5D            pop     ebp
        00405084  |.  5B            pop     ebx
        00405085  |.  59            pop     ecx
        00405086  |.  C3            retn
        ;把注册码拷贝到一个另一个全局缓冲区中,我们称之为code_buf2,原来的称之为code_buf1
        00405087  |>  BF 40B74000   mov     edi, offset <序列号>                ;  b
        0040508C  |.  83C9 FF       or      ecx, FFFFFFFF
        0040508F  |.  33C0          xor     eax, eax
        00405091  |.  C605 51B74000>mov     byte ptr [40B751], 0
        00405098  |.  F2:AE         repne   scas byte ptr es:[edi]
        0040509A  |.  F7D1          not     ecx
        0040509C  |.  2BF9          sub     edi, ecx
        0040509E  |.  8BC1          mov     eax, ecx
        004050A0  |.  8BF7          mov     esi, edi
        004050A2  |.  BF 54B74000   mov     edi, 0040B754
        004050A7  |.  C1E9 02       shr     ecx, 2
        004050AA  |.  F3:A5         rep     movs dword ptr es:[edi], dword p>
        004050AC  |.  8BC8          mov     ecx, eax
        004050AE  |.  33C0          xor     eax, eax
        004050B0  |.  83E1 03       and     ecx, 3
        004050B3  |.  F3:A4         rep     movs byte ptr es:[edi], byte ptr>
        ;删除code_buf2中第9个字母
        004050B5  |.  BF 49B74000   mov     edi, 0040B749                    ;  ASCII "AE7201C"
        004050BA  |.  83C9 FF       or      ecx, FFFFFFFF
        004050BD  |.  F2:AE         repne   scas byte ptr es:[edi]
        004050BF  |.  F7D1          not     ecx
        004050C1  |.  2BF9          sub     edi, ecx
        004050C3  |.  8BD1          mov     edx, ecx
        004050C5  |.  8BF7          mov     esi, edi
        004050C7  |.  BF 5CB74000   mov     edi, 0040B75C
        004050CC  |.  C1E9 02       shr     ecx, 2
        004050CF  |.  F3:A5         rep     movs dword ptr es:[edi], dword p>
        004050D1  |.  8BCA          mov     ecx, edx
        004050D3  |.  83E1 03       and     ecx, 3
        004050D6  |.  32DB          xor     bl, bl
        004050D8  |.  F3:A4         rep     movs byte ptr es:[edi], byte ptr>;  
       
        004050DA  |.  BE 41B74000   mov     esi, 0040B741                   ;code_buf1
        004050DF  |.  BF 54B74000   mov     edi, 0040B754                   ;code_buf2
        ;要求注册码去掉第9个字母后的字符为大写字母或数字,然后两个一起当一个16进制字节来处理,
        ;处理结果为8个字节,依次保存在code_buf1中
        004050E4  |>  57            /push    edi                             ;  for(int i=0; i<8; i++) {esi[i] = strToex[edi] ^ (50h + i);}
        004050E5  |.  E8 E6010000   |call    <StrtoHex>
        004050EA  |.  8ACB          |mov     cl, bl
        004050EC  |.  83C4 04       |add     esp, 4
        004050EF  |.  80C1 50       |add     cl, 50
        004050F2  |.  83C7 02       |add     edi, 2
        004050F5  |.  32C1          |xor     al, cl
        004050F7  |.  FEC3          |inc     bl
        004050F9  |.  8846 FF       |mov     byte ptr [esi-1], al
        004050FC  |.  C606 00       |mov     byte ptr [esi], 0
        004050FF  |.  46            |inc     esi
        00405100  |.  80FB 08       |cmp     bl, 8
        00405103  |.^ 72 DF         \jb      short 004050E4
       
        00405105  |.  68 54B74000   push    0040B754                            ;  code_buf2
        0040510A  |.  68 40B74000   push    offset <序列号>                     ;  b
        0040510F  |.  E8 EC010000   call    00405300                            ;另一个处理序列号的函数,我们后面载分析
        ; 把用户名保存复制到一个全局缓冲区中,我们称之为name_buf2, 如果用户名长度<8,则两个用户名接起来
        ; 取前8个字母
        00405114  |.  BF C0C34000   mov     edi, offset <用户名>                ;  a
        00405119  |.  83C9 FF       or      ecx, FFFFFFFF
        0040511C  |.  33C0          xor     eax, eax
        0040511E  |.  83C4 08       add     esp, 8
        00405121  |.  F2:AE         repne   scas byte ptr es:[edi]
        00405123  |.  F7D1          not     ecx
        00405125  |.  2BF9          sub     edi, ecx
        00405127  |.  33ED          xor     ebp, ebp
        00405129  |.  8BD1          mov     edx, ecx
        0040512B  |.  8BF7          mov     esi, edi
        0040512D  |.  BF 5EB74000   mov     edi, 0040B75E                    ;  ASCII "qiufenghan"
        00405132  |.  C1E9 02       shr     ecx, 2
        00405135  |.  F3:A5         rep     movs dword ptr es:[edi], dword p>
        00405137  |.  8BCA          mov     ecx, edx
        00405139  |.  83E1 03       and     ecx, 3
        0040513C  |.  F3:A4         rep     movs byte ptr es:[edi], byte ptr>
        0040513E  |.  BF C0C34000   mov     edi, offset <用户名>                ;  a
        00405143  |.  83C9 FF       or      ecx, FFFFFFFF
        00405146  |.  F2:AE         repne   scas byte ptr es:[edi]
        00405148  |.  F7D1          not     ecx
        0040514A  |.  49            dec     ecx
        0040514B  |.  80F9 08       cmp     cl, 8
        0040514E  |.  884C24 10     mov     byte ptr [esp+10], cl
        00405152  |.  73 30         jnb     short 00405184                   ;  用户名长度是否等于8
        00405154  |.  8B5424 10     mov     edx, dword ptr [esp+10]
        00405158  |.  BF C0C34000   mov     edi, offset <用户名>                ;  a
        0040515D  |.  81E2 FF000000 and     edx, 0FF
        00405163  |.  83C9 FF       or      ecx, FFFFFFFF
        00405166  |.  81C2 5EB74000 add     edx, 0040B75E                    ;  ASCII "qiufenghan"
        0040516C  |.  F2:AE         repne   scas byte ptr es:[edi]
        0040516E  |.  F7D1          not     ecx
        00405170  |.  2BF9          sub     edi, ecx
        00405172  |.  8BC1          mov     eax, ecx
        00405174  |.  8BF7          mov     esi, edi
        00405176  |.  8BFA          mov     edi, edx
        00405178  |.  C1E9 02       shr     ecx, 2
        0040517B  |.  F3:A5         rep     movs dword ptr es:[edi], dword p>
        0040517D  |.  8BC8          mov     ecx, eax
        0040517F  |.  83E1 03       and     ecx, 3
        00405182  |.  F3:A4         rep     movs byte ptr es:[edi], byte ptr>;  如果用户名长读小于8,则连接用户名。
        00405184  |>  C605 66B74000>mov     byte ptr [40B766], 0             ;  取用户名的前8个字母
       
        ;for(i=0; i<8; i++)
        ;{
        ;  if(code_buf2[i] >= 0x20)
        ;     ebx += code_buf2[i] ^ name_buf2[i];   //route1
        ;  else
        ;     ebx += code_buf2[i] | name_buf2[i];   //route2
        ;}
        ;  后面我们知道,要ebx等于0才算注册成功。ebx的值为8个字节的和,不可能溢出
        ;  所以只能每个加数为0才可以
        ;  因为用户名中不可能有为0的字节,所以只要进入路径2中的值不可能为0,
        ;  所以循环只能完全执行路径一,因为只有两个相同的数异或为0,所以用户名中只能有小写
        ; 字母(字节值大于20h的字母)。其实就是说此时code_buf2的值就是用户名
        0040518B  |.  B9 54B74000   mov     ecx, 0040B754                   ;code_buf2
        00405190  |.  BE 08000000   mov     esi, 8
        00405195  |>  8A01          /mov     al, byte ptr [ecx]
        00405197  |.  3C 20         |cmp     al, 20
        00405199  |.  73 0E         |jnb     short 004051A9
        0040519B  |.  33D2          |xor     edx, edx
        0040519D  |.  25 FF000000   |and     eax, 0FF
        004051A2  |.  8A51 0A       |mov     dl, byte ptr [ecx+A]
        004051A5  |.  0BD0          |or      edx, eax
        004051A7  |.  EB 0C         |jmp     short 004051B5
        004051A9  |>  33D2          |xor     edx, edx
        004051AB  |.  25 FF000000   |and     eax, 0FF
        004051B0  |.  8A51 0A       |mov     dl, byte ptr [ecx+A]
        004051B3  |.  33D0          |xor     edx, eax
        004051B5  |>  03EA          |add     ebp, edx
        004051B7  |.  41            |inc     ecx
        004051B8  |.  4E            |dec     esi
        004051B9  |.^ 75 DA         \jnz     short 00405195
       
        ;如果ebp为0,则认为注册成功
        004051BB  |.  33C0          xor     eax, eax
        004051BD  |.  5F            pop     edi
        004051BE  |.  85ED          test    ebp, ebp
        004051C0  |.  5E            pop     esi
        004051C1  |.  5D            pop     ebp
        004051C2      0F94C0        sete    al
        004051C5  |.  5B            pop     ebx
        004051C6  |.  59            pop     ecx
        004051C7  \.  C3            retn
8、先在我们看看函数00405300做什么事
  00405300  /$  53            push    ebx
        00405301  |.  55            push    ebp
        00405302  |.  8B6C24 10     mov     ebp, dword ptr [esp+10]          ;  arg2
        00405306  |.  56            push    esi
        00405307  |.  57            push    edi
        00405308  |.  8B7C24 14     mov     edi, dword ptr [esp+14]          ;  arg1
        0040530C  |.  33C9          xor     ecx, ecx
        0040530E  |.  2BFD          sub     edi, ebp
        00405310  |.  897C24 18     mov     dword ptr [esp+18], edi          ;  arg2
        00405314  |.  EB 04         jmp     short 0040531A
       
        00405316  |>  8B7C24 18     /mov     edi, dword ptr [esp+18]
        0040531A  |>  8D3429         lea     esi, dword ptr [ecx+ebp]
        0040531D  |.  33D2          |xor     edx, edx
        0040531F  |.  B8 01000000   |mov     eax, 1
        00405324  |.  C74424 14 070>|mov     dword ptr [esp+14], 7           ;  arg1
        0040532C  |.  8A1437        |mov     dl, byte ptr [edi+esi]
        0040532F  |.  8BFA          |mov     edi, edx
        ;求一个数的7次方%0x8899的结果
        00405331  |>  8BD7          |/mov     edx, edi
        00405333  |.  0FAFC2        ||imul    eax, edx
        00405336  |.  3D 99880000   ||cmp     eax, 8899
        0040533B  |.  7E 0A         ||jle     short 00405347
        0040533D  |.  99            ||cdq
        0040533E  |.  BB 99880000   ||mov     ebx, 8899
        00405343  |.  F7FB          ||idiv    ebx
        00405345  |.  8BC2          ||mov     eax, edx
        00405347  |>  8B5424 14     ||mov     edx, dword ptr [esp+14]
        0040534B  |.  4A            ||dec     edx
        0040534C  |.  895424 14     ||mov     dword ptr [esp+14], edx
        00405350  |.^ 75 DF         |\jnz     short 00405331
       
        00405352  |.  99            |cdq
        00405353  |.  BF BB000000   |mov     edi, 0BB
        00405358  |.  F7FF          |idiv    edi
        0040535A  |.  41            |inc     ecx
        0040535B  |.  83F9 08       |cmp     ecx, 8
        0040535E  |.  8816          |mov     byte ptr [esi], dl
        00405360  |.  C60429 00     |mov     byte ptr [ecx+ebp], 0
        00405364  |.^ 7C B0         \jl      short 00405316
        00405366  |.  5F            pop     edi
        00405367  |.  5E            pop     esi
        00405368  |.  5D            pop     ebp
        00405369  |.  5B            pop     ebx
        0040536A  \.  C3            retn
  该函数实际是把参数1中的每个字节的7次方模0x8899的结果再模0xbb的结果保存在参数2中相应的位置。
9、我们再来看看程序中的StrToHex的实现
        004052D0 >/$  8B4C24 04     mov     ecx, dword ptr [esp+4]
        004052D4  |.  8A01          mov     al, byte ptr [ecx]
        004052D6  |.  3C 39         cmp     al, 39
        004052D8  |.  7E 04         jle     short 004052DE
        004052DA  |.  04 C9         add     al, 0C9
        004052DC  |.  EB 02         jmp     short 004052E0
        004052DE  |>  04 D0         add     al, 0D0
        004052E0  |>  8A49 01       mov     cl, byte ptr [ecx+1]
        004052E3  |.  80F9 39       cmp     cl, 39
        004052E6  |.  7E 09         jle     short 004052F1
        004052E8  |.  C0E0 04       shl     al, 4
        004052EB  |.  80E9 37       sub     cl, 37
        004052EE  |.  0AC1          or      al, cl
        004052F0  |.  C3            retn
        004052F1  |>  C0E0 04       shl     al, 4
        004052F4  |.  80E9 30       sub     cl, 30
        004052F7  |.  0AC1          or      al, cl
        004052F9  \.  C3            retn
        可见这个函数功能并不完善,它要求str只能是数字或大写字母
10、先在注册算法清楚了
  a、用户名需要大于等于5各字节,序列号为17个以上字节
  b、用户名小于8个字符时,需要连接自己组成长于8个字符的串,用户名只使用前8个字符。我们称为name。
  c、注册码的第9个字符将被抛弃。
  d、把注册码当作16进制数串恢复为8个字节值,多余的抛弃。我们称为code,
  e、(pow(code[i] ^ (0x50 + i), 7) % 0x8899 ) % 0xBB == name[i]
11、一个注册机参考实现如下:
        int APIs32KeyGen(char* name)
        {
                int len = strlen(name);
                if(len< 5)
                {
                        printf("用户名长度必须大于4.\n");
                        return 1;
                }
       
       
                char* lName = new char[len * 2 + 1];
                if(lName == NULL)
                {
                        printf("内存不足.\n");
                        return 1;
                }
       
                //TODO check是否全为小写字母
       
                ::strcpy(lName, name);
                ::strcpy(lName + len, name);
                lName[len * 2] = '\0';
       
                unsigned char res[8];
                bool find = true;
                for(int n=0; n <8; n++)
                {
                        find = false;
                        for(unsigned char i=2; i<=0xFF; i++)
                        {
                                unsigned int k = 1;
                                for(int m=0; m<7; m++)
                                {
                                        k *= i;
                                        if(k > 0x8899)
                                        {
                                                k %= 0x8899;
                                        }
                                }
                                if((k % 0xBB) == lName[n])
                                {
                                        res[n] = i ^ (0x50 + n);
                                        find = true;
                                        break;
                                }
                        }
       
                        if(find == false)
                        {
                                break;
                        }
       
                }
       
                if(find)
                {
                        printf("用户名%s的注册码为:", name);
                        char buf[18];
                        ::sprintf(buf, "%02x%02x%02x%02x=%02x%02x%02x%02x", res[0], res[1], res[2], res[3], res[4], res[5], res[6], res[7]);
                        ::strupr(buf);
                        printf("%s", buf);
                }
                else
                {
                        printf("未能为用户名%s找到注册码", name);
                }
                printf("\n");
       
                delete [] lName;
                return 0;
        }

12、终于完成了。
   

--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年01月07日 下午 07:36:12

[公告][征集寄语] 看雪20周年年会 | 感恩有你,一路同行

最新回复 (1)
hezhichun 2009-6-1 16:07
2
0
这个程序不支持XP啊,怎么解决,谁知道
游客
登录 | 注册 方可回帖
返回