qifeon 发表于 2008-9-3 16:51:55

Mister PiX 算法的简单分析

【文章标题】: Mister PiX 算法的简单分析
【文章作者】: qifeon
【软件名称】: Mister PiX 2.10
【下载地址】: 自己搜索下载
【保护方式】: 注册码
【使用工具】: od,peid
【操作平台】: winxp sp2
【软件介绍】: 可以在 newsgroup 里面寻找指定的图片。
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
一、分析过程

1、Peid查壳,显示无壳。编程语言为Borland Delphi 4.0 - 5.0。

2、试运行,输入“qifeon,12345”,有错误提示“”。

3、od载入,查找字符串,没找到。Delphi程序,找到关键点方法很多,如按钮事件代码,F12暂停法等。这里我们使用下API函数下断的方法。

既然有错误对话框,可以考虑使用MessageBoxExA或MessageBoxA,具体用哪个,需要测试,try and error。

*****************************************************************************************************************************

ctrl+N,找到名称位于 MrPix, 条目 309
   地址=0053E644
   区段=.idata
   类型=输入    (已知)
   名称=user32.MessageBoxExA

******************************************************************************************************************************

右键“在输入函数上下断”,然后F9运行,出现异常,SHIFT+F9几次,出现注册框,输入“qifeon,12345”,点确定

程序断下在系统领空,看堆栈

*******************************************************************************************************************************

0012D4A4   00F31EC8ASCII "Warning"
0012D4A8   005292EA/CALL 到 MessageBoxExA 来自 MrPix.005292E5
0012D4AC   000D0540|hOwner = 000D0540 ('Mister PiX',class='TApplication')
0012D4B0   00F34C4C|Text = "Username or Private Key don't match.",CR,"Please check your entry."
0012D4B4   00F31EC8|Title = "Warning"
0012D4B8   00000030|Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
0012D4BC   00120409\LanguageID = 120409 (LANG_ENGLISH)
0012D4C0   0012D5EC指向下一个 SEH 记录的指针
0012D4C4   0052930ASE处理程序

**********************************************************************************************************************************

“Alt+F9”返回,点错误对话框后程序返回到自己代码内

***********************************************************************************************************************************
005292E5|.E8 9EE1EDFF   call    <jmp.&user32.MessageBoxExA>      ; \MessageBoxExA
005292EA|.8BD8          mov   ebx, eax                           返回处
005292EC|.33C0          xor   eax, eax
005292EE|.5A            pop   edx
005292EF|.59            pop   ecx
005292F0|.59            pop   ecx
005292F1|.64:8910       mov   dword ptr fs:, edx

**************************************************************************************************************************************

向上看,没有跳转可以跳过此对话框。还要继续回溯关键处。可以找到段首下断回溯,这里使用一种快捷些的方法。

向下翻堆栈,找到

0012D5CC|00F34C4CASCII "Username or Private Key don't match.",CR,"Please check your entry."
0012D5D0|0012D601
0012D5D4|00F31EC8ASCII "Warning"
0012D5D8|0004D87C
0012D5DC|00F34C4CASCII "Username or Private Key don't match.",CR,"Please check your entry."
0012D5E0|0012D704
0012D5E4|00514B6E返回到 MrPix.00514B6E 来自 MrPix.00529134
0012D5E8|00000000

******************************************************************************************************************************************

0左键点击012D5E4处,右键“反汇编窗口跟随”来到

********************************************************************************************************************************************

00514A54/.55            push    ebp                           段首
00514A55|.8BEC          mov   ebp, esp
00514A57|.81C4 F8FEFFFF add   esp, -108
00514A5D|.53            push    ebx
00514A5E|.33C9          xor   ecx, ecx
00514A60|.898D F8FEFFFF mov   dword ptr , ecx
00514A66|.894D FC       mov   dword ptr , ecx
00514A69|.8BD8          mov   ebx, eax
00514A6B|.33C0          xor   eax, eax
00514A6D|.55            push    ebp
00514A6E|.68 8F4B5100   push    00514B8F
00514A73|.64:FF30       push    dword ptr fs:
00514A76|.64:8920       mov   dword ptr fs:, esp
00514A79|.8D55 FC       lea   edx, dword ptr
00514A7C|.8B83 EC020000 mov   eax, dword ptr
00514A82|.E8 D908F2FF   call    00435360
00514A87|.8B55 FC       mov   edx, dword ptr          ;用户名
00514A8A|.A1 388D5300   mov   eax, dword ptr
00514A8F|.E8 00F2EEFF   call    00403C94
00514A94|.8D55 FC       lea   edx, dword ptr
00514A97|.8B83 F0020000 mov   eax, dword ptr
00514A9D|.E8 BE08F2FF   call    00435360
00514AA2|.8B45 FC       mov   eax, dword ptr          ;试炼码
00514AA5|.33D2          xor   edx, edx
00514AA7|.E8 8C41EFFF   call    00408C38                         ;试炼码字符串转为整数保存在eax
00514AAC|.8B15 248F5300 mov   edx, dword ptr           ;MrPix.0053D728
00514AB2|.8902          mov   dword ptr , eax             ;eax值传到edx内指向的地址内
00514AB4|.8D85 FCFEFFFF lea   eax, dword ptr
00514ABA|.8B15 388D5300 mov   edx, dword ptr           ;MrPix.0053D724
00514AC0|.8B12          mov   edx, dword ptr              ;用户名
00514AC2|.B9 FF000000   mov   ecx, 0FF                         ;0FFh即十进制256
00514AC7|.E8 CCF3EEFF   call    00403E98                         ;取用户名长度,如果超过256位,按256位计算
00514ACC|.8D85 FCFEFFFF lea   eax, dword ptr
00514AD2|.8B15 248F5300 mov   edx, dword ptr           ;MrPix.0053D728
00514AD8|.66:8B12       mov   dx, word ptr                ;试炼码转换的整数值放入dx
00514ADB|.E8 4061FFFF   call    0050AC20                         ;关键CALL
00514AE0|.84C0          test    al, al                           ;标志位: al=1则注册成功, al=0则失败
00514AE2|.74 46         je      short 00514B2A                   ;关键跳转
00514AE4|.6A 00         push    0
00514AE6|.8D85 FCFEFFFF lea   eax, dword ptr
00514AEC|.50            push    eax
00514AED|.A1 CC8D5300   mov   eax, dword ptr
00514AF2|.8B00          mov   eax, dword ptr
00514AF4|.B9 9C4B5100   mov   ecx, 00514B9C                  ;:mister pix wurde erfolgreich freigeschaltet.\nvielen dank!
00514AF9|.BA D84B5100   mov   edx, 00514BD8                  ;ASCII 08,"UnlockOK"
00514AFE|.E8 B9720100   call    0052BDBC
00514B03|.8D95 FCFEFFFF lea   edx, dword ptr
00514B09|.8D85 F8FEFFFF lea   eax, dword ptr
00514B0F|.E8 4CF3EEFF   call    00403E60
00514B14|.8B85 F8FEFFFF mov   eax, dword ptr
00514B1A|.66:8B0D E44B5>mov   cx, word ptr
00514B21|.B2 02         mov   dl, 2
00514B23|.E8 0C460100   call    00529134
00514B28|.EB 44         jmp   short 00514B6E
00514B2A|>6A 00         push    0
00514B2C|.8D85 FCFEFFFF lea   eax, dword ptr
00514B32|.50            push    eax
00514B33|.A1 CC8D5300   mov   eax, dword ptr
00514B38|.8B00          mov   eax, dword ptr
00514B3A|.B9 E84B5100   mov   ecx, 00514BE8                  ;ASCII "PBenutzername oder Private Key stimmen nicht.\nBitte 黚erpr黤en Sie Ihre Eingabe."
00514B3F|.BA 3C4C5100   mov   edx, 00514C3C                  ;\nunlockfail
00514B44|.E8 73720100   call    0052BDBC
00514B49|.8D95 FCFEFFFF lea   edx, dword ptr
00514B4F|.8D85 F8FEFFFF lea   eax, dword ptr
00514B55|.E8 06F3EEFF   call    00403E60
00514B5A|.8B85 F8FEFFFF mov   eax, dword ptr
00514B60|.66:8B0D E44B5>mov   cx, word ptr
00514B67|.33D2          xor   edx, edx
00514B69|.E8 C6450100   call    00529134
00514B6E|>33C0          xor   eax, eax                         ;返回处
00514B70|.5A            pop   edx
00514B71|.59            pop   ecx
00514B72|.59            pop   ecx
00514B73|.64:8910       mov   dword ptr fs:, edx
00514B76|.68 964B5100   push    00514B96
00514B7B|>8D85 F8FEFFFF lea   eax, dword ptr
00514B81|.E8 BAF0EEFF   call    00403C40
00514B86|.8D45 FC       lea   eax, dword ptr
00514B89|.E8 B2F0EEFF   call    00403C40
00514B8E\.C3            retn

**************************************************************************************************************************************************************
显然,这里就是关键了。回溯的方法常常在调试里用到,段首下断就可以反复调试了。

段首下断后运行中断后,单步

00514ADB处进入   call    0050AC20

****************************************************************************************************************************************************************

0050AC20/$53            push    ebx
0050AC21|.56            push    esi
0050AC22|.57            push    edi
0050AC23|.83C4 E8       add   esp, -18
0050AC26|.8BF0          mov   esi, eax                         ;用户名地址和长度传入esi
0050AC28|.8D3C24      lea   edi, dword ptr
0050AC2B|.33C9          xor   ecx, ecx
0050AC2D|.8A0E          mov   cl, byte ptr                ;用户名长度传入cl
0050AC2F|.80F9 14       cmp   cl, 14                           ;比较用户名长度是否小于20位?
0050AC32|.72 02         jb      short 0050AC36                   ;小于或等于按实际长度计算
0050AC34|.B1 14         mov   cl, 14                           ;大于20位则只取前20位
0050AC36|>880F          mov   byte ptr , cl               ;用户名长度传送
0050AC38|.46            inc   esi                              ;esi增1
0050AC39|.47            inc   edi                              ;edi增1
0050AC3A|.F3:A4         rep   movs byte ptr es:, byte ptr>;用户名传送到edi指向地址内
0050AC3C|.8BDA          mov   ebx, edx
0050AC3E|.E8 D1FFFFFF   call    0050AC14                         ;生成注册框内显示的pubkey,我们直接利用,算法此处不探讨。
0050AC43|.8BD0          mov   edx, eax                         ;edx=eax=pubkey
0050AC45|.8BC4          mov   eax, esp
0050AC47|.E8 10000000   call    0050AC5C                         ;算法CALL
0050AC4C|.66:3BD8       cmp   bx, ax                           ;真码与假码相比较
0050AC4F|.0F94C0      sete    al                               ;相等则置al=1,否则为0
0050AC52|.83C4 18       add   esp, 18
0050AC55|.5F            pop   edi
0050AC56|.5E            pop   esi
0050AC57|.5B            pop   ebx
0050AC58\.C3            retn

*********************************************************************************************************************************

单步,0050AC47处进入   call    0050AC5C

***********************************************************************************************************************************

0050AC5C/$53            push    ebx
0050AC5D|.56            push    esi
0050AC5E|.57            push    edi
0050AC5F|.83C4 E8       add   esp, -18
0050AC62|.8BF0          mov   esi, eax                         ;用户名
0050AC64|.8D3C24      lea   edi, dword ptr
0050AC67|.33C9          xor   ecx, ecx
0050AC69|.8A0E          mov   cl, byte ptr
0050AC6B|.80F9 14       cmp   cl, 14
0050AC6E|.72 02         jb      short 0050AC72
0050AC70|.B1 14         mov   cl, 14
0050AC72|>880F          mov   byte ptr , cl
0050AC74|.46            inc   esi
0050AC75|.47            inc   edi
0050AC76|.F3:A4         rep   movs byte ptr es:, byte ptr>
0050AC78|.8BDA          mov   ebx, edx                         ;ebx=edx=pubkey
0050AC7A|.8BC4          mov   eax, esp                         ;用户名及长度地址传入eax
0050AC7C|.E8 13FFFFFF   call    0050AB94                         ;算法CALL
0050AC81|.66:81F3 82DExor   bx, 0DE82                        ;bx= bx xor 0DE82h
0050AC86|.66:33C3       xor   ax, bx                           ;ax=ax xor bx
0050AC89|.83C4 18       add   esp, 18
0050AC8C|.5F            pop   edi
0050AC8D|.5E            pop   esi
0050AC8E|.5B            pop   ebx
0050AC8F\.C3            retn

**********************************************************************************************************************

0050AC7C处进入call    0050AB94

************************************************************************************************************************

0050AB94/$53            push    ebx
0050AB95|.56            push    esi
0050AB96|.57            push    edi
0050AB97|.83C4 D0       add   esp, -30
0050AB9A|.8BF0          mov   esi, eax
0050AB9C|.8D3C24      lea   edi, dword ptr
0050AB9F|.33C9          xor   ecx, ecx
0050ABA1|.8A0E          mov   cl, byte ptr
0050ABA3|.80F9 14       cmp   cl, 14
0050ABA6|.72 02         jb      short 0050ABAA
0050ABA8|.B1 14         mov   cl, 14
0050ABAA|>880F          mov   byte ptr , cl
0050ABAC|.46            inc   esi
0050ABAD|.47            inc   edi
0050ABAE|.F3:A4         rep   movs byte ptr es:, byte ptr>
0050ABB0|.8D5424 18   lea   edx, dword ptr
0050ABB4|.8BC4          mov   eax, esp
0050ABB6|.E8 91FEFFFF   call    0050AA4C                         ;用户名长度小于4,则后面用'0'补充为4位
0050ABBB|.8D5424 18   lea   edx, dword ptr
0050ABBF|.8BC4          mov   eax, esp
0050ABC1|.B1 14         mov   cl, 14
0050ABC3|.E8 847FEFFF   call    00402B4C
0050ABC8|.66:BE 0100    mov   si, 1                            ;si=1
0050ABCC|.33DB          xor   ebx, ebx
0050ABCE|.8A1C24      mov   bl, byte ptr                ;bl为用户名长度
0050ABD1|.85DB          test    ebx, ebx                         ;用户名是否为空?
0050ABD3|.76 25         jbe   short 0050ABFA
0050ABD5|.BF 01000000   mov   edi, 1                           ;edi=1
0050ABDA|.8D4C24 01   lea   ecx, dword ptr          ;用户名地址传入ecx
0050ABDE|>0FB7C6      /movzx   eax, si                         ;eax=si,初始值为1
0050ABE1|.40            |inc   eax                           ;eax增1
0050ABE2|.33D2          |xor   edx, edx                        ;edx清零
0050ABE4|.8A11          |mov   dl, byte ptr             ;用户名逐位送入dl
0050ABE6|.F7EA          |imul    edx                           ;eax=eax * edx
0050ABE8|.F7EF          |imul    edi                           ;eax=eax * edi
0050ABEA|.BE FFFF0000   |mov   esi, 0FFFF                      ;esi=0FFFFh
0050ABEF|.33D2          |xor   edx, edx                        ;edx清零
0050ABF1|.F7F6          |div   esi                           ;eax除以esi,商保存在eax,余数保存在edx
0050ABF3|.8BF2          |mov   esi, edx                        ;edx值传入esi
0050ABF5|.47            |inc   edi                           ;edi增1
0050ABF6|.41            |inc   ecx                           ;ecx增1
0050ABF7|.4B            |dec   ebx                           ;ebx减1
0050ABF8|.^ 75 E4         \jnz   short 0050ABDE                  ;ebx值不为0则继续循环
0050ABFA|>8BC6          mov   eax, esi                         ;最后计算值传送入eax
0050ABFC|.83C4 30       add   esp, 30
0050ABFF|.5F            pop   edi
0050AC00|.5E            pop   esi
0050AC01|.5B            pop   ebx
0050AC02\.C3            retn

*****************************************************************************************************************************

二、算法总结

       注册码private key 由 public key 及 用户名name经计算而生成,根据用户名name长度,又分为3种情况;

1、用户名长度小于4,则后面用'0'补充为4位,参与计算;

   这个限制不明显,跟了几次才看到。容易漏掉。测试了一个国外的注册机。这点就被忽略了,算出来就是错误的了。

2、用户名长度大于20则只取前20位参与计算,后面不参与验证。(用户名长度大于256,按256操作);

3、用户名长度在4-20,则正常计算。


**************************************************************************************************************************************

三、C语言注册机代码

   偷了点懒,从程序提取部分汇编代码嵌在里面。

#include "stdio.h"
#include "string.h"
void main()
{
        static char name={'0','0','0','0'};
        int pubkey,reg,len;
        printf("please enter your name:");
        scanf("%s",name);
        printf("please enter your public key:");
        scanf("%d",&pubkey);
        len=strlen(name);
        if (len>=20)
        len=20;
        else if(len<4)
        {*(name+4)='\0';
       *(name+len)='0';       
         len=4;}
       
                _asm
        {
               
                mov ebx,len
                mov edi,1
                mov si,1
                mov ecx,0                       
                n1:
                  movzx   eax, si
                  inc   eax
                  xor   edx, edx
                  mov   dl, byte ptr
                  imul    edx
                  imul    edi
                  mov   esi, 0xFFFF
                  xor   edx, edx                     
                  div   esi
                  mov   esi, edx
                  nc   edi
                  inc   ecx
                  dec   ebx
               jnz n1
             xor esi,0xDE82
             xor esi,pubkey
             mov reg,esi
               
               
        }
       

        printf("Private key is:%d",reg);
      
}

Luckly 发表于 2008-9-3 19:26:07

good job 。。。/:001

天蓝小色色 发表于 2008-9-7 14:35:12

牛人呀!多发破文/:013 /:013
页: [1]
查看完整版本: Mister PiX 算法的简单分析