初练160个CrakeMe程序之009
本帖最后由 海天一色001 于 2017-6-9 14:11 编辑第9个CM,这仍是一个VB程序,用的是用户名/注册码的保护方式,一星难度。
随意输入用户名时,OK按钮变得可用了;输入key,点击OK,弹出错误窗口:
PeiD检查后没壳;
第一步汉化:继续使用VB程序汉化专用工具VBExplorer,这仍是一个熟悉软件使用的过程。修改时,未完全按照原文翻译,使自己能够清楚作者的意图就行了。汉化后另存为CM009.exe。
汉化的地方为我用粉红色圈住的部分:在图中左下方的属性窗口修改程序的标题栏内容,我修改为“CM009 (海天一色汉化)”;在右侧字符串栏中点每个地址后的现字符串栏,修改成自己的内容。
修改后点上方工具栏中的三角形,运行修改后的程序,看是否合适,合适则另存为CM009.exe。汉化后程序界面如下:
第二步爆破:将CM009载入OD,查找字符串:
点击成功处的地址进入CPU窗口,来到地址00402308处,向上看了一下,在004022CB处 的“je CM009.00402391”指令跳过了成功。和上一个CM很相似,所以在这里nop掉就行了!
保存为CM009_nop.exe。
第三步追码:重新将CM009载入OD,查找字符串,然后点击成功处的地址进入CPU窗口,向上查找段首至00401FF0处下断,F9运行程序:
输入用户名“52pojie.cn”,密码“1234567890”,点击OK按钮,程序中断下来,F8单步向下,一堆堆的VB函数,很令人头疼!边单步走着,边看寄存器窗口、信息窗口、堆栈窗口的内容,唯恐错过了什么地方:很快来到下列代码处,从00402126-004021D1地址处是一个循环,作用是取用户名的每一字符的16进制ASCII值相加,存入ecx寄存器中,应该是从用户名计算注册码的一部分吧:00402126 .FF15 20414000 call dword ptr ds:[<&MSVBVM50.__vbaVarForInit>]; \执行初始化
0040212C .8B3D 04414000 mov edi,dword ptr ds:[<&MSVBVM50.__vbaFreeVarLis>;将缓冲区释放了
00402132 >85C0 test eax,eax ;循环开始
00402134 .0F84 9C000000 je CM009.004021D6
0040213A .8D55 94 lea edx,dword ptr ss:
0040213D .8D45 DC lea eax,dword ptr ss:
00402140 .52 push edx
00402141 .50 push eax
00402142 .C745 9C 01000>mov dword ptr ss:,0x1
00402149 .895D 94 mov dword ptr ss:,ebx
0040214C .FF15 90414000 call dword ptr ds:[<&MSVBVM50.__vbaI4Var>] ;msvbvm50.__vbaI4Var
00402152 .8D4D BC lea ecx,dword ptr ss: ; |
00402155 .50 push eax ; |Start = 0x2
00402156 .8D55 84 lea edx,dword ptr ss: ; |
00402159 .51 push ecx ; |dString8 = 0012F49C
0040215A .52 push edx ; |RetBUFFER = 0012F464
0040215B .FF15 38414000 call dword ptr ds:[<&MSVBVM50.#rtcMidCharVar_632>; \rtcMidCharVar
00402161 .8D45 84 lea eax,dword ptr ss:
00402164 .8D4D A8 lea ecx,dword ptr ss:
00402167 .50 push eax ; /String8 = 00000002
00402168 .51 push ecx ; |ARG2 = 0012F49C
00402169 .FF15 70414000 call dword ptr ds:[<&MSVBVM50.__vbaStrVarVal>] ; \__vbaStrVarVal
0040216F .50 push eax ; /String = 00000002 ???
00402170 .FF15 0C414000 call dword ptr ds:[<&MSVBVM50.#rtcAnsiValueBstr_>; \rtcAnsiValueBstr
00402176 .66:8985 4CFFF>mov word ptr ss:,ax
0040217D .8D55 CC lea edx,dword ptr ss:
00402180 .8D85 44FFFFFF lea eax,dword ptr ss:
00402186 .52 push edx ; /var18 = 0012F464
00402187 .8D8D 74FFFFFF lea ecx,dword ptr ss: ; |
0040218D .50 push eax ; |var28 = 00000002
0040218E .51 push ecx ; |saveto8 = 0012F49C
0040218F .899D 44FFFFFF mov dword ptr ss:,ebx ; |
00402195 .FF15 94414000 call dword ptr ds:[<&MSVBVM50.__vbaVarAdd>] ; \__vbaVarAdd
0040219B .8BD0 mov edx,eax ;ecx=用户名每个字符ASCII值相加,跟eax没关系啊
0040219D .8D4D CC lea ecx,dword ptr ss:
004021A0 .FFD6 call esi ;msvbvm50.__vbaVarMove
004021A2 .8D4D A8 lea ecx,dword ptr ss:
004021A5 .FF15 B8414000 call dword ptr ds:[<&MSVBVM50.__vbaFreeStr>] ;msvbvm50.__vbaFreeStr
004021AB .8D55 84 lea edx,dword ptr ss:
004021AE .8D45 94 lea eax,dword ptr ss:
004021B1 .52 push edx
004021B2 .50 push eax
004021B3 .53 push ebx
004021B4 .FFD7 call edi ;msvbvm50.__vbaFreeVarList
004021B6 .83C4 0C add esp,0xC
004021B9 .8D8D E8FEFFFF lea ecx,dword ptr ss:
004021BF .8D95 F8FEFFFF lea edx,dword ptr ss:
004021C5 .8D45 DC lea eax,dword ptr ss:
004021C8 .51 push ecx ; /TMPend8 = 0012F49C
004021C9 .52 push edx ; |TMPstep8 = 0012F464
004021CA .50 push eax ; |Counter8 = 00000002
004021CB .FF15 AC414000 call dword ptr ds:[<&MSVBVM50.__vbaVarForNext>]; \__vbaVarForNext
004021D1 .^ E9 5CFFFFFF jmp CM009.00402132 ;循环作用是取用户名每个字符的16进制ASCII值相加,存入ecx中程序运行到循环结束的下一句004021D6处时,ecx=0x120003:再往下,又是如下代码:004021D6 > \8D4D CC lea ecx,dword ptr ss:
004021D9 .8D95 54FFFFFF lea edx,dword ptr ss:
004021DF .51 push ecx ; /var18 = 0012F49C
004021E0 .8D45 94 lea eax,dword ptr ss: ; |
004021E3 .52 push edx ; |var28 = 0012F464
004021E4 .50 push eax ; |SaveTo8 = 00000002
004021E5 .C785 5CFFFFFF>mov dword ptr ss:,0x499602D2 ; |10进制数1234567890入栈ss:
004021EF .C785 54FFFFFF>mov dword ptr ss:,0x3 ; |3进ss:
004021F9 .FF15 5C414000 call dword ptr ds:[<&MSVBVM50.__vbaVarMul>] ; \__vbaVarMul
004021FF .8BD0 mov edx,eax__vbaVarMul函数的作用是两数相乘,但是它的参数是什么还不清楚,花了很长时间,在004021E4和004021FF处分别下断点,在反复在这里计算,查看寄存器内容,还是没弄明白这个函数的参数是谁,只知道是返回到eax中,可是eax中的值也令人摸不清头脑,没有什么用处啊!继续向下,又看到了“__vbaVarMove”、“ __vbaMidStmtVar”之类的函数,太头疼了!多少能猜测一点儿它们的用途,可是找不到具体的东西来。00402206 .8B1D A0414000 mov ebx,dword ptr ds:[<&MSVBVM50.__vbaMidStmtVar>;msvbvm50.__vbaMidStmtVar
0040220C .8D4D CC lea ecx,dword ptr ss:
0040220F .51 push ecx
00402210 .6A 04 push 0x4
00402212 .8D95 54FFFFFF lea edx,dword ptr ss:
00402218 .6A 01 push 0x1
0040221A .52 push edx
0040221B .C785 5CFFFFFF>mov dword ptr ss:,CM009.00401C34 ;-
00402225 .C785 54FFFFFF>mov dword ptr ss:,0x8
0040222F .FFD3 call ebx ;<&MSVBVM50.__vbaMidStmtVar>
00402231 .8D45 CC lea eax,dword ptr ss:
00402234 .8D8D 54FFFFFF lea ecx,dword ptr ss:
0040223A .50 push eax
0040223B .6A 09 push 0x9
0040223D .6A 01 push 0x1
0040223F .51 push ecx
00402240 .C785 5CFFFFFF>mov dword ptr ss:,CM009.00401C34 ;-
0040224A .C785 54FFFFFF>mov dword ptr ss:,0x8
00402254 .FFD3 call ebx
00402256 .8B45 08 mov eax,dword ptr ss:运行到00402231处时,堆栈中出现了可疑的注册码数字!!!!!!
继续单步至00402256处时,堆栈中显示如下图,那么“110-4691-5770”很可能就是注册码了!
把110-4691-5770填入注册码编辑框中,点OK按钮,运行成功了!
再用“海天一色”作为用户名,在OD中追码,出来了一个这样的字符串:UNICODE "-69-4444-811590"!输入编辑框中,注册也成功了!
出现这样的字符是调用了两次msvbvm50.__vbaMidStmtVar函数运行后的结果,猜测这个函数参数可能是__vbaMidStmtVar(字符串,开始替换的位置,要替换的长度,要替换的字符),最终把一串数字中的第4位和第9位用“-”代替,形成了一个新的字符串。虽然注册码找出来了,可是怎么算出来的呢?一头雾水!
下面的代码基本上应该对注册码算法没什么作用了,到00402292处取假码进行处理,一直到004022AE处用MSVBVM50.__vbaVarTstEq函数对真假码比较,
004022AE .FF15 48414000 call dword ptr ds:[<&MSVBVM50.__vbaVarTs>; \__vbaVarTstEq
004022B4 .8D4D A4 lea ecx,dword ptr ss:
004022B7 .8BD8 mov ebx,eax
004022B9 .FF15 B4414000 call dword ptr ds:[<&MSVBVM50.__vbaFreeO>;msvbvm50.__vbaFreeObj
004022BF .8D4D 94 lea ecx,dword ptr ss:
004022C2 .FF15 00414000 call dword ptr ds:[<&MSVBVM50.__vbaFreeV>;msvbvm50.__vbaFreeVar
004022C8 .66:85DB test bx,bx
004022CB 0F84 C0000000 je CM009.00402391 ;关键跳
从网上找到此函数比较两个数,如两数相同eax=1;否则eax=0。因为输入的错码,eax当然是0;后面eax赋值给了ebx,所以到关键跳前的test bx,bx一句时,下一句就跳过成功了。想从OD中直接找到算法看样子很困难!所以再利用VB反编译利器VB Decompiler出场!
Text2_Change()的代码只有一个功能,输入字符,OK按钮可用!双击左侧窗口中Command1_Click_401FF0,在右侧反编译器窗口中出现了如下代码:
Private Sub Command1_Click() '401FF0
loc_00402092: var_58 = Text2.Text
loc_004020CA: var_44 = var_58
loc_00402126: For var_24 = 1 To Len(var_44) Step 1
loc_00402132:
loc_00402134: If var_108 = 0 Then GoTo loc_004021D6
loc_00402169: var_58 = CStr(Mid(var_44, CLng(var_24), 1))
loc_00402176: var_B4 = Asc(var_58)
loc_004021A0: var_34 = var_34 + Asc(var_58)
loc_004021CB: Next var_24
loc_004021D1: GoTo loc_00402132
loc_004021D6: 'Referenced from: 00402134
loc_00402204: var_34 = var_34 * 1234567890
loc_00402276: var_58 = Text1.Text
loc_00402298: var_64 = var_58
loc_004022CB: If (var_58 = var_34) = 0 Then GoTo loc_00402391
loc_004022D1: Beep
loc_00402308: var_B4 = "成功"
loc_00402327: var_A4 = "成功了,请继续下去!"
loc_00402374: var_54 = MsgBox("成功了,请继续下去!", 48, "成功", 10, 10)
loc_0040238C: GoTo loc_00402446
loc_00402391: 'Referenced from: 004022CB
loc_004023C2: var_B4 = "失败"
loc_004023E1: var_A4 = "不幸的错误!"
loc_0040242E: var_54 = MsgBox("不幸的错误!", 16, "失败", 10, 10)
loc_00402446: 'Referenced from: 0040238C
loc_00402459: GoTo loc_0040248F
loc_0040248E: Exit Sub
loc_0040248F: 'Referenced from: 00402459
loc_004024C0: GoTo loc_00esi
End Sub
这些代码很容易就看出来是精简过的代码,只抽取出了注册码的数学计算,将用户名每个字符的16进制ASCII值相加后的结果再乘以 1234567890得到的一个结果,所以用户名“52pojie.cn”算出的注册码是(893*1234567890=)1102469125770;此时对照OD中的注册码,整个注册算法出来了,是用户名每个字符的16进制ASCII值相加后的结果再乘以 1234567890得到的一个结果转成字符串形式,再将第4个、第9个字符替换成“-”即可。
注册机编写时基本上将VBDecompiler反编译的代码修改一下,再加上字符替换就行了。
附件含原程序、汉化程序CM009、爆破程序CM009_nop及009的注册机。
百度链接是:http://pan.baidu.com/s/1skMkJY9密码: 86pm,160个CM、个人学习过的前9个crackme程序都在里面。 楼主,对于009这个CM,我这周也做了一下,我觉得你的分析没有分析到这个CM的实质。这个CM是用VB写的,也不知道是VB的特性,还是这个CM的特性,数字在寄存器中的存储都很奇怪,好像是扩展了一下的样子。所以用OD去调试的时候,只看寄存器的值是看不出任何端倪的,需要把寄存器保存的值按照数据地址的方式查看,才能有一些眉目。在这个吾爱破解论坛,有人贴出来一个009的分析,我觉得那个分析还是写的挺到位的,你可以参考一下。帖子地址:http://www.52pojie.cn/forum.php?mod=viewthread&tid=265789
另外,用VB反编译出来的东西,把后面处理字符串的部分给丢掉了。这个我也很奇怪。考虑到VB的特性,操作数在EAX中,我甚至怀疑这个CM是用VB写好以后,又用二进制编辑工具把一些MOV LEA以及CALL交换位置而形成的,这样就导致VB反编译工具无法识别正确的代码了。
反正,对于VB的程序,我觉得实在是难以理解,今后我还是远离它们吧。 另外,我再说一下楼主有一个非常不好的习惯,就是在破解前先把软件汉化。比如软件运行时判断自身是否被修改,或者某个英文提示作为注册码生成的密钥等等,汉化都会把这些破坏掉。所以我建议破解前不要做汉化操作。 我也认同肥牛兄的说法,这些CM本来就是用来练手破解的,汉化实在是没有必要的操作。如果LZ想练手汉化,不如找些其他的软件来练练。CM当中的字符串本来就只有那两个。 肥牛 发表于 2017-6-9 14:36
楼主,对于009这个CM,我这周也做了一下,我觉得你的分析没有分析到这个CM的实质。这个CM是用VB写的,也不 ...
感谢肥牛的指导!我的本意是既练习了些破解知识,又顺便练习了汉化,目的是加深对程序和编程语言的理解,确实没有想到软件的自校验及其他方面!以后会注意这些问题的!
另外:http://www.52pojie.cn/forum.php?mod=viewthread&tid=265789这个帖子我也学习了,但对怎样把寄存器保存的值按照数据地址的方式查看还是一头雾水!手头有几本VB编程的书,但没有一本讲到VB对数据在寄存器中是如何处理的!VB编程是我接触的第一个编程语言,没想到这么令人难受!
不过作为CM练习,我还是要继续练下去,再次感谢!
在此也感谢海盗小K! 大神,我有个不联网的小程序,换硬盘后就需要重新注册,能帮我看看么,500k的程序。 18633304400 发表于 2017-6-9 19:52
大神,我有个不联网的小程序,换硬盘后就需要重新注册,能帮我看看么,500k的程序。
首先说明我不是大神!!!
只是刚学习逆向的新手!!!
你的这个程序从各种渠道了解到应该是利用硬盘的机器码来判断的,但怎么破我还真的不会!目前只在用户名/注册码这一块进行学习呢! 好复杂,一下子很难看的懂。但还是要顶 感谢分享!
页:
[1]