一个简单的注册机程序破解
用ida 载入,看反汇编代码:
代码:
.text:00401290 ; =============== S U B R O U T I N E =======================================
.text:00401290
.text:00401290 ; Attributes: bp-based frame
.text:00401290
.text:00401290 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401290 _main proc near ; CODE XREF: ___mingw_CRTStartup+E2p
.text:00401290
.text:00401290 var_8C = dword ptr -8Ch
.text:00401290 var_80 = dword ptr -80h
.text:00401290 var_7C = dword ptr -7Ch
.text:00401290 var_78 = dword ptr -78h
.text:00401290 var_74 = dword ptr -74h
.text:00401290 var_70 = dword ptr -70h
.text:00401290 var_6A = byte ptr -6Ah
.text:00401290 var_69 = byte ptr -69h
.text:00401290 var_68 = byte ptr -68h
.text:00401290 var_64 = dword ptr -64h
.text:00401290 var_60 = dword ptr -60h
.text:00401290 var_5C = dword ptr -5Ch
.text:00401290 var_58 = dword ptr -58h
.text:00401290 var_54 = dword ptr -54h
.text:00401290 var_50 = dword ptr -50h
.text:00401290 var_4C = word ptr -4Ch
.text:00401290 var_48 = byte ptr -48h
.text:00401290 var_44 = dword ptr -44h
.text:00401290 var_40 = dword ptr -40h
.text:00401290 var_3C = dword ptr -3Ch
.text:00401290 var_38 = dword ptr -38h
.text:00401290 var_34 = dword ptr -34h
.text:00401290 var_30 = dword ptr -30h
.text:00401290 var_2C = dword ptr -2Ch
.text:00401290 var_28 = byte ptr -28h
.text:00401290 var_24 = dword ptr -24h
.text:00401290 var_20 = dword ptr -20h
.text:00401290 var_1C = dword ptr -1Ch
.text:00401290 var_18 = byte ptr -18h
.text:00401290 argc = dword ptr 8
.text:00401290 argv = dword ptr 0Ch
.text:00401290 envp = dword ptr 10h
;定义了很多变量
.text:00401290
.text:00401290 push ebp
.text:00401291 mov ebp, esp
.text:00401293 sub esp, 0B8h
.text:00401299 and esp, 0FFFFFFF0h
.text:0040129C mov eax, 0
.text:004012A1 add eax, 0Fh
.text:004012A4 add eax, 0Fh
.text:004012A7 shr eax, 4
.text:004012AA shl eax, 4
.text:004012AD mov [ebp+var_8C], eax
.text:004012B3 mov eax, [ebp+var_8C]
.text:004012B9 call ___chkstk
.text:004012BE call ___main
.text:004012C3 mov dword ptr [esp], offset aTitleCrackme ; "title CrackMe"
.text:004012CA call system
;从这里开始,看到是一系列赋值操作
.text:004012CF mov eax, ds:dword_40300E
.text:004012D4 mov dword ptr [ebp+var_28], eax
.text:004012D7 mov eax, ds:dword_403012
.text:004012DC mov [ebp+var_24], eax
.text:004012DF mov eax, ds:dword_403016
.text:004012E4 mov [ebp+var_20], eax
.text:004012E7 mov eax, ds:dword_40301A
.text:004012EC mov [ebp+var_1C], eax
.text:004012EF movzx eax, ds:byte_40301E
.text:004012F6 mov [ebp+var_18], al
.text:004012F9 mov eax, ds:dword_403020
.text:004012FE mov dword ptr [ebp+var_48], eax
.text:00401301 mov eax, ds:dword_403024
.text:00401306 mov [ebp+var_44], eax
.text:00401309 mov eax, ds:dword_403028
.text:0040130E mov [ebp+var_40], eax
.text:00401311 mov eax, ds:dword_40302C
.text:00401316 mov [ebp+var_3C], eax
.text:00401319 mov eax, ds:dword_403030
.text:0040131E mov [ebp+var_38], eax
.text:00401321 mov eax, ds:dword_403034
.text:00401326 mov [ebp+var_34], eax
.text:00401329 mov eax, ds:dword_403038
.text:0040132E mov [ebp+var_30], eax
.text:00401331 mov eax, ds:dword_40303C
.text:00401336 mov [ebp+var_2C], eax
.text:00401339 mov eax, ds:dword_403040
.text:0040133E mov dword ptr [ebp+var_68], eax
.text:00401341 mov eax, ds:dword_403044
.text:00401346 mov [ebp+var_64], eax
.text:00401349 mov eax, ds:dword_403048
.text:0040134E mov [ebp+var_60], eax
.text:00401351 mov eax, ds:dword_40304C
.text:00401356 mov [ebp+var_5C], eax
.text:00401359 mov eax, ds:dword_403050
.text:0040135E mov [ebp+var_58], eax
.text:00401361 mov eax, ds:dword_403054
.text:00401366 mov [ebp+var_54], eax
.text:00401369 mov eax, ds:dword_403058
.text:0040136E mov [ebp+var_50], eax
.text:00401371 movzx eax, ds:word_40305C
.text:00401378 mov [ebp+var_4C], ax
.text:0040137C lea eax, [ebp+var_28]
.text:0040137F mov [esp], eax ; char *
.text:00401382 call puts
;这里执行puts输出字符串命令,首地址是ebp+var_28,再看前面的赋值操作,可以确定这里输出的正是提示字符串“Type your serial”。
.text:00401387 lea eax, [ebp+var_78]
.text:0040138A mov [esp+14h], eax
.text:0040138E lea eax, [ebp+var_6A]
.text:00401391 mov [esp+10h], eax
.text:00401395 lea eax, [ebp+var_74]
.text:00401398 mov [esp+0Ch], eax
.text:0040139C lea eax, [ebp+var_69]
.text:0040139F mov [esp+8], eax
.text:004013A3 lea eax, [ebp+var_70]
.text:004013A6 mov [esp+4], eax
.text:004013AA mov dword ptr [esp], offset aDCDCD ; "%d%c%d%c%d"
.text:004013B1 call scanf
;这里执行scanf命令,输入三个int数据,两个字符,三个int分别保存在[ebp+var_70],[ebp+var_74],[ebp+var_78]
.text:004013B6 mov edx, [ebp+var_70] ;取输入的第一个int
.text:004013B9 mov eax, edx
.text:004013BB shl eax, 2
.text:004013BE add eax, edx
.text:004013C0 add eax, eax
.text:004013C2 mov [ebp+var_7C], eax
.text:004013C5 lea eax, [ebp+var_7C]
.text:004013C8 add dword ptr [eax], 7Dh
.text:004013CB mov eax, [ebp+var_7C]
.text:004013CE add eax, eax
.text:004013D0 mov [ebp+var_7C], eax
.text:004013D3 lea eax, [ebp+var_7C]
.text:004013D6 inc dword ptr [eax]
.text:004013D8 lea eax, [ebp+var_7C]
.text:004013DB sub dword ptr [eax], 15h
.text:004013DE lea eax, [ebp+var_7C]
.text:004013E1 add dword ptr [eax], 58h
;这里是一系列运算,假设第一个int表示为a,[ebp+var_7C]表示为tmp1,那么tmp1=((a*4+a)*2 +0x7D ) *2 + 1 - 0x15 + 0x58
;化简得 tmp1 = 20*a + 318
.text:004013E4 mov eax, [ebp+var_70]
.text:004013E7 add eax, eax
.text:004013E9 mov [ebp+var_80], eax
.text:004013EC lea eax, [ebp+var_80]
.text:004013EF add dword ptr [eax], 0FDh
.text:004013F5 mov eax, [ebp+var_80]
.text:004013F8 add eax, eax
.text:004013FA mov [ebp+var_80], eax
.text:004013FD lea eax, [ebp+var_80]
.text:00401400 inc dword ptr [eax]
;跟上面类似,这是也是取第一个输入的数,然后进行操作,结果放到[ebp+var_80]中,不妨将其标记为tmp2,则tmp2=( 2*a + 0xFD ) * 2 + 1
;化简一下 tmp2 = 4*a + 507
.text:00401402 mov eax, [ebp+var_80]
.text:00401405 add eax, [ebp+var_7C]
.text:00401408 add eax, 2
.text:0040140B mov [ebp+var_80], eax
;这里可以看到,tmp2 = tmp2 + tmp1 + 2 = 24*a + 827
.text:0040140E mov eax, [ebp+var_74] ;eax=输入的第二个整数b
.text:00401411 cmp eax, [ebp+var_7C] ;eax和tmp1比较
.text:00401414 jnz short loc_40142B ;不相等直接退出
.text:00401416 mov eax, [ebp+var_78] ;相等则令 eax = 输入的第三个整数
.text:00401419 cmp eax, [ebp+var_80] ;eax和tmp2比较
.text:0040141C jnz short loc_40142B ;不相等退出
.text:0040141E lea eax, [ebp+var_48]
.text:00401421 mov [esp], eax ; char *
.text:00401424 call puts
.text:00401429 jmp short locret_401442 ;跳到正确的输出
.text:0040142B ; ---------------------------------------------------------------------------
.text:0040142B
.text:0040142B loc_40142B: ; CODE XREF: _main+184j
.text:0040142B ; _main+18Cj
.text:0040142B lea eax, [ebp+var_68]
.text:0040142E mov [esp], eax ; char *
.text:00401431 call puts
.text:00401436 mov dword ptr [esp], offset aPauseNul ; "Pause >NUL"
.text:0040143D call system ;这里是错误的输出
.text:00401442
.text:00401442 locret_401442: ; CODE XREF: _main+199j
.text:00401442 leave
.text:00401443 retn
.text:00401443 _main endp ;这里是正确的输出
这样就很容易构造出一个正确的字符串输入了。
但是结果一闪就过去了,我没想到什么好办法,只好用od动态调试,这样显示出正确结果后就挺下来了。
字符串合法情况下输出“Right Crack, now write a KeyGen”。
这个注册机真是非常非常简陋,只是用到了基本的运算,连除法都没有。不过我都想不太明白源程序怎么会搞出那么多的赋值操作~~~
crackme下载:
http://up.2cto.com/2013/0627/20130627095859133.rar
上一篇: 一款宝宝取名软件爆破分析
下一篇: 纯手工编写的PE可执行程序