作为一个小菜。最近在52pojie上看了一些逆向破解的知识。 发现论坛有160个crack me。觉得不错。拿来做做。
这可把一个没基础没经验的我 弄得是稀里糊涂昏天黑地。看着前辈的经验贴,才有点懂。不多说。
//前辈大牛的帖子:http://www.52pojie.cn/thread-264393-1-1.html
打开软件,
很明显 第一关是check correct。
正常习惯 我们先尝试一个错误的 xiaozhu|123123 单击check
出现
很好 出现了 Sorry,The serial is incorrect!
我们用OD载入程序,搜索ASCII字符串。 发现有两处
1.中文搜索引擎, item 236
地址=0042FA63
反汇编=mov edx,0042FB80
文本字符串=Sorry , The serial is incorect !
2.
中文搜索引擎, item 244
地址=0042FB26
反汇编=mov edx,0042FB80
文本字符串=Sorry , The serial is incorect !
也不好确定是哪个。
按下F12暂停,打开调用堆栈。
看到了两个MessageBox。看堆栈的位置。 第一个位置为0x77d50550 很明显这不是程序领空。程序地址开始为 0x00400000 而第二个正好为0x00421AE.据此判断出这个位我们的MessageBox。Show Call 我们来看看代码
0042A170 /$ 55 push ebp
0042A171 |. 8BEC mov ebp,esp
0042A173 |. 83C4 F4 add esp,-0xC
0042A176 |. 53 push ebx
0042A177 |. 56 push esi
0042A178 |. 57 push edi
0042A179 |. 8BF9 mov edi,ecx
0042A17B |. 8BF2 mov esi,edx
0042A17D |. 8BD8 mov ebx,eax
0042A17F |. E8 7CB4FDFF call <jmp.&user32.GetActiveWindow> ; [GetActiveWindow
0042A184 |. 8945 F8 mov [local.2],eax
0042A187 |. 33C0 xor eax,eax
0042A189 |. E8 12A0FFFF call 004241A0
0042A18E |. 8945 F4 mov [local.3],eax
0042A191 |. 33C0 xor eax,eax
0042A193 |. 55 push ebp
0042A194 |. 68 D0A14200 push 0042A1D0
0042A199 |. 64:FF30 push dword ptr fs:[eax]
0042A19C |. 64:8920 mov dword ptr fs:[eax],esp
0042A19F |. 8B45 08 mov eax,[arg.1]
0042A1A2 |. 50 push eax ; /Style
0042A1A3 |. 57 push edi ; |Title
0042A1A4 |. 56 push esi ; |Text
0042A1A5 |. 8B43 24 mov eax,dword ptr ds:[ebx+0x24] ; |
0042A1A8 |. 50 push eax ; |hOwner
0042A1A9 |. E8 FAB5FDFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
显而易见,这个是调用MessageBoxA函数,附上MessageBox函数原型:
int WINAPI MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
这个函数的地址是 0x0042A170~~0X0042A1CF
那么我们来找一个这个函数是从哪调用的呢
我们继续看刚才的堆栈调用图 找到最后一行
发现 0042A170 的call from 0042FB32 ,找到了 show call
0042FA7C |. 8B83 DC010000 mov eax,dword ptr ds:[ebx+0x1DC]
0042FA82 |. E8 D1AFFEFF call 0041AA58
0042FA87 |. 8B45 F0 mov eax,[local.4] ; eax = 00DD2668 xiaozhu的地址
0042FA8A |. 0FB600 movzx eax,byte ptr ds:[eax] ; 把第一个字符放进eax eax = 'x'
0042FA8D |. F72D 50174300 imul dword ptr ds:[0x431750] ; *29
0042FA93 |. A3 50174300 mov dword ptr ds:[0x431750],eax ; eax=0x78*0x29=0x1338
0042FA98 |. A1 50174300 mov eax,dword ptr ds:[0x431750]
0042FA9D |. 0105 50174300 add dword ptr ds:[0x431750],eax ; eax=eax+eax DS:[0X431750]=0X2670
0042FAA3 |. 8D45 FC lea eax,[local.1] ; ds:[local.1]=0012F9A4
0042FAA6 |. BA ACFB4200 mov edx,0042FBAC ; CW
0042FAAB |. E8 583CFDFF call 00403708
0042FAB0 |. 8D45 F8 lea eax,[local.2]
0042FAB3 |. BA B8FB4200 mov edx,0042FBB8 ; CRACKED
0042FAB8 |. E8 4B3CFDFF call 00403708
0042FABD |. FF75 FC push [local.1] ; push CW
0042FAC0 |. 68 C8FB4200 push 0042FBC8 ; -
0042FAC5 |. 8D55 E8 lea edx,[local.6] ; edx=12f990
0042FAC8 |. A1 50174300 mov eax,dword ptr ds:[0x431750] ; eax2670
0042FACD |. E8 466CFDFF call 00406718 ; Stack ss:[0012F990]=00DD609C, (ASCII "9840")
0042FAD2 |. FF75 E8 push [local.6]
0042FAD5 |. 68 C8FB4200 push 0042FBC8 ; -
0042FADA |. FF75 F8 push [local.2] ; push CRACKED
0042FADD |. 8D45 F4 lea eax,[local.3]
0042FAE0 |. BA 05000000 mov edx,0x5
0042FAE5 |. E8 C23EFDFF call 004039AC ; 附近的call 2 eax=0042FAEA
0042FAEA |. 8D55 F0 lea edx,[local.4] ; edx 0012F998
0042FAED |. 8B83 E0010000 mov eax,dword ptr ds:[ebx+0x1E0] ; eax 00DD5E54
0042FAF3 |. E8 60AFFEFF call 0041AA58 ; 附近的call 1 注册码 call
0042FAF8 |. 8B55 F0 mov edx,[local.4] ; edx 出现 用户密码
0042FAFB |. 8B45 F4 mov eax,[local.3] ; eax 出现正确密码
0042FAFE |. E8 F93EFDFF call 004039FC ; strcmp
0042FB03 75 1A jnz short 0042FB1F ; 这个貌似是关键判断
0042FB05 |. 6A 00 push 0x0
0042FB07 |. B9 CCFB4200 mov ecx,0042FBCC ; Congratz !!
0042FB0C |. BA D8FB4200 mov edx,0042FBD8 ; Good job dude =)
0042FB11 |. A1 480A4300 mov eax,dword ptr ds:[0x430A48]
0042FB16 |. 8B00 mov eax,dword ptr ds:[eax]
0042FB18 |. E8 53A6FFFF call 0042A170
0042FB1D |. EB 18 jmp short 0042FB37
0042FB1F |> 6A 00 push 0x0
0042FB21 |. B9 74FB4200 mov ecx,0042FB74 ; Try Again!
0042FB26 |. BA 80FB4200 mov edx,0042FB80 ; Sorry , The serial is incorect !
0042FB2B |. A1 480A4300 mov eax,dword ptr ds:[0x430A48]
0042FB30 |. 8B00 mov eax,dword ptr ds:[eax]
0042FB32 |. E8 39A6FFFF call 0042A170
最后一行就是调用代码。
我们浏览了一下 发现了 两个字符串 分别对应正确和错误的情况。我们向前找 发现了一个可以JNZ 我们在此处下断点。通过改变ZF的值 可以发现产生了不同的结果,没错。这个就是关键jnz。 为了让程序表现出验证通过 我们可以采用最近单的爆破。右击这一句。binary->fill with NOP's 后,发现 之前的用户和密码 可以通过验证 爆破成功。
爆破的目的达到了。接下来我们来尝试写一个注册机。
我们单步调试。发现在jnz的前两行
042FAF8 |. 8B55 F0 mov edx,[local.4] ; edx 出现 用户密码 123123
0042FAFB |. 8B45 F4 mov eax,[local.3] ; eax 出现正确密码 CW-9840-CHRCKED
0042FAFE |. E8 F93EFDFF call 004039FC ; strcmp
0042FB03 75 1A jnz short 0042FB1F ; 这个貌似是关键判断
依次出现了edx=CW-9840-CHRCKED 和eax =123123
我们将CW--9840-CRACKED 作为注册码写入到软件中,发现验证通过了 没错 它就是注册码,
后面jnz是根据eax来判断返回的。 所以很明晰那中间的call就是strcmp函数 返回值存在eax中。
现在我们的问题是 注册码是如何产生的。
我们继续向上找。第一种情况。找最近的call ,很有可能是调用了一个函数得出注册码。但是我们不断的F7单步跟入,发现里面一个函数调用一个函数,显而易见。我们的猜想错了。 那么判断看来就应该是在前面一段中产生的。
我们把上面一段程序拿来 F8 调试。一行行看
0042F998 /. 55 push ebp
0042F999 |. 8BEC mov ebp,esp
0042F99B |. 33C9 xor ecx,ecx
0042F99D |. 51 push ecx
0042F99E |. 51 push ecx
0042F99F |. 51 push ecx
0042F9A0 |. 51 push ecx
0042F9A1 |. 51 push ecx
0042F9A2 |. 51 push ecx
0042F9A3 |. 53 push ebx
0042F9A4 |. 56 push esi
0042F9A5 |. 8BD8 mov ebx,eax
0042F9A7 |. 33C0 xor eax,eax
0042F9A9 |. 55 push ebp
0042F9AA |. 68 67FB4200 push 0042FB67
0042F9AF |. 64:FF30 push dword ptr fs:[eax]
0042F9B2 |. 64:8920 mov dword ptr fs:[eax],esp
0042F9B5 |. C705 50174300>mov dword ptr ds:[0x431750],0x29
0042F9BF |. 8D55 F0 lea edx,[local.4]
0042F9C2 |. 8B83 DC010000 mov eax,dword ptr ds:[ebx+0x1DC]
0042F9C8 |. E8 8BB0FEFF call 0041AA58
0042F9CD |. 8B45 F0 mov eax,[local.4]
0042F9D0 |. E8 DB40FDFF call 00403AB0
0042F9D5 |. A3 6C174300 mov dword ptr ds:[0x43176C],eax
0042F9DA |. 8D55 F0 lea edx,[local.4]
0042F9DD |. 8B83 DC010000 mov eax,dword ptr ds:[ebx+0x1DC]
0042F9E3 |. E8 70B0FEFF call 0041AA58
0042F9E8 |. 8B45 F0 mov eax,[local.4]
0042F9EB |. 0FB600 movzx eax,byte ptr ds:[eax]
0042F9EE |. 8BF0 mov esi,eax
0042F9F0 |. C1E6 03 shl esi,0x3
0042F9F3 |. 2BF0 sub esi,eax
0042F9F5 |. 8D55 EC lea edx,[local.5]
0042F9F8 |. 8B83 DC010000 mov eax,dword ptr ds:[ebx+0x1DC]
0042F9FE |. E8 55B0FEFF call 0041AA58
0042FA03 |. 8B45 EC mov eax,[local.5]
0042FA06 |. 0FB640 01 movzx eax,byte ptr ds:[eax+0x1]
0042FA0A |. C1E0 04 shl eax,0x4
0042FA0D |. 03F0 add esi,eax
0042FA0F |. 8935 54174300 mov dword ptr ds:[0x431754],esi
0042FA15 |. 8D55 F0 lea edx,[local.4]
0042FA18 |. 8B83 DC010000 mov eax,dword ptr ds:[ebx+0x1DC]
0042FA1E |. E8 35B0FEFF call 0041AA58
0042FA23 |. 8B45 F0 mov eax,[local.4]
0042FA26 |. 0FB640 03 movzx eax,byte ptr ds:[eax+0x3]
0042FA2A |. 6BF0 0B imul esi,eax,0xB
0042FA2D |. 8D55 EC lea edx,[local.5]
0042FA30 |. 8B83 DC010000 mov eax,dword ptr ds:[ebx+0x1DC]
0042FA36 |. E8 1DB0FEFF call 0041AA58
0042FA3B |. 8B45 EC mov eax,[local.5]
0042FA3E |. 0FB640 02 movzx eax,byte ptr ds:[eax+0x2]
0042FA42 |. 6BC0 0E imul eax,eax,0xE
0042FA45 |. 03F0 add esi,eax
0042FA47 |. 8935 58174300 mov dword ptr ds:[0x431758],esi
0042FA4D |. A1 6C174300 mov eax,dword ptr ds:[0x43176C] ; //NAME TAH
0042FA52 |. E8 D96EFDFF call 00406930 ; 关键call
0042FA57 |. 83F8 04 cmp eax,0x4 ; 判断name或者tag是否合格
0042FA5A |. 7D 1D jge short 0042FA79 ; 很明显 我们的长度合格
0042FA5C |. 6A 00 push 0x0
0042FA5E |. B9 74FB4200 mov ecx,0042FB74 ; Try Again!
0042FA63 |. BA 80FB4200 mov edx,0042FB80 ; Sorry , The serial is incorect !
0042FA68 |. A1 480A4300 mov eax,dword ptr ds:[0x430A48]
0042FA6D |. 8B00 mov eax,dword ptr ds:[eax]
0042FA6F |. E8 FCA6FFFF call 0042A170
0042FA74 |. E9 BE000000 jmp 0042FB37
0042FA79 |> 8D55 F0 lea edx,[local.4]
0042FA7C |. 8B83 DC010000 mov eax,dword ptr ds:[ebx+0x1DC]
0042FA82 |. E8 D1AFFEFF call 0041AA58
0042FA87 |. 8B45 F0 mov eax,[local.4] ; eax = 00DD2668 xiaozhu的地址
0042FA8A |. 0FB600 movzx eax,byte ptr ds:[eax] ; 把第一个字符放进eax eax = 'x'
0042FA8D |. F72D 50174300 imul dword ptr ds:[0x431750] ; *29
0042FA93 |. A3 50174300 mov dword ptr ds:[0x431750],eax ; eax=0x78*0x29=0x1338
0042FA98 |. A1 50174300 mov eax,dword ptr ds:[0x431750]
0042FA9D |. 0105 50174300 add dword ptr ds:[0x431750],eax ; eax=eax+eax DS:[0X431750]=0X2670
0042FAA3 |. 8D45 FC lea eax,[local.1] ; ds:[local.1]=0012F9A4
0042FAA6 |. BA ACFB4200 mov edx,0042FBAC ; CW
0042FAAB |. E8 583CFDFF call 00403708
0042FAB0 |. 8D45 F8 lea eax,[local.2]
0042FAB3 |. BA B8FB4200 mov edx,0042FBB8 ; CRACKED
0042FAB8 |. E8 4B3CFDFF call 00403708
0042FABD |. FF75 FC push [local.1] ; push CW
0042FAC0 |. 68 C8FB4200 push 0042FBC8 ; -
0042FAC5 |. 8D55 E8 lea edx,[local.6] ; edx=12f990
0042FAC8 |. A1 50174300 mov eax,dword ptr ds:[0x431750] ; eax2670
0042FACD |. E8 466CFDFF call 00406718 ; Stack ss:[0012F990]=00DD609C, (ASCII "9840")
0042FAD2 |. FF75 E8 push [local.6]
0042FAD5 |. 68 C8FB4200 push 0042FBC8 ; -
0042FADA |. FF75 F8 push [local.2] ; push CRACKED
0042FADD |. 8D45 F4 lea eax,[local.3]
0042FAE0 |. BA 05000000 mov edx,0x5
0042FAE5 |. E8 C23EFDFF call 004039AC ; 附近的call 2 eax=0042FAEA
0042FAEA |. 8D55 F0 lea edx,[local.4] ; edx 0012F998
0042FAED |. 8B83 E0010000 mov eax,dword ptr ds:[ebx+0x1E0] ; eax 00DD5E54
0042FAF3 |. E8 60AFFEFF call 0041AA58 ; 附近的call 1 注册码 call
0042FAF8 |. 8B55 F0 mov edx,[local.4] ; edx 出现 用户密码 123123
0042FAFB |. 8B45 F4 mov eax,[local.3] ; eax 出现正确密码
0042FAFE |. E8 F93EFDFF call 004039FC ; strcmp
0042FB03 75 1A jnz short 0042FB1F ; 这个貌似是关键判断
0042FB05 |. 6A 00 push 0x0
0042FB07 |. B9 CCFB4200 mov ecx,0042FBCC ; Congratz !!
0042FB0C |. BA D8FB4200 mov edx,0042FBD8 ; Good job dude =)
0042FB11 |. A1 480A4300 mov eax,dword ptr ds:[0x430A48]
0042FB16 |. 8B00 mov eax,dword ptr ds:[eax]
0042FB18 |. E8 53A6FFFF call 0042A170
0042FB1D |. EB 18 jmp short 0042FB37
0042FB1F |> 6A 00 push 0x0
0042FB21 |. B9 74FB4200 mov ecx,0042FB74 ; Try Again!
0042FB26 |. BA 80FB4200 mov edx,0042FB80 ; Sorry , The serial is incorect !
0042FB2B |. A1 480A4300 mov eax,dword ptr ds:[0x430A48]
0042FB30 |. 8B00 mov eax,dword ptr ds:[eax]
0042FB32 |. E8 39A6FFFF call 0042A170
0042FB37 |> 33C0 xor eax,eax
这里就是一点点求注册码的部分。 我看了很久,刚开始接触不是很懂。 看了大牛的总结 感觉是对的。
总结:取第一个字母的ASNI的数字,如xiaozhu中第一个字符1对应数字0x78,然后用它乘以0x29,结果再自增一倍(即x2),将得到的数字转为10进制的字符串,在前加上”CW-”,后加上”-CRACKED”,就组成了用户名对应的注册码。
当然这中间还有很多call需要跟进,这种逆向能力 我暂时还达不到。。。
既然算法知道了 注册机的编写问题应该不大了。。