TA的每日心情 | 开心 2018-12-18 12:34 |
---|
签到天数: 4 天 [LV.2]偶尔看看I
|
【文章标题】: 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 00F31EC8 ASCII "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 0052930A SE处理程序
**********************************************************************************************************************************
“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:[eax], edx
**************************************************************************************************************************************
向上看,没有跳转可以跳过此对话框。还要继续回溯关键处。可以找到段首下断回溯,这里使用一种快捷些的方法。
向下翻堆栈,找到
0012D5CC |00F34C4C ASCII "Username or Private Key don't match.",CR,"Please check your entry."
0012D5D0 |0012D601
0012D5D4 |00F31EC8 ASCII "Warning"
0012D5D8 |0004D87C
0012D5DC |00F34C4C ASCII "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 [ebp-108], ecx
00514A66 |. 894D FC mov dword ptr [ebp-4], 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:[eax]
00514A76 |. 64:8920 mov dword ptr fs:[eax], esp
00514A79 |. 8D55 FC lea edx, dword ptr [ebp-4]
00514A7C |. 8B83 EC020000 mov eax, dword ptr [ebx+2EC]
00514A82 |. E8 D908F2FF call 00435360
00514A87 |. 8B55 FC mov edx, dword ptr [ebp-4] ; 用户名
00514A8A |. A1 388D5300 mov eax, dword ptr [538D38]
00514A8F |. E8 00F2EEFF call 00403C94
00514A94 |. 8D55 FC lea edx, dword ptr [ebp-4]
00514A97 |. 8B83 F0020000 mov eax, dword ptr [ebx+2F0]
00514A9D |. E8 BE08F2FF call 00435360
00514AA2 |. 8B45 FC mov eax, dword ptr [ebp-4] ; 试炼码
00514AA5 |. 33D2 xor edx, edx
00514AA7 |. E8 8C41EFFF call 00408C38 ; 试炼码字符串转为整数保存在eax
00514AAC |. 8B15 248F5300 mov edx, dword ptr [538F24] ; MrPix.0053D728
00514AB2 |. 8902 mov dword ptr [edx], eax ; eax值传到edx内指向的地址内
00514AB4 |. 8D85 FCFEFFFF lea eax, dword ptr [ebp-104]
00514ABA |. 8B15 388D5300 mov edx, dword ptr [538D38] ; MrPix.0053D724
00514AC0 |. 8B12 mov edx, dword ptr [edx] ; 用户名
00514AC2 |. B9 FF000000 mov ecx, 0FF ; 0FFh即十进制256
00514AC7 |. E8 CCF3EEFF call 00403E98 ; 取用户名长度,如果超过256位,按256位计算
00514ACC |. 8D85 FCFEFFFF lea eax, dword ptr [ebp-104]
00514AD2 |. 8B15 248F5300 mov edx, dword ptr [538F24] ; MrPix.0053D728
00514AD8 |. 66:8B12 mov dx, word ptr [edx] ; 试炼码转换的整数值放入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 [ebp-104]
00514AEC |. 50 push eax
00514AED |. A1 CC8D5300 mov eax, dword ptr [538DCC]
00514AF2 |. 8B00 mov eax, dword ptr [eax]
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 [ebp-104]
00514B09 |. 8D85 F8FEFFFF lea eax, dword ptr [ebp-108]
00514B0F |. E8 4CF3EEFF call 00403E60
00514B14 |. 8B85 F8FEFFFF mov eax, dword ptr [ebp-108]
00514B1A |. 66:8B0D E44B5>mov cx, word ptr [514BE4]
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 [ebp-104]
00514B32 |. 50 push eax
00514B33 |. A1 CC8D5300 mov eax, dword ptr [538DCC]
00514B38 |. 8B00 mov eax, dword ptr [eax]
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 [ebp-104]
00514B4F |. 8D85 F8FEFFFF lea eax, dword ptr [ebp-108]
00514B55 |. E8 06F3EEFF call 00403E60
00514B5A |. 8B85 F8FEFFFF mov eax, dword ptr [ebp-108]
00514B60 |. 66:8B0D E44B5>mov cx, word ptr [514BE4]
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:[eax], edx
00514B76 |. 68 964B5100 push 00514B96
00514B7B |> 8D85 F8FEFFFF lea eax, dword ptr [ebp-108]
00514B81 |. E8 BAF0EEFF call 00403C40
00514B86 |. 8D45 FC lea eax, dword ptr [ebp-4]
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 [esp]
0050AC2B |. 33C9 xor ecx, ecx
0050AC2D |. 8A0E mov cl, byte ptr [esi] ; 用户名长度传入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 [edi], cl ; 用户名长度传送
0050AC38 |. 46 inc esi ; esi增1
0050AC39 |. 47 inc edi ; edi增1
0050AC3A |. F3:A4 rep movs byte ptr es:[edi], 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 [esp]
0050AC67 |. 33C9 xor ecx, ecx
0050AC69 |. 8A0E mov cl, byte ptr [esi]
0050AC6B |. 80F9 14 cmp cl, 14
0050AC6E |. 72 02 jb short 0050AC72
0050AC70 |. B1 14 mov cl, 14
0050AC72 |> 880F mov byte ptr [edi], cl
0050AC74 |. 46 inc esi
0050AC75 |. 47 inc edi
0050AC76 |. F3:A4 rep movs byte ptr es:[edi], 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 82DE xor 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 [esp]
0050AB9F |. 33C9 xor ecx, ecx
0050ABA1 |. 8A0E mov cl, byte ptr [esi]
0050ABA3 |. 80F9 14 cmp cl, 14
0050ABA6 |. 72 02 jb short 0050ABAA
0050ABA8 |. B1 14 mov cl, 14
0050ABAA |> 880F mov byte ptr [edi], cl
0050ABAC |. 46 inc esi
0050ABAD |. 47 inc edi
0050ABAE |. F3:A4 rep movs byte ptr es:[edi], byte ptr>
0050ABB0 |. 8D5424 18 lea edx, dword ptr [esp+18]
0050ABB4 |. 8BC4 mov eax, esp
0050ABB6 |. E8 91FEFFFF call 0050AA4C ; 用户名长度小于4,则后面用'0'补充为4位
0050ABBB |. 8D5424 18 lea edx, dword ptr [esp+18]
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 [esp] ; 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 [esp+1] ; 用户名地址传入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 [ecx] ; 用户名逐位送入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[30]={'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 [name+ecx]
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);
} |
|