本帖最后由 海天一色001 于 2019-5-2 14:20 编辑
第22个CM,又回到了VB程序中,打开它看看:
随意输入字符,点击按钮,弹出错误提示:
错误提示的文本信息有了。这个程序有个菜单命令,打开看看,Restart点开没发现变化,About弹出一个提示框,Quit是退出命令。
先查壳,无壳:
第一步、爆破:
OD载入CarLitoZ.1.exe,然后先用智能搜索查找字符串:
这次很轻松地找到了错误及正确提示。
双击00402F51这一行错误提示处,返回CPU窗口:
观察反汇编代码,在00402F44处跳转到00402FD5处跳过了错误提示,但在它的下一行00402F49处却是从上面跳过来的,所以想要让这个跳转生效,必须让00402F49的来源处跳转命令失效:
在00402F49处右键选择“转到---je来自00402DE9”,
来到此处,je跳转指令跳过了正确提示,赶紧把它nop掉,
然后存为CarLitoZ.1_nop.exe,试运行一下,不输入任何字符点击按钮,弹出正确提示,成功了。
第二步、追码:
在刚才nop掉的00402DE9处选择撤消修改选项,恢复原程序的代码:
有跳转就会有比较,在00402DE9上面肯定会有一个比较指令,没有的话也会有一个call之类的来进行比较。向上查看,注释栏里很快看到了__vbaVarTstEq这个东东!
再向上,应该是var18与 var28(也就是[ecx]=ds:[esi+0x34]与[edx]=ss:[ebp-0x6C])进行比较;再向上,发现00402D9D处将ss:[ebp-0x6C]进行赋值的地方,却没有给ds:[esi+0x34]赋值的指令!
再向上到段首处,有3个call,有两个都是关于控制控件的,只有00402D7E处的“call dword ptr ds:[ebx+0x6F8]”很可疑,估计计算注册码就在这里面了!
[Asm] 纯文本查看 复制代码 00402D94 . FF15 34614000 call dword ptr ds:[<&MSVBVM50.__vbaHresultCheckObj>] ; msvbvm50.__vbaHresultCheckObj
00402D7E . FF93 F8060000 call dword ptr ds:[ebx+0x6F8] ; ?????
00402D60 . FF53 04 call dword ptr ds:[ebx+0x4] ; msvbvm50.BASIC_CLASS_AddRef
来到段首00402D20处下断,输入“52pojie”,点击按钮,程序中断,F8单步向下,到00402D84处,在堆栈窗口中上下翻看,看到[ebp-318]=“52pojie”,是我输入的假码;[ebp-308]=“rkh1oyie”,怀疑是真码,
将其填入CarLitoZ.1.exe 的文本框中,点击按钮,弹出成功提示,确定后文本框、按钮均变灰,右下角的“Unregistered”变成了“REGISTERED”。
把真码“rkh1oyie”记在纸上,一会儿在OD中找一找看是怎么来的。重载程序,文本框为空,按钮变灰,右下角为“REGISTERED”,无法输入了!怎么回事?
在窗体上有个菜单命令“File”,点开“Restrat”一下,程序界面回到了未注册时的初始情况,可以输入了。
再输入“52pojie”,点击按钮,程序再次中断,这次F8到到00402D7E 处,F7跟入自己怀疑的call中,
看到00401F11处,直接一个大跳转,F8过去,来到00403230处:
F8继续向下,过了很长一段时间,期间不断地上下翻看堆栈窗口的数据,随着指令的运行,从ss:[ ebp-1C]开始向上不断地存储“UNICODE "bPe CrackMe v1.0 "”,一直到运行完004035FA处的指令,才看到将输入的假码存入ss:[ebp-18]中。此时的堆栈窗口里,在假码之上有8个“UNICODE "bPe CrackMe v1.0 "”了。
不应该拿假码与这串字符进行各类计算得到真码吗?但也不需要与8个一样的字符分别运算吧?
继续向下进行:到00403616处,[eax]=假码,下一句是mid函数,要从假码中取字符了!应该是从这里开始运算了吧:
[Asm] 纯文本查看 复制代码 00403616 > \8B45 E8 mov eax,dword ptr ss:[ebp-0x18] ; 得到假码
00403619 . 8B3D 58614000 mov edi,dword ptr ds:[<&MSVBVM50.#rtcMidCharVar_632>] ; msvbvm50.rtcMidCharVar
0040361F . 8985 ACFDFFFF mov dword ptr ss:[ebp-0x254],eax ; ss:[ebp-0x254]=[eax]:假码
00403625 . 8B45 E4 mov eax,dword ptr ss:[ebp-0x1C] ; [eax]=(UNICODE "bPe CrackMe v1.0 ")
00403628 . 8D55 84 lea edx,dword ptr ss:[ebp-0x7C]
0040362B . 8945 9C mov dword ptr ss:[ebp-0x64],eax
0040362E . 52 push edx ; /Length8 = 0x2
0040362F . 8D45 94 lea eax,dword ptr ss:[ebp-0x6C] ; |
00403632 . 6A 06 push 0x6 ; |Start = 0x6
00403634 . 8D8D 74FFFFFF lea ecx,dword ptr ss:[ebp-0x8C] ; |
0040363A . BB 02000000 mov ebx,0x2 ; |
0040363F . 50 push eax ; |dString8 =0012FAC0
00403640 . 51 push ecx ; |RetBUFFER = NULL
00403641 . 8975 E8 mov dword ptr ss:[ebp-0x18],esi ; |
00403644 . C785 A4FDFFFF>mov dword ptr ss:[ebp-0x25C],0x8008 ; |
0040364E . C745 8C 01000>mov dword ptr ss:[ebp-0x74],0x1 ; |
00403655 . 895D 84 mov dword ptr ss:[ebp-0x7C],ebx ; |
00403658 . 8975 E4 mov dword ptr ss:[ebp-0x1C],esi ; |
0040365B . C745 94 08000>mov dword ptr ss:[ebp-0x6C],0x8 ; |
00403662 . FFD7 call edi ; \rtcMidCharVar
一直运行完00403662一句,仔细研究代码,发现自己的猜测竟然不对:
虽然eax得到了假码,可立即又存到了ss:[ebp-0x254]中,eax中又存了UNICODE "bPe CrackMe v1.0 "这个东西,并在下面mid函数中取了第6位的字符“r”出来存入ss:[ebp-0x84]中,而不是取假码中的字符:
以前对Length8 = 0x2不理解,长度不是取两个吗,怎么就取出来了一个字符,原来这是UNICODE格式,两个字节只存了1个UNICODE字符!以前在017中的疑惑在这里得到了解答,有一种高兴的感觉!
下面又是几个相同作用的代码段,分别从第9位、第143位、第16位、第161位、第171位、第166位、第168位、取字符存入堆栈中ss:[ebp-0xB4]、 ss:[ebp-0xF4] 、ss:[ebp-0x134]、 ss:[ebp-0x174]、 ss:[ebp-0x1B4]、 ss:[ebp-0x1F4]、 ss:[ebp-0x234],但这个字符串没有那么长啊!估计是OD中信息框及堆栈中显示不全,那就从内存中看看:
00403664处运行后,再点一下这一行,信息栏显示[eax]= ss:[ebp-0x20]= UNICODE "bPe CrackMe v1.0 ",
右键点击eax这一行,选择“数据窗口中跟随数值”,数据显示了00163B64开始的数据,但显示的是ASCII数据,
再改成UNICode的,这下看完整了,这正是About窗口上的内容嘛!并且这个字串从00163B64开始,到00163E07结束,共有675个内存字节,够用了!
F8运行到0040382C,查看堆栈中取出的这几个字符,与纸上的真码一对照,正好一样!如果这就是注册码的每位字符,下一步就是将它们连接起来了!
从0040383E至004038B7地址,注释中看出应该是一个整体的代码,作用可能是进行比较(__vbaVarTstEq),但它里面还有7个小段,var18=var18+var28,
第一个小段中,F8运行的同时认真地观察堆栈窗口:
0040383E处运行后,var18 = 0012F1C0,堆栈中0012F1C0地址数据是0x8008,而它下面0012F1C8处的数据是“52pojie”这个假码;继续向下,
00403845处运行后,var18 = 0012F390,而我想要的结果“r”存在0012F398中;
0040384C处运行后,var28 = 0012F360,实际上数据应该存在0012F360+8=0012F368中,这时看到了“k”;
0040384D处运行后,saveto8 = 0012F350,数据也应该是存在0012F358中;
0040384E处运行后,var18 =0012F350,而0012F358中果然出现了“rk”两个连接好的字符!
继续第二个小段,var18 = 0012F310,在0012F318中出现了“rkh”三个连接好的字符;
一直到最后一个小段(004038AB至004038B4处)运行结束后var18 = 0012F1D0,在0012F1D8处则是真码“rkh1oyie”。
[Asm] 纯文本查看 复制代码 0040383E . 52 push edx ; /var18 = 00150608
0040383F . 8D8D 44FFFFFF lea ecx,dword ptr ss:[ebp-0xBC] ; |
00403845 . 50 push eax ; |/var18 = 0012F1D0
00403846 . 8D95 34FFFFFF lea edx,dword ptr ss:[ebp-0xCC] ; ||
0040384C . 51 push ecx ; ||var28 = 0015B320
0040384D . 52 push edx ; ||saveto8 = 00150608
0040384E . FFD7 call edi ; |\__vbaVarAdd
00403850 . 50 push eax ; |/var18 = 0012F1D0
00403851 . 8D85 04FFFFFF lea eax,dword ptr ss:[ebp-0xFC] ; ||
00403857 . 8D8D F4FEFFFF lea ecx,dword ptr ss:[ebp-0x10C] ; ||
0040385D . 50 push eax ; ||var28 = 0012F1D0
0040385E . 51 push ecx ; ||saveto8 = 0015B320
0040385F . FFD7 call edi ; |\__vbaVarAdd
00403861 . 50 push eax ; |/var18 = 0012F1D0
00403862 . 8D95 C4FEFFFF lea edx,dword ptr ss:[ebp-0x13C] ; ||
00403868 . 8D85 B4FEFFFF lea eax,dword ptr ss:[ebp-0x14C] ; ||
0040386E . 52 push edx ; ||var28 = 00150608
0040386F . 50 push eax ; ||saveto8 = 0012F1D0
00403870 . FFD7 call edi ; |\__vbaVarAdd
00403872 . 8D8D 84FEFFFF lea ecx,dword ptr ss:[ebp-0x17C] ; |
00403878 . 50 push eax ; |/var18 = 0012F1D0
00403879 . 8D95 74FEFFFF lea edx,dword ptr ss:[ebp-0x18C] ; ||
0040387F . 51 push ecx ; ||var28 = 0015B320
00403880 . 52 push edx ; ||saveto8 = 00150608
00403881 . FFD7 call edi ; |\__vbaVarAdd
00403883 . 50 push eax ; |/var18 = 0012F1D0
00403884 . 8D85 44FEFFFF lea eax,dword ptr ss:[ebp-0x1BC] ; ||
0040388A . 8D8D 34FEFFFF lea ecx,dword ptr ss:[ebp-0x1CC] ; ||
00403890 . 50 push eax ; ||var28 = 0012F1D0
00403891 . 51 push ecx ; ||saveto8 = 0015B320
00403892 . FFD7 call edi ; |\__vbaVarAdd
00403894 . 50 push eax ; |/var18 = 0012F1D0
00403895 . 8D95 04FEFFFF lea edx,dword ptr ss:[ebp-0x1FC] ; ||
0040389B . 8D85 F4FDFFFF lea eax,dword ptr ss:[ebp-0x20C] ; ||
004038A1 . 52 push edx ; ||var28 = 00150608
004038A2 . 50 push eax ; ||saveto8 = 0012F1D0
004038A3 . FFD7 call edi ; |\__vbaVarAdd
004038A5 . 8D8D C4FDFFFF lea ecx,dword ptr ss:[ebp-0x23C] ; |
004038AB . 50 push eax ; |/var18 = 0012F1D0
004038AC . 51 push ecx ; ||var28 = 0015B320
004038AD . 8D95 B4FDFFFF lea edx,dword ptr ss:[ebp-0x24C] ; ||
004038B3 . 52 push edx ; ||saveto8 = 00150608
004038B4 . FFD7 call edi ; |\__vbaVarAdd
004038B6 . 50 push eax ; |var28 = 0012F1D0
004038B7 . FF15 6C614000 call dword ptr ds:[<&MSVBVM50.__vbaVarTs>; \__vbaVarTstEq
7个小代码段结束后,整个大段代码如上,此时__vbaVarTstEq的参数应该是最上方0040383E处的var18 = 00150608和最下方004038B6处的var28 = 0012F1D0了。
var28存了真码,此时的var18应该就是存的假码,要找一找这个数值。堆栈窗口中从最上到最下的范围,是0012D000到0012FFFC,00150608不在其中,无法通过堆栈找到它。而00150608是寄存器edx的地址,那么右键点击edx的地址,选择“数据窗口中跟随”命令,
地址栏中看到00150608的数据为7C99E5C0,如果是0015060F的数据则是FF。不知道这样查找出来的对不对,反正与var28肯定是对不上了。
为了能弄明白,试着F7跟入call中,进入系统领空内看看:
从7412B9A8处继续F7进call:
接下来又有call:
[Asm] 纯文本查看 复制代码 74120632 FF73 08 push dword ptr ds:[ebx+0x8]
74120635 FF72 08 push dword ptr ds:[edx+0x8]
74120638 FF75 08 push dword ptr ss:[ebp+0x8]
7412063B E8 BC3FF0FF [color=#ff0000] call msvbvm50.740245FC[/color]
。。。。。。
[Asm] 纯文本查看 复制代码 7402460D FF7424 0C push dword ptr ss:[esp+0xC]
74024611 FF7424 0C push dword ptr ss:[esp+0xC]
74024615 50 push eax
74024616 E8 48EFFFFF call msvbvm50.__vbaStrComp
又有3个call,见到了熟悉的__vbaStrComp指令,在上面两行的push指令分别是真码与假码,所以,虽然不明白var18的值到底怎么变成了假码,还是认为这个__vbaVarTstEq是比的真假码,结果存入eax中。
从系统领空出来,到了004038BD处将比较结果转到edi中:
继续F8,又过了很长时间,返回到00402D84处,进入了按钮事件中。
找到了注册码,但是还不太明白是如何对真假码进行比较的,主要是对数据在内存中的存储还是不够清楚。
现在爆破很快就能搞定,追码相对吃力,基础知识的重要性开始体现出来,所以得认真学一学汇编语言了。
022破解完成,注册机用VB编写,很简单,主要代码如下:
[Visual Basic] 纯文本查看 复制代码 Private Sub Command1_Click()
Dim StrAbout As String
Dim Serial As String
StrAbout =[font="][size=10.5pt] "bPeCrackMe v1.0 This CrackMe it's to trainer your VB cracking ability Developed by CarLitoZ"[/size][/font]
Serial = Mid(StrAbout, 6, 1) & Mid(StrAbout, 9, 1) & Mid(StrAbout, 143, 1) & Mid(StrAbout, 16,1) & Mid(StrAbout, 161, 1) & Mid(StrAbout, 171, 1) & Mid(StrAbout, 166, 1) & Mid(StrAbout, 168, 1)
Text1.Text = Serial
End Sub
这次破解练习开始也没想只用OD进行,在分析过程中能进行下去,所以没有使用SmartCheck和VB Decompiler,基本破解完成后才想起这两个软件,分别运行了一下,程序运行过程就比较清晰了,是对分析有很大帮助的,可以节省不少时间呀!
另:写完之后看了一下网上其他的破解过程,应该都是大神了,很轻松就能找到关键代码进行分析,而且对整个程序都很了解,比如在程序中如果输入注册码正确,那么会生成一个c:\windows\MTR.dat文件,并将文本“trv2156j0e”写入文件,下次再使用这个程序时,如果存在这个文件且文件内容是“trv2156j0e”,那么文本框无法输入,右下方显示已注册的提示,只有执行“restart”命令,清除dat文件的内容,恢复未注册状态。关于VB读写文件的知识我又学习了一些!
附件
022.zip
(250.24 KB, 下载次数: 2)
,含CM原程序、爆破后的程序、注册机、OD的调试文件等。
百度链接是:http://pan.baidu.com/s/1skMkJY9密码: 86pm,160个CM、我已练习过的前22个crackme程序(不含012)都在里面。
|