[反汇编练习] 160个CrackMe之018.
本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注册机的东西。
其中,文章中按照如下逻辑编排(解决如下问题):
1、使用什么环境和工具
2、程序分析
3、思路分析和破解流程
4、注册机的探索
----------------------------------
提醒各位看客: 如果文章中的逻辑看不明白,那你一定是没有亲手操刀!OD中的跳转提示很强大,只要你跟踪了,不用怎么看代码就理解了!
----------------------------------
1、工具和环境:
WinXP SP3 + 52Pojie六周年纪念版OD + PEID + 汇编金手指。
160个CrackMe的打包文件。
下载地址: http://pan.baidu.com/s/1xUWOY 密码: jbnq
注:
1、Win7系统对于模块和程序开启了随机初始地址的功能,会给分析带来很大的负担,所以不建议使用Win7进行分析。
2、以上工具都是在52PoJie论坛下的原版程序,NOD32不报毒,个人承诺绝对不会进行任何和木马病毒相关内容。
2、程序分析:
想要破解一个程序,必须先了解这个程序。所以,在破解过程中,对最初程序的分析很重要,他可以帮助我们理解作者的目的和意图,特别是对于注册码的处理细节,从而方便我们反向跟踪和推导。
和上一节一样,打开CHM,选择第19个Brad Soblesky.2.exe,保存下来。运行程序,程序界面如下:
3、思路分析和破解流程
又见信息框,哈哈哈!
PEID查看: Microsoft Visual C++ 6.0
和以前的一样,直接上步骤:
1、打开OD,将exe拖到OD窗口中,等程序暂停后,直接点击运行按钮(F9),不用理会。
2、在exe中输入伪码:bbdxf 123123。点击OK按钮,弹出错误信息框,不要关闭。
3、在OD中点击暂停按钮(Ctrl+F12),再点击堆栈K按钮(Ctrl+K),可以看到当前堆栈情况。
和上一个一模一样,右键->show call。
4、反汇编窗口看到如下信息:
00401618 |.^\EB AD \jmp short 004015C7 0040161A |> 8B45 F0 mov eax,[local.4] 0040161D |. 50 push eax 0040161E |. 68 54404000 push 00404054 ; ASCII "%lu" 00401623 |. 8D4D DC lea ecx,[local.9] 00401626 |. 51 push ecx 00401627 |. E8 52070000 call <jmp.&MFC42.#2818> 0040162C |. 83C4 0C add esp,0xC 0040162F |. 8D4D DC lea ecx,[local.9] 00401632 |. E8 79020000 call 004018B0 00401637 |. 50 push eax ; /Arg1 00401638 |. 8D4D E8 lea ecx,[local.6] ; | 0040163B |. E8 80020000 call 004018C0 ; \Brad_Sob.004018C0 00401640 |. 85C0 test eax,eax 00401642 |. 0F85 FF000000 jnz 00401747 00401648 |. 8D8D ACFEFFFF lea ecx,[local.85] 0040164E |. E8 19070000 call <jmp.&MFC42.#540> 00401653 |. C645 FC 03 mov byte ptr ss:[ebp-0x4],0x3 00401657 |. 6A 66 push 0x66 00401659 |. 8D8D ACFEFFFF lea ecx,[local.85] 0040165F |. E8 02070000 call <jmp.&MFC42.#4160> 00401664 |. B9 07000000 mov ecx,0x7 00401669 |. BE 58404000 mov esi,00404058 ; ASCII "Correct!! " 0040166E |. 8DBD 48FEFFFF lea edi,[local.110] 00401674 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds> 00401676 |. 66:A5 movs word ptr es:[edi],word ptr ds:[esi] 00401678 |. A4 movs byte ptr es:[edi],byte ptr ds:[esi] 00401679 |. B9 11000000 mov ecx,0x11 0040167E |. 33C0 xor eax,eax 00401680 |. 8DBD 67FEFFFF lea edi,dword ptr ss:[ebp-0x199] 00401686 |. F3:AB rep stos dword ptr es:[edi] 00401688 |. AA stos byte ptr es:[edi] 00401689 |. B9 07000000 mov ecx,0x7 0040168E |. BE 78404000 mov esi,00404078 ; ASCII "<BrD-SoB> " 00401693 |. 8DBD 14FFFFFF lea edi,[local.59] 00401699 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds> 0040169B |. 66:A5 movs word ptr es:[edi],word ptr ds:[esi] 0040169D |. B9 11000000 mov ecx,0x11 004016A2 |. 33C0 xor eax,eax 004016A4 |. 8DBD 32FFFFFF lea edi,dword ptr ss:[ebp-0xCE] 004016AA |. F3:AB rep stos dword ptr es:[edi] 004016AC |. 66:AB stos word ptr es:[edi] 004016AE |. B9 06000000 mov ecx,0x6 004016B3 |. BE 98404000 mov esi,00404098 ; ASCII "Incorrect!!, Try Again." 004016B8 |. 8DBD 78FFFFFF lea edi,[local.34] 004016BE |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds> 004016C0 |. B9 13000000 mov ecx,0x13 004016C5 |. 33C0 xor eax,eax 004016C7 |. 8D7D 90 lea edi,[local.28] 004016CA |. F3:AB rep stos dword ptr es:[edi] 004016CC |. B9 07000000 mov ecx,0x7 004016D1 |. BE B0404000 mov esi,004040B0 ; ASCII "Correct way to go, You Got It." 004016D6 |. 8DBD B0FEFFFF lea edi,[local.84] 004016DC |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds> 004016DE |. 66:A5 movs word ptr es:[edi],word ptr ds:[esi] 004016E0 |. A4 movs byte ptr es:[edi],byte ptr ds:[esi] 004016E1 |. B9 11000000 mov ecx,0x11 004016E6 |. 33C0 xor eax,eax 004016E8 |. 8DBD CFFEFFFF lea edi,dword ptr ss:[ebp-0x131] 004016EE |. F3:AB rep stos dword ptr es:[edi] 004016F0 |. AA stos byte ptr es:[edi] 004016F1 |. 6A 40 push 0x40 004016F3 |. 68 D0404000 push 004040D0 ; ASCII "CrackMe" 004016F8 |. 8D8D ACFEFFFF lea ecx,[local.85] 004016FE |. E8 AD010000 call 004018B0 00401703 |. 50 push eax 00401704 |. 8B8D 40FEFFFF mov ecx,[local.112] 0040170A |. E8 75060000 call <jmp.&MFC42.#4224> 0040170F |. C645 FC 02 mov byte ptr ss:[ebp-0x4],0x2 00401713 |. 8D8D ACFEFFFF lea ecx,[local.85] 00401719 |. E8 42060000 call <jmp.&MFC42.#800> 0040171E |. C645 FC 01 mov byte ptr ss:[ebp-0x4],0x1 00401722 |. 8D4D DC lea ecx,[local.9] 00401725 |. E8 36060000 call <jmp.&MFC42.#800> 0040172A |. C645 FC 00 mov byte ptr ss:[ebp-0x4],0x0 0040172E |. 8D4D E8 lea ecx,[local.6] 00401731 |. E8 2A060000 call <jmp.&MFC42.#800> 00401736 |. C745 FC FFFFF>mov [local.1],-0x1 0040173D |. 8D4D EC lea ecx,[local.5] 00401740 |. E8 1B060000 call <jmp.&MFC42.#800> 00401745 |. EB 70 jmp short 004017B7 00401747 |> 8D8D 44FEFFFF lea ecx,[local.111] 0040174D |. E8 1A060000 call <jmp.&MFC42.#540> 00401752 |. C645 FC 04 mov byte ptr ss:[ebp-0x4],0x4 00401756 |. 6A 67 push 0x67 00401758 |. 8D8D 44FEFFFF lea ecx,[local.111] 0040175E |. E8 03060000 call <jmp.&MFC42.#4160> 00401763 |. 6A 40 push 0x40 00401765 |. 68 D8404000 push 004040D8 ; ASCII "CrackMe" 0040176A |. 8D8D 44FEFFFF lea ecx,[local.111] 00401770 |. E8 3B010000 call 004018B0 00401775 |. 50 push eax 00401776 |. 8B8D 40FEFFFF mov ecx,[local.112] 0040177C |. E8 03060000 call <jmp.&MFC42.#4224>
向上查找,很容易地找到了一个跳转 jnz 00401747 ,逻辑上很难明白到底对不对,但是我们可以试试,选中它,右键->Binary->Fill with Nops。回到exe,试试,哈哈!
4、注册机的探索
我们已经知道了关键跳转,那他的附近肯定有判断条件,刚好,他的上面有一个call,我们跟进去看看,F8只到返回:
004018C0 /$ 55 push ebp 004018C1 |. 8BEC mov ebp,esp 004018C3 |. 51 push ecx 004018C4 |. 894D FC mov [local.1],ecx 004018C7 |. 8B45 08 mov eax,[arg.1] 004018CA |. 50 push eax ; /Arg2 004018CB |. 8B4D FC mov ecx,[local.1] ; | 004018CE |. 8B11 mov edx,dword ptr ds:[ecx] ; | 004018D0 |. 52 push edx ; |Arg1 004018D1 |. E8 0A000000 call 004018E0 ; \Brad_Sob.004018E0 004018D6 |. 83C4 08 add esp,0x8 004018D9 |. 8BE5 mov esp,ebp 004018DB |. 5D pop ebp 004018DC \. C2 0400 retn 0x4 004018DF CC int3 004018E0 /$ 55 push ebp ; // 上面的函数跳到这里 004018E1 |. 8BEC mov ebp,esp 004018E3 |. 8B45 0C mov eax,[arg.2] 004018E6 |. 50 push eax ; /s2 = "3524958250" 004018E7 |. 8B4D 08 mov ecx,[arg.1] ; | 004018EA |. 51 push ecx ; |s1 = "123123" 004018EB |. FF15 B4314000 call dword ptr ds:[<&MSVCRT._mbscmp>] ; \_mbscmp 004018F1 |. 83C4 08 add esp,0x8 004018F4 |. 5D pop ebp 004018F5 \. C3 retn
很容易看出,这个Call就是用来比较两个字符串的。
5、返回关键跳转附近代码,向上查看与算法相关东西:
004014E4 |. 68 8F204000 push 0040208F ; SE handler installation 004014E9 |. 64:A1 0000000>mov eax,dword ptr fs:[0] 004014EF |. 50 push eax 004014F0 |. 64:8925 00000>mov dword ptr fs:[0],esp 004014F7 |. 81EC B4010000 sub esp,0x1B4 004014FD |. 56 push esi 004014FE |. 57 push edi 004014FF |. 898D 40FEFFFF mov [local.112],ecx 00401505 |. C745 F0 45632>mov [local.4],0x81276345 ; // 常量在这里赋值 0040150C |. 68 AC414000 push 004041AC 00401511 |. 8D4D EC lea ecx,[local.5] 00401514 |. E8 77080000 call <jmp.&MFC42.#537> 00401519 |. C745 FC 00000>mov [local.1],0x0 00401520 |. 68 B0414000 push 004041B0 00401525 |. 8D4D E8 lea ecx,[local.6] 00401528 |. E8 63080000 call <jmp.&MFC42.#537> 0040152D |. C645 FC 01 mov byte ptr ss:[ebp-0x4],0x1 00401531 |. 68 B4414000 push 004041B4 00401536 |. 8D4D DC lea ecx,[local.9] 00401539 |. E8 52080000 call <jmp.&MFC42.#537> 0040153E |. C645 FC 02 mov byte ptr ss:[ebp-0x4],0x2 00401542 |. 8D45 EC lea eax,[local.5] 00401545 |. 50 push eax 00401546 |. 68 E8030000 push 0x3E8 0040154B |. 8B8D 40FEFFFF mov ecx,[local.112] 00401551 |. E8 34080000 call <jmp.&MFC42.#3097> 00401556 |. 8D4D E8 lea ecx,[local.6] 00401559 |. 51 push ecx 0040155A |. 68 E9030000 push 0x3E9 0040155F |. 8B8D 40FEFFFF mov ecx,[local.112] 00401565 |. E8 20080000 call <jmp.&MFC42.#3097> 0040156A |. 8D4D EC lea ecx,[local.5] 0040156D |. E8 DE020000 call 00401850 00401572 |. 8945 E4 mov [local.7],eax 00401575 |. 837D E4 05 cmp [local.7],0x5 ; // name 的长度比较 00401579 |. /7D 43 jge short 004015BE 0040157B |. |6A 40 push 0x40 0040157D |. |68 20404000 push 00404020 ; ASCII "CrackMe" 00401582 |. |68 28404000 push 00404028 ; ASCII "User Name must have at least 5 characters." 00401587 |. |8B8D 40FEFFFF mov ecx,[local.112] 0040158D |. |E8 F2070000 call <jmp.&MFC42.#4224> 00401592 |. |C645 FC 01 mov byte ptr ss:[ebp-0x4],0x1 00401596 |. |8D4D DC lea ecx,[local.9] 00401599 |. |E8 C2070000 call <jmp.&MFC42.#800> 0040159E |. |C645 FC 00 mov byte ptr ss:[ebp-0x4],0x0 004015A2 |. |8D4D E8 lea ecx,[local.6] 004015A5 |. |E8 B6070000 call <jmp.&MFC42.#800> 004015AA |. |C745 FC FFFFF>mov [local.1],-0x1 004015B1 |. |8D4D EC lea ecx,[local.5] 004015B4 |. |E8 A7070000 call <jmp.&MFC42.#800> 004015B9 |. |E9 F9010000 jmp 004017B7 004015BE |> \C745 E0 00000>mov [local.8],0x0 004015C5 |. EB 09 jmp short 004015D0 004015C7 |> 8B55 E0 /mov edx,[local.8] 004015CA |. 83C2 01 |add edx,0x1 004015CD |. 8955 E0 |mov [local.8],edx 004015D0 |> 8B45 E0 mov eax,[local.8] 004015D3 |. 3B45 E4 |cmp eax,[local.7] 004015D6 |. 7D 42 |jge short 0040161A 004015D8 |. 8B4D E0 |mov ecx,[local.8] 004015DB |. 51 |push ecx ; /Arg1 004015DC |. 8D4D EC |lea ecx,[local.5] ; | 004015DF |. E8 1C030000 |call 00401900 ; \Brad_Sob.00401900 004015E4 |. 0FBED0 |movsx edx,al 004015E7 |. 8B45 F0 |mov eax,[local.4] 004015EA |. 03C2 |add eax,edx 004015EC |. 8945 F0 |mov [local.4],eax 004015EF |. 8B4D E0 |mov ecx,[local.8] 004015F2 |. C1E1 08 |shl ecx,0x8 004015F5 |. 8B55 F0 |mov edx,[local.4] 004015F8 |. 33D1 |xor edx,ecx 004015FA |. 8955 F0 |mov [local.4],edx 004015FD |. 8B45 E0 |mov eax,[local.8] 00401600 |. 83C0 01 |add eax,0x1 00401603 |. 8B4D E4 |mov ecx,[local.7] 00401606 |. 0FAF4D E0 |imul ecx,[local.8] 0040160A |. F7D1 |not ecx 0040160C |. 0FAFC1 |imul eax,ecx 0040160F |. 8B55 F0 |mov edx,[local.4] 00401612 |. 0FAFD0 |imul edx,eax 00401615 |. 8955 F0 |mov [local.4],edx 00401618 |.^ EB AD \jmp short 004015C7 0040161A |> 8B45 F0 mov eax,[local.4] 0040161D |. 50 push eax 0040161E |. 68 54404000 push 00404054 ; ASCII "%lu" 00401623 |. 8D4D DC lea ecx,[local.9] 00401626 |. 51 push ecx 00401627 |. E8 52070000 call <jmp.&MFC42.#2818> 0040162C |. 83C4 0C add esp,0xC 0040162F |. 8D4D DC lea ecx,[local.9] 00401632 |. E8 79020000 call 004018B0 ; // 字符串比较,它的返回值是eax 00401637 |. 50 push eax ; /Arg1 = ASCII "3524958250" 00401638 |. 8D4D E8 lea ecx,[local.6] ; | 0040163B |. E8 80020000 call 004018C0 ; \Brad_Sob.004018C0 00401640 |. 85C0 test eax,eax 00401642 |. 0F85 FF000000 jnz 00401747 ; // 关键跳转
在这里面有一个大的循环,应该就是处理算法部分,并且对于Name部分,他还有长度判断:
0040157B |. 6A 40 push 0x40 0040157D |. 68 20404000 push 00404020 ; ASCII "CrackMe" 00401582 |. 68 28404000 push 00404028 ; ASCII "User Name must have at least 5 characters." 00401587 |. 8B8D 40FEFFFF mov ecx,[local.112] 0040158D |. E8 F2070000 call <jmp.&MFC42.#4224>
至少5个字符。
算法循环处理部分分析如下:
004015B9 |. /E9 F9010000 jmp 004017B7 004015BE |> |C745 E0 00000>mov [local.8],0x0 ; // 开始处理 004015C5 |. |EB 09 jmp short 004015D0 004015C7 |> |8B55 E0 /mov edx,[local.8] 004015CA |. |83C2 01 |add edx,0x1 ; // 序号+1 004015CD |. |8955 E0 |mov [local.8],edx 004015D0 |> |8B45 E0 mov eax,[local.8] ; // 初始值为0 004015D3 |. |3B45 E4 |cmp eax,[local.7] ; 与Name的长度比较 004015D6 |. |7D 42 |jge short 0040161A 004015D8 |. |8B4D E0 |mov ecx,[local.8] 004015DB |. |51 |push ecx ; /Arg1 = ASCII "bbdxf" 004015DC |. |8D4D EC |lea ecx,[local.5] ; | 004015DF |. |E8 1C030000 |call 00401900 ; \Brad_Sob.00401900 004015E4 |. |0FBED0 |movsx edx,al ; // 取第一个字符的ANSII值,放在al中 004015E7 |. |8B45 F0 |mov eax,[local.4] ; // 这是一个常量 004015EA |. |03C2 |add eax,edx 004015EC |. |8945 F0 |mov [local.4],eax ; // eax = 812763A7; 然后又存进去 004015EF |. |8B4D E0 |mov ecx,[local.8] ; // 序号,初值0 004015F2 |. |C1E1 08 |shl ecx,0x8 ; // 左移8位 004015F5 |. |8B55 F0 |mov edx,[local.4] 004015F8 |. |33D1 |xor edx,ecx ; // 异或 004015FA |. |8955 F0 |mov [local.4],edx ; // 存进去 004015FD |. |8B45 E0 |mov eax,[local.8] 00401600 |. |83C0 01 |add eax,0x1 ; // 序号+1 00401603 |. |8B4D E4 |mov ecx,[local.7] ; // Name长度 00401606 |. |0FAF4D E0 |imul ecx,[local.8] ; // 带符号乘法,Name长度*序号 0040160A |. |F7D1 |not ecx ; // 取反 0040160C |. |0FAFC1 |imul eax,ecx ; // 序号*ecx 0040160F |. |8B55 F0 |mov edx,[local.4] ; // 取出来 00401612 |. |0FAFD0 |imul edx,eax ; // 与刚才的结果相乘 00401615 |. |8955 F0 |mov [local.4],edx ; // 存进去 00401618 |.^|EB AD \jmp short 004015C7 0040161A |> |8B45 F0 mov eax,[local.4] 0040161D |. |50 push eax ; eax=D21A982A 0040161E |. |68 54404000 push 00404054 ; ASCII "%lu" 00401623 |. |8D4D DC lea ecx,[local.9] 00401626 |. |51 push ecx 00401627 |. |E8 52070000 call <jmp.&MFC42.#2818> ; // 格式化字符串 0040162C |. |83C4 0C add esp,0xC 0040162F |. |8D4D DC lea ecx,[local.9] 00401632 |. |E8 79020000 call 004018B0 ; // 字符串比较,它的返回值是eax 00401637 |. |50 push eax ; /Arg1 = ASCII "3524958250" 00401638 |. |8D4D E8 lea ecx,[local.6] ; | 0040163B |. |E8 80020000 call 004018C0 ; \Brad_Sob.004018C0 00401640 |. |85C0 test eax,eax 00401642 |. |0F85 FF000000 jnz 00401747 ; // 关键跳转
大概的流程是:
。。。直接看C++代码吧,我也说不清楚:
// CrackMeDemo.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "iostream" int _tmain(int argc, _TCHAR* argv[]) { char Name[100] = "bbdxf"; char key[100] = {0}; int nLen = strlen(Name); int uStart = 0x81276345; for (int i=0;i<nLen;i++) { uStart += Name[i]; uStart = uStart ^ (i<<8); uStart *= (i+1)*(~(nLen*i)); } printf("hex: %X\r\n",uStart); printf("Key: %lu\r\n",uStart); system("pause"); return 0; }
BY 笨笨D幸福
[反汇编练习] 160个CrackMe之019,布布扣,bubuko.com
原文:http://www.cnblogs.com/bbdxf/p/3810906.html