系统 : 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-14] ; |
004012AF |. 50 push eax ; |Buffer
004012B0 |. 6A 65 push 65 ; |ControlID = 65 (101.)
004012B2 |. FF75 08 push dword ptr [ebp+8] ; |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 |. 50 push eax ; |Buffer
004012C0 |. 6A 66 push 66 ; |ControlID = 66 (102.)
004012C2 |. FF75 08 push dword ptr [ebp+8] ; |hWnd
004012C5 |. E8 E2010000 call <jmp.&USER32.GetDlgItemTextA> ; GetDlgItemTextA
004012CA |. 8D45 F6 lea eax, dword ptr [ebp-A] ; 取序列号
004012CD |. 50 push eax ; 序列号入栈
004012CE |. 8D45 EC lea eax, dword ptr [ebp-14] ; 取用户名
004012D1 |. 50 push eax ; 用户名入栈
004012D2 |. E8 73000000 call 0040134A
004012D7 |. 83C4 08 add esp, 8 ; 平衡堆栈
004012DA |. 09C0 or eax, eax ; eax 为 0?
004012DC |. 74 16 je short 004012F4 ; 为0 则错误。
004012DE |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
004012E0 |. 68 26324000 push 00403226 ; |great !!!
004012E5 |. 68 30324000 push 00403230 ; |congratulations, you have cracked the zebra crackme ver 1.1
004012EA |. FF75 08 push dword ptr [ebp+8] ; |hOwner
004012ED |. E8 C6010000 call <jmp.&USER32.MessageBoxA> ; MessageBoxA
004012F2 |. EB 14 jmp short 00401308
004012F4 |> 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
004012F6 |. 68 F8314000 push 004031F8 ; |hmmmm :p
004012FB |. 68 01324000 push 00403201 ; |Text = "Sorry... The Serial isn't correct :?
00401300 |. FF75 08 push dword ptr [ebp+8] ; |hOwner
00401303 |. E8 B0010000 call <jmp.&USER32.MessageBoxA> ; MessageBoxA
跟入关键call:
0040134A /$ 55 push ebp
0040134B |. 89E5 mov ebp, esp
0040134D |. 83EC 68 sub esp, 68 ; ↓将用户名字串转化为浮点数
00401350 |. FF75 08 push dword ptr [ebp+8] ; /s
00401353 |. E8 78010000 call <jmp.&CRTDLL.atof> ; atof
00401358 |. DD55 E8 fst qword ptr [ebp-18] ; 保存转化结果
0040135B |. 83EC 08 sub esp, 8 ; 开辟内存
0040135E |. DD1C24 fstp qword ptr [esp] ; 保存转化结果并弹栈
00401361 |. E8 82010000 call <jmp.&CRTDLL.floor> ; 向下取整
00401366 |. DD5D F8 fstp qword ptr [ebp-8] ; ↓将序列号转化为浮点数
00401369 |. FF75 0C push dword ptr [ebp+C] ; /s
0040136C |. E8 5F010000 call <jmp.&CRTDLL.atof> ; atof
00401371 |. DD55 D8 fst qword ptr [ebp-28] ; 保存转化后的序列号
00401374 |. 83EC 08 sub esp, 8 ; 平衡堆栈
00401377 |. DD1C24 fstp qword ptr [esp] ; 将结果入栈
0040137A |. E8 69010000 call <jmp.&CRTDLL.floor> ; 向下取整
0040137F |. 83C4 18 add esp, 18 ; 平衡堆栈
00401382 |. DD55 F0 fst qword ptr [ebp-10] ; 保存取整结果
00401385 |. DC4D F8 fmul qword ptr [ebp-8] ; 乘以用户名
00401388 |. D9EE fldz ; 载入0
0040138A |. DED9 fcompp ; 比较st(0)st(1),并弹出寄存器堆栈
0040138C |. DFE0 fstsw ax ; 把该状态寄存器的值传送给通用寄存器AX
0040138E |. 9E sahf ; 标志传送指令
0040138F |. 75 07 jnz short 00401398 ; st0和st1相等?
00401391 |. 31C0 xor eax, eax ; 清空eax
00401393 |. E9 96000000 jmp 0040142E ; 函数结束
00401398 |> DD45 F8 fld qword ptr [ebp-8] ; 用户名浮点数入栈
0040139B |. DC5D F0 fcomp qword ptr [ebp-10] ; 与序列号浮点数比较
0040139E |. DFE0 fstsw ax
004013A0 |. 9E sahf
004013A1 |. 75 07 jnz short 004013AA ; 用户名浮点数与序列号浮点数相等则函数结束
004013A3 |. 31C0 xor eax, eax ; 清空eax
004013A5 |. E9 84000000 jmp 0040142E ; 函数结束
004013AA |> DD45 F8 fld qword ptr [ebp-8] ; 用户名浮点数入栈
004013AD |. DD5D C8 fstp qword ptr [ebp-38] ; 保存用户名浮点数
004013B0 |. D9E8 fld1 ; 1入栈
004013B2 |. DD55 C0 fst qword ptr [ebp-40] ; 保存1
004013B5 |. DC5D C8 fcomp qword ptr [ebp-38] ; 1 > 用户名浮点数?
004013B8 |. DFE0 fstsw ax
004013BA |. 9E sahf
004013BB |. 77 2D ja short 004013EA ; 是则错误
004013BD |. DF2D 38304000 fild qword ptr [403038] ; 载入10的10次方
004013C3 |. DD55 B8 fst qword ptr [ebp-48] ; 保存
004013C6 |. DC5D C8 fcomp qword ptr [ebp-38] ; 10的10次方 < 用户名浮点数?
004013C9 |. DFE0 fstsw ax
004013CB |. 9E sahf
004013CC |. 72 1C jb short 004013EA ; 是则错误
004013CE |. DD45 F0 fld qword ptr [ebp-10] ; 序列号浮点数入栈
004013D1 |. DD5D B0 fstp qword ptr [ebp-50] ; 保存
004013D4 |. DD45 C0 fld qword ptr [ebp-40] ; 用户名浮点数入栈
004013D7 |. DC5D B0 fcomp qword ptr [ebp-50] ; 用户名浮点数 > 序列号浮点数?
004013DA |. DFE0 fstsw ax
004013DC |. 9E sahf
004013DD |. 77 0B ja short 004013EA ; 是则错误
004013DF |. DD45 B8 fld qword ptr [ebp-48] ; 载入10的10次方
004013E2 |. DC5D B0 fcomp qword ptr [ebp-50] ; 10的10次方 >= 序列号浮点数?
004013E5 |. DFE0 fstsw ax
004013E7 |. 9E sahf
004013E8 |. 73 04 jnb short 004013EE ; 是则继续流程
004013EA |> 31C0 xor eax, eax ; 清空eax
004013EC |. EB 40 jmp short 0040142E ; 函数结束
004013EE |> DD45 F8 fld qword ptr [ebp-8] ; 用户名浮点数入栈
004013F1 |. D9FE fsin ; 计算栈顶的正弦函数
004013F3 |. DD5D A8 fstp qword ptr [ebp-58] ; 保存结果
004013F6 |. DD45 F0 fld qword ptr [ebp-10] ; 序列号浮点数入栈
004013F9 |. D9FE fsin ; 计算栈顶的正弦函数
004013FB |. DD5D A0 fstp qword ptr [ebp-60] ; 保存结果
004013FE |. DD45 A8 fld qword ptr [ebp-58] ; 用户名正弦值入栈
00401401 |. DC4D A0 fmul qword ptr [ebp-60] ; 乘以 序列号正弦值
00401404 |. DF2D 30304000 fild qword ptr [403030] ; 10的16次方入栈
0040140A |. DEC9 fmulp st(1), st ; 再相乘
0040140C |. 83EC 08 sub esp, 8 ; 开辟8个字节的空间
0040140F |. DD1C24 fstp qword ptr [esp] ; 保存结果
00401412 |. E8 D1000000 call <jmp.&CRTDLL.floor> ; 向下取整
00401417 |. 83C4 08 add esp, 8
0040141A |. DD5D 98 fstp qword ptr [ebp-68] ; 保存
0040141D |. D9EE fldz ; 载入0
0040141F |. DC5D 98 fcomp qword ptr [ebp-68] ; 结果是否为0?
00401422 |. DFE0 fstsw ax
00401424 |. 9E sahf ; (initial cpu selection)
00401425 |. 75 05 jnz short 0040142C ; 不为0则失败
00401427 |. 31C0 xor eax, eax
00401429 |. 40 inc eax
0040142A |. EB 02 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 }
动手编写程序,验证我们的猜想:
=========================十年后============================》
好吧。。。肯定是哪儿出问题了,经过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-8;
cout << "Valid number:" << endl;
for ( i = 1 ; i <= 1e+10 ; 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,1
s: pop eax
}
if ( Flag )
cout << setprecision(10) << i <<endl;
}
cout << "Done." << endl;
return 0;
}
运行效果:
但经过测试发现,算出的数中 大于 10的9次方的数的Sin值与zebrone1.1的Sin值有偏差,所以有效的数值有:
245850922
411557987
657408909
823115974
随便取出两个按照 升序填入:
就注册成功了: