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);
} good job 。。。/:001 牛人呀!多发破文/:013 /:013
页:
[1]