穷举法破解 zebrone1.1

时间:2023-03-08 15:47:29

系统 : Windows xp

程序 : zebrone1.1

程序下载地址 :http://pan.baidu.com/s/1boqVcU7

要求 : 编写注册机

使用工具 :OD

可在看雪论坛中查找关于此程序的讨论:传送门

用OD载入程序,查找字串发现成功提示“congratulations, you have cracked the zebra crackme ver 1.1”,双击定位该字串:

004012AA  |> \6A 0A         push    0A                               ; /Count = A (10.); Case 1 of switch 0040128D
004012AC |. 8D45 EC lea eax, dword ptr [ebp-] ; |
004012AF |. push eax ; |Buffer
004012B0 |. 6A push ; |ControlID = 65 (101.)
004012B2 |. FF75 push dword ptr [ebp+] ; |hWnd
004012B5 |. E8 F2010000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004012BA |. 6A 0A push 0A ; /Count = A (10.)
004012BC |. 8D45 F6 lea eax, dword ptr [ebp-A] ; |
004012BF |. push eax ; |Buffer
004012C0 |. 6A push ; |ControlID = 66 (102.)
004012C2 |. FF75 push dword ptr [ebp+] ; |hWnd
004012C5 |. E8 E2010000 call <jmp.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004012CA |. 8D45 F6 lea eax, dword ptr [ebp-A] ; 取序列号
004012CD |. push eax ; 序列号入栈
004012CE |. 8D45 EC lea eax, dword ptr [ebp-] ; 取用户名
004012D1 |. push eax ; 用户名入栈
004012D2 |. E8 call 0040134A
004012D7 |. 83C4 add esp, ; 平衡堆栈
004012DA |. 09C0 or eax, eax ; eax 为 0?
004012DC |. je short 004012F4 ; 为0 则错误。
004012DE |. 6A push ; /Style = MB_OK|MB_APPLMODAL
004012E0 |. push ; |great !!!
004012E5 |. push ; |congratulations, you have cracked the zebra crackme ver 1.1
004012EA |. FF75 push dword ptr [ebp+] ; |hOwner
004012ED |. E8 C6010000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
004012F2 |. EB jmp short
004012F4 |> 6A push ; /Style = MB_OK|MB_APPLMODAL
004012F6 |. F8314000 push 004031F8 ; |hmmmm :p
004012FB |. push ; |Text = "Sorry... The Serial isn't correct :?
|. FF75 push dword ptr [ebp+] ; |hOwner
|. E8 B0010000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA

跟入关键call:

0040134A  /$              push    ebp
0040134B |. 89E5 mov ebp, esp
0040134D |. 83EC sub esp, ; ↓将用户名字串转化为浮点数
|. FF75 push dword ptr [ebp+] ; /s
|. E8 call <jmp.&CRTDLL.atof> ; \atof
|. DD55 E8 fst qword ptr [ebp-] ; 保存转化结果
0040135B |. 83EC sub esp, ; 开辟内存
0040135E |. DD1C24 fstp qword ptr [esp] ; 保存转化结果并弹栈
|. E8 call <jmp.&CRTDLL.floor> ; 向下取整
|. DD5D F8 fstp qword ptr [ebp-] ; ↓将序列号转化为浮点数
|. FF75 0C push dword ptr [ebp+C] ; /s
0040136C |. E8 5F010000 call <jmp.&CRTDLL.atof> ; \atof
|. DD55 D8 fst qword ptr [ebp-] ; 保存转化后的序列号
|. 83EC sub esp, ; 平衡堆栈
|. DD1C24 fstp qword ptr [esp] ; 将结果入栈
0040137A |. E8 call <jmp.&CRTDLL.floor> ; 向下取整
0040137F |. 83C4 add esp, ; 平衡堆栈
|. DD55 F0 fst qword ptr [ebp-] ; 保存取整结果
|. DC4D F8 fmul qword ptr [ebp-] ; 乘以用户名
|. D9EE fldz ; 载入0
0040138A |. DED9 fcompp ; 比较st(0)st(1),并弹出寄存器堆栈
0040138C |. DFE0 fstsw ax ; 把该状态寄存器的值传送给通用寄存器AX
0040138E |. 9E sahf ; 标志传送指令
0040138F |. jnz short ; st0和st1相等?
|. 31C0 xor eax, eax ; 清空eax
|. E9 jmp 0040142E ; 函数结束
|> DD45 F8 fld qword ptr [ebp-] ; 用户名浮点数入栈
0040139B |. DC5D F0 fcomp qword ptr [ebp-] ; 与序列号浮点数比较
0040139E |. DFE0 fstsw ax
004013A0 |. 9E sahf
004013A1 |. jnz short 004013AA ; 用户名浮点数与序列号浮点数相等则函数结束
004013A3 |. 31C0 xor eax, eax ; 清空eax
004013A5 |. E9 jmp 0040142E ; 函数结束
004013AA |> DD45 F8 fld qword ptr [ebp-] ; 用户名浮点数入栈
004013AD |. DD5D C8 fstp qword ptr [ebp-] ; 保存用户名浮点数
004013B0 |. D9E8 fld1 ; 1入栈
004013B2 |. DD55 C0 fst qword ptr [ebp-] ; 保存1
004013B5 |. DC5D C8 fcomp qword ptr [ebp-] ; 1 > 用户名浮点数?
004013B8 |. DFE0 fstsw ax
004013BA |. 9E sahf
004013BB |. 2D ja short 004013EA ; 是则错误
004013BD |. DF2D fild qword ptr [] ; 载入10的10次方
004013C3 |. DD55 B8 fst qword ptr [ebp-] ; 保存
004013C6 |. DC5D C8 fcomp qword ptr [ebp-] ; 10的10次方 < 用户名浮点数?
004013C9 |. DFE0 fstsw ax
004013CB |. 9E sahf
004013CC |. 1C jb short 004013EA ; 是则错误
004013CE |. DD45 F0 fld qword ptr [ebp-] ; 序列号浮点数入栈
004013D1 |. DD5D B0 fstp qword ptr [ebp-] ; 保存
004013D4 |. DD45 C0 fld qword ptr [ebp-] ; 用户名浮点数入栈
004013D7 |. DC5D B0 fcomp qword ptr [ebp-] ; 用户名浮点数 > 序列号浮点数?
004013DA |. DFE0 fstsw ax
004013DC |. 9E sahf
004013DD |. 0B ja short 004013EA ; 是则错误
004013DF |. DD45 B8 fld qword ptr [ebp-] ; 载入10的10次方
004013E2 |. DC5D B0 fcomp qword ptr [ebp-] ; 10的10次方 >= 序列号浮点数?
004013E5 |. DFE0 fstsw ax
004013E7 |. 9E sahf
004013E8 |. jnb short 004013EE ; 是则继续流程
004013EA |> 31C0 xor eax, eax ; 清空eax
004013EC |. EB jmp short 0040142E ; 函数结束
004013EE |> DD45 F8 fld qword ptr [ebp-] ; 用户名浮点数入栈
004013F1 |. D9FE fsin ; 计算栈顶的正弦函数
004013F3 |. DD5D A8 fstp qword ptr [ebp-] ; 保存结果
004013F6 |. DD45 F0 fld qword ptr [ebp-] ; 序列号浮点数入栈
004013F9 |. D9FE fsin ; 计算栈顶的正弦函数
004013FB |. DD5D A0 fstp qword ptr [ebp-] ; 保存结果
004013FE |. DD45 A8 fld qword ptr [ebp-] ; 用户名正弦值入栈
|. DC4D A0 fmul qword ptr [ebp-] ; 乘以 序列号正弦值
|. DF2D fild qword ptr [] ; 10的16次方入栈
0040140A |. DEC9 fmulp st(), st ; 再相乘
0040140C |. 83EC sub esp, ; 开辟8个字节的空间
0040140F |. DD1C24 fstp qword ptr [esp] ; 保存结果
|. E8 D1000000 call <jmp.&CRTDLL.floor> ; 向下取整
|. 83C4 add esp,
0040141A |. DD5D fstp qword ptr [ebp-] ; 保存
0040141D |. D9EE fldz ; 载入0
0040141F |. DC5D fcomp qword ptr [ebp-] ; 结果是否为0?
|. DFE0 fstsw ax
|. 9E sahf ; (initial cpu selection)
|. jnz short 0040142C ; 不为0则失败
|. 31C0 xor eax, eax
|. inc eax
0040142A |. EB jmp short 0040142E
0040142C |> 31C0 xor eax, eax
0040142E |> C9 leave
0040142F \. C3 retn

这里的Sin指令是按弧度制算的,所以想用180的倍数充当乘数是不行的,我们只能遍历[1,10^10],找出其中正弦值为正数且正弦值小于10^-8的实数。这样的两个实数相乘再乘以10的16次方的乘积就满足了条件。{ x | 0 < x < 1 }

动手编写程序,验证我们的猜想:

穷举法破解 zebrone1.1

穷举法破解 zebrone1.1

=========================十年后============================》

穷举法破解 zebrone1.1

穷举法破解 zebrone1.1

穷举法破解 zebrone1.1

好吧。。。肯定是哪儿出问题了,经过Debug之后源程序如下:

#include <iostream>
#include <math.h>
#include <iomanip> // 精度控制头文件 using namespace std; inline double Sin( double Var ) //内联Sin指令
{
__asm{
fld Var
fsin
fstp Var
} return Var;
} int main( void )
{
double i,j,res;
const double min = 1e-; cout << "Valid number:" << endl; for ( i = ; i <= 1e+ ; i++ ){
res = Sin( i ); //接受正弦值。 bool Flag = false;
__asm{
push eax fld res //载入正弦值
fldz //载入0
fcompp //0 < 正弦值?
fstsw ax
sahf
jnb s //不小于则跳转
fld res //载入正弦值
fcomp min //正弦值 < min?
fstsw ax
sahf
jnb s //不小于则跳转
mov Flag, s: pop eax
} if ( Flag )
cout << setprecision() << i <<endl;
} cout << "Done." << endl; return ;
}

运行效果:

穷举法破解 zebrone1.1

但经过测试发现,算出的数中 大于 10的9次方的数的Sin值与zebrone1.1的Sin值有偏差,所以有效的数值有:


随便取出两个按照 升序填入:

穷举法破解 zebrone1.1

就注册成功了:

穷举法破解 zebrone1.1