[反汇编练习] 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不报毒,个人承诺绝对不会进行任何和木马病毒相关内容。http://images.cnitblog.com/blog/573547/201406/101049468116028.png2、程序分析:想要破解一个程序,必须先了解这个程序。所以,在破解过程中,对最初程序的分析很重要,他可以帮助我们理解作者的目的和意图,特别是对于注册码的处理细节,从而方便我们反向跟踪和推导。和上一节一样,打开CHM,选择第二个Afkayas,保存下来。运行程序,崩溃,缺少msvbvm50.dll,程序无法运行。没办法,上网上搜索一个,放到程序同一级目录,再次运行,OK。程序界面如下:http://images.cnitblog.com/blog/573547/201406/101049495301298.png这是一个标准的Name/Serial注册码方式,二话不说,来个伪码测试:Name: 111222 Serial: 3334444点击OK,弹出了一个错误对话框,You Get Wrong,Try again!3、思路分析和破解流程:首先,按照经验,有对话框提示的程序可以通过堆栈查找调用的位置。方法如下:输入伪码,点击OK,弹出错误对话框,此时不要关闭这个对话框,切换到OD,点击暂停程序,然后Ctrl+K到堆栈视图,如下:http://images.cnitblog.com/blog/573547/201406/101049516086696.png到了这里基本蒙圈了,竟然不是一般的C/C++代码,看看后面的Called from大部分来自msvbvm50,user32,根据名称百度一下,发现是使用VB的模块写的。再查看红色部分,发现表面上和对话框相关的只有msvbvm50.rtcmsgbox和user32.MessageBoxIndirectA,最主要的是msvbvm50.rtcMsgBox的调用来自AfKayas_.0040261C,所以我们基本可以断定rtcMsgBox是Vb中弹出对话框相关的东西,不要犹豫,选中它,右键->show call。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:
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:,eax
00402603 . |8D45 94 lea eax,dword ptr ss:
00402606 . |8D4D A4 lea ecx,dword ptr ss:
00402609 . |50 push eax
0040260A . |8D55 B4 lea edx,dword ptr ss:
0040260D . |51 push ecx
0040260E . |52 push edx
0040260F . |8D45 C4 lea eax,dword ptr ss:
00402612 . |6A 00 push 0x0
00402614 . |50 push eax
00402615 . |C745 C4 08000>mov dword ptr ss:,0x8
0040261C . |FF15 10414000 call dword ptr ds:[<&MSVBVM50.#595>] ;msvbvm50.rtcMsgBox
将代码稍微向上查看,发现最近的地方就有“Try again”和“You get wrong”的提示,我们基本就可以断定就是这里了。继续向上,看看判断的逻辑部分在哪里: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:,ecx
00402579 .66:85F6 test si,si
0040257C .8945 94 mov dword ptr ss:,eax
0040257F .894D AC mov dword ptr ss:,ecx
00402582 .8945 A4 mov dword ptr ss:,eax
00402585 .894D BC mov dword ptr ss:,ecx
00402588 .8945 B4 mov dword ptr ss:,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:
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:
004025AB .8945 CC mov dword ptr ss:,eax
004025AE .8D55 A4 lea edx,dword ptr ss:
004025B1 .51 push ecx
004025B2 .8D45 B4 lea eax,dword ptr ss:
004025B5 .52 push edx
004025B6 .50 push eax
004025B7 .8D4D C4 lea ecx,dword ptr ss:
004025BA .6A 00 push 0x0
004025BC .51 push ecx
004025BD .C745 C4 08000>mov dword ptr ss:,0x8
004025C4 .FF15 10414000 call dword ptr ds:[<&MSVBVM50.#595>] ;msvbvm50.rtcMsgBox
004025CA .8D4D E8 lea ecx,dword ptr ss:
004025CD .FF15 80414000 call dword ptr ds:[<&MSVBVM50.__vbaFreeS>;msvbvm50.__vbaFreeStr
004025D3 .8D55 94 lea edx,dword ptr ss:
004025D6 .8D45 A4 lea eax,dword ptr ss:
004025D9 .52 push edx
004025DA .8D4D B4 lea ecx,dword ptr ss:
004025DD .50 push eax
004025DE .8D55 C4 lea edx,dword ptr ss:
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:
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相关的东西,分析后代码如下:00402403 .FF15 04414000 call dword ptr ds:[<&MSVBVM50.__vbaHresultChec>;MSVBVM50.__vbaHresultCheckObj
00402409 >8B95 50FFFFFF mov edx,dword ptr ss:
0040240F .8B45 E4 mov eax,dword ptr ss:
00402412 .50 push eax ;//eax=111222,name
00402413 .8B1A mov ebx,dword ptr ds:
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: ;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:
0040244A .FF15 70414000 call dword ptr ds:[<&MSVBVM50.__vbaStrMove>] ;MSVBVM50.__vbaStrMove
00402450 .8BBD 50FFFFFF mov edi,dword ptr ss:
00402456 .50 push eax ;// 585235
00402457 .57 push edi ;// 0091B51C
00402458 .FF93 A4000000 call dword ptr ds:
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:
00402477 .8D4D E4 lea ecx,dword ptr ss:
0040247A .50 push eax
0040247B .8D55 E8 lea edx,dword ptr ss:
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:
0040248E .8D4D D8 lea ecx,dword ptr ss:
00402491 .8D55 DC lea edx,dword ptr ss:
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:
004024A1 .83C4 10 add esp,0x10
004024A4 .56 push esi
004024A5 .FF90 04030000 call dword ptr ds:
004024AB .8B1D 0C414000 mov ebx,dword ptr ds:[<&MSVBVM50.__vbaObjSet>] ;MSVBVM50.__vbaObjSet
004024B1 .50 push eax
004024B2 .8D45 DC lea eax,dword ptr ss:
004024B5 .50 push eax
004024B6 .FFD3 call ebx ;<&MSVBVM50.__vbaObjSet>
004024B8 .8BF8 mov edi,eax
004024BA .8D55 E8 lea edx,dword ptr ss:
004024BD .52 push edx
004024BE .57 push edi
004024BF .8B0F mov ecx,dword ptr ds:
004024C1 .FF91 A0000000 call dword ptr ds:
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:
004024E4 .50 push eax
004024E5 .8D45 D8 lea eax,dword ptr ss:
004024E8 .50 push eax
004024E9 .FFD3 call ebx
004024EB .8BF0 mov esi,eax
004024ED .8D55 E4 lea edx,dword ptr ss:
004024F0 .52 push edx
004024F1 .56 push esi
004024F2 .8B0E mov ecx,dword ptr ds:
004024F4 .FF91 A0000000 call dword ptr ds:
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: ;eax=3334444
00402513 .8B4D E4 mov ecx,dword ptr ss: ;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:
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:
0040253E .F7DE neg esi ;取补
00402540 .8D45 E8 lea eax,dword ptr ss:
00402543 .52 push edx
00402544 .1BF6 sbb esi,esi
00402546 .8D4D E4 lea ecx,dword ptr ss:
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:
0040255C .8D45 DC lea eax,dword ptr ss:
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:,ecx
00402579 .66:85F6 test si,si ;esi=0,ZF=1
0040257C .8945 94 mov dword ptr ss:,eax
0040257F .894D AC mov dword ptr ss:,ecx
00402582 .8945 A4 mov dword ptr ss:,eax
00402585 .894D BC mov dword ptr ss:,ecx
00402588 .8945 B4 mov dword ptr ss:,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
其实代码很简单,经过一遍跟踪,基本都出来了,重点分析部分如下:00402412 .50 push eax ;//eax=111222,name
00402413 .8B1A mov ebx,dword ptr ds:
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: ;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相关的东西:00402510 >8B45 E8 mov eax,dword ptr ss: ;eax=3334444
00402513 .8B4D E4 mov ecx,dword ptr ss: ;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:
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代码如下:// CrackMe160.cpp : 定义控制台应用程序的入口点。
// 002
#include "stdafx.h"
#include <stdio.h>
#include "iostream"
char buff = {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;
printf("AKA-%d\r\n",nRet);
}else{
printf("Input error!\r\n");
}
system("pause");
return 0;
}
http://images.cnitblog.com/blog/573547/201406/101049542805980.png
这是教我们的吗 谢谢大神让我们菜鸟学习 D13 发表于 2014-6-11 13:47
楼主一起搞160?争取一个月搞定?
{:17_1079:}有工作要伺候,没时间啊。都是现学现弄,怕水平赶不上进度呢。 刘宏伟大人丶 发表于 2014-6-10 19:48
楼主连发2贴 这个2贴 我感觉沙发必须是我的在火之前占个前排
这两个花了牛鼻子气才弄好的,努力争取不断更已经满足了 xiaowenyu520 发表于 2014-6-10 19:48
坐等发到160个
{:17_1081:}争取做到不断更,毕竟越到后面越难,没信心啊! 楼主要发完这个吗 syh123q 发表于 2014-6-10 19:50
楼主要发完这个吗
力争每天至少弄一个,边学习边更新啊! 学习了。。。 感谢楼主的教导!