首页 > 代码库 > [反汇编练习] 160个CrackMe之002
[反汇编练习] 160个CrackMe之002
[反汇编练习] 160个CrackMe之002。
本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注册机的东西。
其中,文章中按照如下逻辑编排(解决如下问题):
1、使用什么环境和工具
2、程序分析
3、思路分析和破解流程
4、注册机的探索
1、工具和环境:
WinXP SP3 + 52Pojie六周年纪念版OD + PEID + 汇编金手指。
160个CrackMe的打包文件。
下载地址: http://pan.baidu.com/s/1xUWOY 密码: jbnq
注:
1、Win7系统对于模块和程序开启了随机初始地址的功能,会给分析带来很大的负担,所以不建议使用Win7进行分析。
2、以上工具都是在52PoJie论坛下的原版程序,NOD32不报毒,个人承诺绝对不会进行任何和木马病毒相关内容。
2、程序分析:
想要破解一个程序,必须先了解这个程序。所以,在破解过程中,对最初程序的分析很重要,他可以帮助我们理解作者的目的和意图,特别是对于注册码的处理细节,从而方便我们反向跟踪和推导。
和上一节一样,打开CHM,选择第二个Afkayas,保存下来。运行程序,崩溃,缺少msvbvm50.dll,程序无法运行。没办法,上网上搜索一个,放到程序同一级目录,再次运行,OK。程序界面如下:
这是一个标准的Name/Serial注册码方式,二话不说,来个伪码测试:
Name: 111222 Serial: 3334444
点击OK,弹出了一个错误对话框,You Get Wrong,Try again!
3、思路分析和破解流程:
首先,按照经验,有对话框提示的程序可以通过堆栈查找调用的位置。方法如下:输入伪码,点击OK,弹出错误对话框,此时不要关闭这个对话框,切换到OD,点击暂停程序,然后Ctrl+K到堆栈视图,如下:
到了这里基本蒙圈了,竟然不是一般的C/C++代码,看看后面的Called from大部分来自msvbvm50,user32,根据名称百度一下,发现是使用VB的模块写的。再查看红色部分,发现表面上和对话框相关的只有msvbvm50.rtcmsgbox和user32.MessageBoxIndirectA,最主要的是msvbvm50.rtcMsgBox的调用来自AfKayas_.0040261C,所以我们基本可以断定rtcMsgBox是Vb中弹出对话框相关的东西,不要犹豫,选中它,右键->show call。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 004025E3 . /EB 56 jmp short 0040263B 004025E5 > |68 C81B4000 push 00401BC8 ; UNICODE "You Get Wrong" 004025EA . |68 9C1B4000 push 00401B9C ; ASCII "\r" 004025EF . |FFD7 call edi 004025F1 . |8BD0 mov edx,eax 004025F3 . |8D4D E8 lea ecx,dword ptr ss:[ebp-0x18] 004025F6 . |FFD3 call ebx 004025F8 . |50 push eax 004025F9 . |68 E81B4000 push 00401BE8 ; UNICODE "Try Again" 004025FE . |FFD7 call edi 00402600 . |8945 CC mov dword ptr ss:[ebp-0x34],eax 00402603 . |8D45 94 lea eax,dword ptr ss:[ebp-0x6C] 00402606 . |8D4D A4 lea ecx,dword ptr ss:[ebp-0x5C] 00402609 . |50 push eax 0040260A . |8D55 B4 lea edx,dword ptr ss:[ebp-0x4C] 0040260D . |51 push ecx 0040260E . |52 push edx 0040260F . |8D45 C4 lea eax,dword ptr ss:[ebp-0x3C] 00402612 . |6A 00 push 0x0 00402614 . |50 push eax 00402615 . |C745 C4 08000>mov dword ptr ss:[ebp-0x3C],0x8 0040261C . |FF15 10414000 call dword ptr ds:[<&MSVBVM50.#595>] ; msvbvm50.rtcMsgBox |
将代码稍微向上查看,发现最近的地方就有“Try again”和“You get wrong”的提示,我们基本就可以断定就是这里了。继续向上,看看判断的逻辑部分在哪里:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 00402569 . 83C4 0C add esp,0xC 0040256C . B9 04000280 mov ecx,0x80020004 00402571 . B8 0A000000 mov eax,0xA 00402576 . 894D 9C mov dword ptr ss:[ebp-0x64],ecx 00402579 . 66:85F6 test si,si 0040257C . 8945 94 mov dword ptr ss:[ebp-0x6C],eax 0040257F . 894D AC mov dword ptr ss:[ebp-0x54],ecx 00402582 . 8945 A4 mov dword ptr ss:[ebp-0x5C],eax 00402585 . 894D BC mov dword ptr ss:[ebp-0x44],ecx 00402588 . 8945 B4 mov dword ptr ss:[ebp-0x4C],eax 0040258B . 74 58 je short 004025E5 ; 判断应该是这里吧? 0040258D . 68 801B4000 push 00401B80 ; UNICODE "You Get It" 00402592 . 68 9C1B4000 push 00401B9C ; ASCII "\r" 00402597 . FFD7 call edi 00402599 . 8BD0 mov edx,eax 0040259B . 8D4D E8 lea ecx,dword ptr ss:[ebp-0x18] 0040259E . FFD3 call ebx 004025A0 . 50 push eax 004025A1 . 68 A81B4000 push 00401BA8 ; UNICODE "KeyGen It Now" 004025A6 . FFD7 call edi 004025A8 . 8D4D 94 lea ecx,dword ptr ss:[ebp-0x6C] 004025AB . 8945 CC mov dword ptr ss:[ebp-0x34],eax 004025AE . 8D55 A4 lea edx,dword ptr ss:[ebp-0x5C] 004025B1 . 51 push ecx 004025B2 . 8D45 B4 lea eax,dword ptr ss:[ebp-0x4C] 004025B5 . 52 push edx 004025B6 . 50 push eax 004025B7 . 8D4D C4 lea ecx,dword ptr ss:[ebp-0x3C] 004025BA . 6A 00 push 0x0 004025BC . 51 push ecx 004025BD . C745 C4 08000>mov dword ptr ss:[ebp-0x3C],0x8 004025C4 . FF15 10414000 call dword ptr ds:[<&MSVBVM50.#595>] ; msvbvm50.rtcMsgBox 004025CA . 8D4D E8 lea ecx,dword ptr ss:[ebp-0x18] 004025CD . FF15 80414000 call dword ptr ds:[<&MSVBVM50.__vbaFreeS>; msvbvm50.__vbaFreeStr 004025D3 . 8D55 94 lea edx,dword ptr ss:[ebp-0x6C] 004025D6 . 8D45 A4 lea eax,dword ptr ss:[ebp-0x5C] 004025D9 . 52 push edx 004025DA . 8D4D B4 lea ecx,dword ptr ss:[ebp-0x4C] 004025DD . 50 push eax 004025DE . 8D55 C4 lea edx,dword ptr ss:[ebp-0x3C] 004025E1 . 51 push ecx 004025E2 . 52 push edx 004025E3 . EB 56 jmp short 0040263B 004025E5 > 68 C81B4000 push 00401BC8 ; UNICODE "You Get Wrong" 004025EA . 68 9C1B4000 push 00401B9C ; ASCII "\r" 004025EF . FFD7 call edi 004025F1 . 8BD0 mov edx,eax 004025F3 . 8D4D E8 lea ecx,dword ptr ss:[ebp-0x18] 004025F6 . FFD3 call ebx 004025F8 . 50 push eax 004025F9 . 68 E81B4000 push 00401BE8 ; UNICODE "Try Again" 004025FE . FFD7 call edi |
很简单吧?直接在”You get it ”的旁边就有一个JE跳转,在OD查看发现如果跳转实现就提示错误,不实现就提示正确,爆破开始啦!选中je那一行,右键->Binary->Fill with NOPs. 这时在程序里随意输入试试,哈哈,爆破成功!
4、注册机探索:
由于我们在跳转附近没有发现任何类注册码的东西,所以,我们需要将这里块的内容F8跟踪一下,大概地看看那些地方可能和注册码相关。我们向上查找,在这段程序的开头(即找到最近的那个retn,下面开头一般是push ebp等)下断点:
00402310 > \55 push ebp // 程序段头
单步F8跟踪,将重要信息添加注释,特别是和Name/Serial相关的东西,分析后代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | 00402403 . FF15 04414000 call dword ptr ds:[<&MSVBVM50.__vbaHresultChec>; MSVBVM50.__vbaHresultCheckObj 00402409 > 8B95 50FFFFFF mov edx,dword ptr ss:[ebp-0xB0] 0040240F . 8B45 E4 mov eax,dword ptr ss:[ebp-0x1C] 00402412 . 50 push eax ; //eax=111222,name 00402413 . 8B1A mov ebx,dword ptr ds:[edx] 00402415 . FF15 E4404000 call dword ptr ds:[<&MSVBVM50.__vbaLenBstr>] ; MSVBVM50.__vbaLenBstr 0040241B . 8BF8 mov edi,eax ; edi=6 0040241D . 8B4D E8 mov ecx,dword ptr ss:[ebp-0x18] ; ecx=1111222地址 00402420 . 69FF FB7C0100 imul edi,edi,0x17CFB ; // 乘法,edi*0x17CFB 00402426 . 51 push ecx 00402427 . 0F80 91020000 jo 004026BE 0040242D . FF15 F8404000 call dword ptr ds:[<&MSVBVM50.#516>] ; MSVBVM50.rtcAnsiValueBstr 00402433 . 0FBFD0 movsx edx,ax 00402436 . 03FA add edi,edx ; // edi=edi+edx(0x31) 00402438 . 0F80 80020000 jo 004026BE 0040243E . 57 push edi 0040243F . FF15 E0404000 call dword ptr ds:[<&MSVBVM50.__vbaStrI4>] ; MSVBVM50.__vbaStrI4 00402445 . 8BD0 mov edx,eax ; // eax=585235 00402447 . 8D4D E0 lea ecx,dword ptr ss:[ebp-0x20] 0040244A . FF15 70414000 call dword ptr ds:[<&MSVBVM50.__vbaStrMove>] ; MSVBVM50.__vbaStrMove 00402450 . 8BBD 50FFFFFF mov edi,dword ptr ss:[ebp-0xB0] 00402456 . 50 push eax ; // 585235 00402457 . 57 push edi ; // 0091B51C 00402458 . FF93 A4000000 call dword ptr ds:[ebx+0xA4] 0040245E . 85C0 test eax,eax ; // ==0 00402460 . 7D 12 jge short 00402474 00402462 . 68 A4000000 push 0xA4 00402467 . 68 5C1B4000 push 00401B5C 0040246C . 57 push edi 0040246D . 50 push eax 0040246E . FF15 04414000 call dword ptr ds:[<&MSVBVM50.__vbaHresultChec>; MSVBVM50.__vbaHresultCheckObj 00402474 > 8D45 E0 lea eax,dword ptr ss:[ebp-0x20] 00402477 . 8D4D E4 lea ecx,dword ptr ss:[ebp-0x1C] 0040247A . 50 push eax 0040247B . 8D55 E8 lea edx,dword ptr ss:[ebp-0x18] 0040247E . 51 push ecx 0040247F . 52 push edx 00402480 . 6A 03 push 0x3 00402482 . FF15 5C414000 call dword ptr ds:[<&MSVBVM50.__vbaFreeStrList>; MSVBVM50.__vbaFreeStrList 00402488 . 83C4 10 add esp,0x10 0040248B . 8D45 D4 lea eax,dword ptr ss:[ebp-0x2C] 0040248E . 8D4D D8 lea ecx,dword ptr ss:[ebp-0x28] 00402491 . 8D55 DC lea edx,dword ptr ss:[ebp-0x24] 00402494 . 50 push eax 00402495 . 51 push ecx 00402496 . 52 push edx 00402497 . 6A 03 push 0x3 00402499 . FF15 F4404000 call dword ptr ds:[<&MSVBVM50.__vbaFreeObjList>; MSVBVM50.__vbaFreeObjList 0040249F . 8B06 mov eax,dword ptr ds:[esi] 004024A1 . 83C4 10 add esp,0x10 004024A4 . 56 push esi 004024A5 . FF90 04030000 call dword ptr ds:[eax+0x304] 004024AB . 8B1D 0C414000 mov ebx,dword ptr ds:[<&MSVBVM50.__vbaObjSet>] ; MSVBVM50.__vbaObjSet 004024B1 . 50 push eax 004024B2 . 8D45 DC lea eax,dword ptr ss:[ebp-0x24] 004024B5 . 50 push eax 004024B6 . FFD3 call ebx ; <&MSVBVM50.__vbaObjSet> 004024B8 . 8BF8 mov edi,eax 004024BA . 8D55 E8 lea edx,dword ptr ss:[ebp-0x18] 004024BD . 52 push edx 004024BE . 57 push edi 004024BF . 8B0F mov ecx,dword ptr ds:[edi] 004024C1 . FF91 A0000000 call dword ptr ds:[ecx+0xA0] 004024C7 . 85C0 test eax,eax ; eax=0,zf=1 004024C9 . 7D 12 jge short 004024DD 004024CB . 68 A0000000 push 0xA0 004024D0 . 68 5C1B4000 push 00401B5C 004024D5 . 57 push edi 004024D6 . 50 push eax 004024D7 . FF15 04414000 call dword ptr ds:[<&MSVBVM50.__vbaHresultChec>; MSVBVM50.__vbaHresultCheckObj 004024DD > 56 push esi 004024DE . FF95 40FFFFFF call dword ptr ss:[ebp-0xC0] 004024E4 . 50 push eax 004024E5 . 8D45 D8 lea eax,dword ptr ss:[ebp-0x28] 004024E8 . 50 push eax 004024E9 . FFD3 call ebx 004024EB . 8BF0 mov esi,eax 004024ED . 8D55 E4 lea edx,dword ptr ss:[ebp-0x1C] 004024F0 . 52 push edx 004024F1 . 56 push esi 004024F2 . 8B0E mov ecx,dword ptr ds:[esi] 004024F4 . FF91 A0000000 call dword ptr ds:[ecx+0xA0] 004024FA . 85C0 test eax,eax ; eax=0 004024FC . 7D 12 jge short 00402510 004024FE . 68 A0000000 push 0xA0 00402503 . 68 5C1B4000 push 00401B5C 00402508 . 56 push esi 00402509 . 50 push eax 0040250A . FF15 04414000 call dword ptr ds:[<&MSVBVM50.__vbaHresultChec>; MSVBVM50.__vbaHresultCheckObj 00402510 > 8B45 E8 mov eax,dword ptr ss:[ebp-0x18] ; eax=3334444 00402513 . 8B4D E4 mov ecx,dword ptr ss:[ebp-0x1C] ; ecx=585235 00402516 . 8B3D 00414000 mov edi,dword ptr ds:[<&MSVBVM50.__vbaStrCat>] ; MSVBVM50.__vbaStrCat 0040251C . 50 push eax ; eax=3334444 0040251D . 68 701B4000 push 00401B70 ; UNICODE "AKA-" 00402522 . 51 push ecx ; ecx=585235 00402523 . FFD7 call edi ; <&MSVBVM50.__vbaStrCat> 00402525 . 8B1D 70414000 mov ebx,dword ptr ds:[<&MSVBVM50.__vbaStrMove>>; MSVBVM50.__vbaStrMove 0040252B . 8BD0 mov edx,eax ; edx=eax=AKA-585235 0040252D . 8D4D E0 lea ecx,dword ptr ss:[ebp-0x20] 00402530 . FFD3 call ebx ; <&MSVBVM50.__vbaStrMove> 00402532 . 50 push eax 00402533 . FF15 28414000 call dword ptr ds:[<&MSVBVM50.__vbaStrCmp>] ; MSVBVM50.__vbaStrCmp 00402539 . 8BF0 mov esi,eax ; eax=-1 0040253B . 8D55 E0 lea edx,dword ptr ss:[ebp-0x20] 0040253E . F7DE neg esi ; 取补 00402540 . 8D45 E8 lea eax,dword ptr ss:[ebp-0x18] 00402543 . 52 push edx 00402544 . 1BF6 sbb esi,esi 00402546 . 8D4D E4 lea ecx,dword ptr ss:[ebp-0x1C] 00402549 . 50 push eax 0040254A . 46 inc esi 0040254B . 51 push ecx 0040254C . 6A 03 push 0x3 0040254E . F7DE neg esi 00402550 . FF15 5C414000 call dword ptr ds:[<&MSVBVM50.__vbaFreeStrList>; MSVBVM50.__vbaFreeStrList 00402556 . 83C4 10 add esp,0x10 00402559 . 8D55 D8 lea edx,dword ptr ss:[ebp-0x28] 0040255C . 8D45 DC lea eax,dword ptr ss:[ebp-0x24] 0040255F . 52 push edx 00402560 . 50 push eax 00402561 . 6A 02 push 0x2 00402563 . FF15 F4404000 call dword ptr ds:[<&MSVBVM50.__vbaFreeObjList>; MSVBVM50.__vbaFreeObjList 00402569 . 83C4 0C add esp,0xC 0040256C . B9 04000280 mov ecx,0x80020004 00402571 . B8 0A000000 mov eax,0xA 00402576 . 894D 9C mov dword ptr ss:[ebp-0x64],ecx 00402579 . 66:85F6 test si,si ; esi=0,ZF=1 0040257C . 8945 94 mov dword ptr ss:[ebp-0x6C],eax 0040257F . 894D AC mov dword ptr ss:[ebp-0x54],ecx 00402582 . 8945 A4 mov dword ptr ss:[ebp-0x5C],eax 00402585 . 894D BC mov dword ptr ss:[ebp-0x44],ecx 00402588 . 8945 B4 mov dword ptr ss:[ebp-0x4C],eax 0040258B 74 58 je short 004025E5 ; // 爆破关键跳,NOP 0040258D . 68 801B4000 push 00401B80 ; UNICODE "You Get It" 00402592 . 68 9C1B4000 push 00401B9C ; ASCII "\r" 00402597 . FFD7 call edi |
其实代码很简单,经过一遍跟踪,基本都出来了,重点分析部分如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 00402412 . 50 push eax ; //eax=111222,name 00402413 . 8B1A mov ebx,dword ptr ds:[edx] 00402415 . FF15 E4404000 call dword ptr ds:[<&MSVBVM50.__vbaLenBstr>] ; MSVBVM50.__vbaLenBstr 0040241B . 8BF8 mov edi,eax ; edi=6 0040241D . 8B4D E8 mov ecx,dword ptr ss:[ebp-0x18] ; ecx=1111222地址 00402420 . 69FF FB7C0100 imul edi,edi,0x17CFB ; // 乘法,edi*0x17CFB 00402426 . 51 push ecx 00402427 . 0F80 91020000 jo 004026BE 0040242D . FF15 F8404000 call dword ptr ds:[<&MSVBVM50.#516>] ; MSVBVM50.rtcAnsiValueBstr 00402433 . 0FBFD0 movsx edx,ax 00402436 . 03FA add edi,edx ; // edi=edi+edx(0x31) 00402438 . 0F80 80020000 jo 004026BE 0040243E . 57 push edi 0040243F . FF15 E0404000 call dword ptr ds:[<&MSVBVM50.__vbaStrI4>] ; MSVBVM50.__vbaStrI4 00402445 . 8BD0 mov edx,eax ; // eax=585235 |
首先,eax为Name的地址,经过__vbaLenBstr计算的长度赋值给edi,然后edi=edi*0x17CFB,接着edi=edi+edx,而edx为Name字符串第一个字符Ansi的值,最后进过__vbaStrI4将edi的整数值转换为十进制字符串585235。
然后向下跟踪和字符串585235相关的东西:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 00402510 > 8B45 E8 mov eax,dword ptr ss:[ebp-0x18] ; eax=3334444 00402513 . 8B4D E4 mov ecx,dword ptr ss:[ebp-0x1C] ; ecx=585235 00402516 . 8B3D 00414000 mov edi,dword ptr ds:[<&MSVBVM50.__vbaStrCat>] ; MSVBVM50.__vbaStrCat 0040251C . 50 push eax ; eax=3334444 0040251D . 68 701B4000 push 00401B70 ; UNICODE "AKA-" 00402522 . 51 push ecx ; ecx=585235 00402523 . FFD7 call edi ; <&MSVBVM50.__vbaStrCat> 00402525 . 8B1D 70414000 mov ebx,dword ptr ds:[<&MSVBVM50.__vbaStrMove>>; MSVBVM50.__vbaStrMove 0040252B . 8BD0 mov edx,eax ; edx=eax=AKA-585235 0040252D . 8D4D E0 lea ecx,dword ptr ss:[ebp-0x20] 00402530 . FFD3 call ebx ; <&MSVBVM50.__vbaStrMove> 00402532 . 50 push eax 00402533 . FF15 28414000 call dword ptr ds:[<&MSVBVM50.__vbaStrCmp>] ; MSVBVM50.__vbaStrCmp 00402539 . 8BF0 mov esi,eax ; eax=-1 |
这段代码中将585235通过__vbaStrCat与”AKA-”连接到一起组成字符串”AKA-585235”,然后通过__vbaStrCmp函数与我们的Serial比较结果,最后返回值放到eax中,通过返回值确定是否正确。将这里的分析与上一块合到一起,很容易就可以得出最终的注册码。
小结一下:先取出注册码的长度len, 然后取出注册码第一个字符的ANSI值cName, 让后计算len*0x17CFB+cName,将计算的值转换为10进制文本,前面加上”AKA-”组成最后的注册码。
C/CPP代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // CrackMe160.cpp : 定义控制台应用程序的入口点。 // 002 #include "stdafx.h" #include <stdio.h> #include "iostream" char buff[100] = {0}; int _tmain( int argc, _TCHAR* argv[]) { printf ( "160CrackMe-002 Name/Serial\r\n\r\n" ); printf ( "Name:" ); gets_s(buff,100); int nLen = strlen (buff); if ( nLen > 0 ) { int nRet = nLen * 0x17CFB; nRet += buff[0]; printf ( "AKA-%d\r\n" ,nRet); } else { printf ( "Input error!\r\n" ); } system ( "pause" ); return 0; } |