第30个CM程序,这个程序有好几个窗体,先在File菜单上选择“password”命令进入主窗体,输入“1234567890”,点击“OK”按钮,弹出错误提示框,在About菜单上点击弹出关于信息,没什么用处:
第一步、查壳:
无壳,这个程序是VB5.0编程:
第二步、爆破
用OD载入cracking4all.1.exe,智能搜索字符串:
在004033A5这一行双击进入CPU窗口:
向上查看至00403370处,指令是“je cracking.0040345E”,跳过了成功提示,来到失败提示处,所以将这里nop掉试一下:
修改后的文件保存为cracking4all.1.nop.exe,运行,在password窗口中输入任何字符或者不输入字符,点击“OK”按钮时,均弹出成功提示框,说明破解成功:
第三步、追码:
将00403370处的nop指令撤消修改,观察代码:
向上查看至0040334E处,指令要调用MSVBVM50.__vbaVarTstEq函数,这就是关键比较了,[eax]=[ecx]则失败,不等则成功;
继续向上看,__vbaVarTstEq函数的两个要比较的参数分别是[eax]= ss:[ebp-0x38],[ecx]= ss:[ebp-0xC8],实际参数地址应该是ss:[ebp-0x38+0x8]【ebp-0x30】与ss:[ebp-0xC8+0x8]【ebp-0xC0】,从堆栈窗口中看到,ss:[ebp-0xC0]= “qBQSYdXUe_B\V”,也就是说输入的password经计算后等于“qBQSYdXUe_B\V”才行:
再向上查看,有点吃力了,还是用SmatrCheck/VB Decompiler这两个VB的专用反编译工具及监控工具SoftSnoop来配合OD使用吧:
先将VB Decompiler的解析导入OD中(VB Decompiler直接生成的map文件导入OD中没发现注释有什么改变,可能有什么地方不对;要先用VB Decompiler生成bas文件,再利用bas转map工具转换成map文件后导入OD才行),从SmatrCheck/VB Decompiler/SoftSnoop这三个工具中均可以看到“OK”按钮事件开始于004030F0处:OD中在此地址下断,然后F9运行程序,在File菜单上选择“password”命令进入主窗体,输入“1234567890”,点击“OK”按钮,程序中断于004030F0处:
F8向下,一直到004031A8处,得到password字符串存入[eax]中;
从004031D3至004031DA处,得到假码的长度,并存入ss:[ebp-0x108]中,作为下一步循环的次数:
[Asm] 纯文本查看 复制代码
004031D3 . 51 push ecx ; /var18 =0012F4B8 004031D4 . 52 push edx ; |retBuffer8 =0012F488 004031D5 . BE 01000000 mov esi,0x1 ; | 004031DA > . FF15 18614000 call dword ptr ds:[<&MSVBVM50.__vbaLenVar>] ; \var_58=Len(var_28)=Len(password.text) 004031E0 . 50 push eax ; [eax+8]=len(password.text) 004031E1 . FF15 74614000 call dword ptr ds:[<&MSVBVM50.__vbaI2Var>] ; msvbvm50.__vbaI2Var 004031E7 > . 8985 F8FEFFFF mov dword ptr ss:[ebp-0x108],eax ; var_108=CInt(Me) 004031ED . 8BFE mov edi,esi
从004031EF到0040332A是一个大循环。循环次数是假码的长度值:[其中004031FC、00403206、00403312、00403319等处由导入的注释有点小问题,不知道该怎么说好,前面两个是将标志位ZF用00000001h来表示了,后面两个地址处是将di、si用00000001h来表示,感觉不太合适,需要自己根据情况修改调整一下。]
[Asm] 纯文本查看 复制代码
004031EF > 66:3BBD F8FEFFFF cmp di,word ptr ss:[ebp-0x108] ; di与10比较:从1到len(password.text)循环 004031F6 . 8B1D 6C614000 mov ebx,dword ptr ds:[<&MSVBVM50.__vbaStrVarVal>] ; msvbvm50.__vbaStrVarVal 004031FC > . 0F8F 2D010000 jg <cracking.End`If> ; If`00000001h<=0`Then////if di-10<=0时转移 00403202 . 66:83FE 04 cmp si,0x4 00403206 > . 7E 05 jle short <cracking.End`If> ; If`00000001h`>`4`Then////if si-4>0时转移 00403208 . BE 01000000 mov esi,0x1 0040320D > > 0FBFCF movsx ecx,di ; End`If 。。。。。。。。。 00403309 > . FF15 00614000 call dword ptr ds:[<&MSVBVM50.__vbaFreeVarList>] ; call`undef`'Ignore`this`'__vbaFreeVarList(00000006,`2,`var_68,`2,`2,`var_98,`var_A8) 0040330F . 83C4 1C add esp,0x1C 00403312 > . 66:46 inc si ; si=00000001h`+`1///si自加1 si=si+1 00403314 . B8 01000000 mov eax,0x1 00403319 > . 66:03C7 add ax,di ; 00000001h=00000001h`+`di///ax=ax+di 0040331C > . 0F80 44020000 jo cracking.00403566 ; If`Err.Number<>0`Then 00403322 > . 0F80 3E020000 jo cracking.00403566 ;If`Err.Number<>0`Then`GoTo`loc_00403566 00403328 . 8BF8 mov edi,eax 0040332A > .^ E9 C0FEFFFF jmp cracking.004031EF ; GoTo`loc_004031EF
到0040322B处,依次取假码的每一个字符,存入var_68即SS:[ebp-0x68]中;
[Asm] 纯文本查看 复制代码
00403210 . 8D45 A8 lea eax,dword ptr ss:[ebp-0x58] 00403213 . 8D55 D8 lea edx,dword ptr ss:[ebp-0x28] 00403216 . 50 push eax ; /Length8 = 0x0 00403217 . 51 push ecx ; |Start = 0x12F4B8 00403218 . 8D45 98 lea eax,dword ptr ss:[ebp-0x68] ; | 0040321B . 52 push edx ; |dString8 = 0012F488 0040321C . 50 push eax ; |RetBUFFER = NULL 0040321D . C745 B0 01000000 mov dword ptr ss:[ebp-0x50],0x1 ; | 00403224 . C745 A8 02000000 mov dword ptr ss:[ebp-0x58],0x2 ; | 0040322B > . FF15 38614000 call dword ptr ds:[<&MSVBVM50.#rtcMidCharVar_632>] ; \var_68=Mid(var_28,`di,`1) /取假码的每一个字符
继续到0040325C处,将2000(0x7D0)存入ss:[ebp-0x70]中,在00403263处循环取“2000”的每一个字符,存入var_98即SS:[ebp-0x98]中;
[Asm] 纯文本查看 复制代码
00403231 . B8 02000000 mov eax,0x2 00403236 . 8D8D 78FFFFFF lea ecx,dword ptr ss:[ebp-0x88] 0040323C . 0FBFD6 movsx edx,si 0040323F . 8985 78FFFFFF mov dword ptr ss:[ebp-0x88],eax 00403245 . 8945 88 mov dword ptr ss:[ebp-0x78],eax 00403248 . 51 push ecx ; /Length8 =0x12F4B8 00403249 . 8D45 88 lea eax,dword ptr ss:[ebp-0x78] ; | 0040324C . 52 push edx ; |Start = 0x12F488 0040324D . 8D8D 68FFFFFF lea ecx,dword ptr ss:[ebp-0x98] ; | 00403253 . 50 push eax ; |dString8 =NULL 00403254 . 51 push ecx ; |RetBUFFER = 0012F4B8 00403255 . C745 80 01000000 mov dword ptr ss:[ebp-0x80],0x1 ; | 0040325C . C745 90 D0070000 mov dword ptr ss:[ebp-0x70],0x7D0 ; |0x7D0的10进制数值为2000 00403263 > . FF15 38614000 call dword ptr ds:[<&MSVBVM50.#rtcMidCharVar_632>] ; \var_98=Mid(2000,`si,`1) ///循环取“2000”的每一个字符
00403269处到00403288处将取得的假码字符转换成16进制数值,转存到ss:[ebp-0x118]中;
[Asm] 纯文本查看 复制代码
00403269 . 8D55 98 lea edx,dword ptr ss:[ebp-0x68] 0040326C . 8D45 C0 lea eax,dword ptr ss:[ebp-0x40] 0040326F . 52 push edx 00403270 . 50 push eax 00403271 > . FFD3 call ebx ; var_40=CStr(var_68) 00403273 . 50 push eax ; /String = NULL 00403274 . FF15 0C614000 call dword ptr ds:[<&MSVBVM50.#rtcAnsiValueBstr_516>] ; \rtcAnsiValueBstr 0040327A . 0FBFD0 movsx edx,ax 0040327D . 8D8D 68FFFFFF lea ecx,dword ptr ss:[ebp-0x98] 00403283 . 8D45 BC lea eax,dword ptr ss:[ebp-0x44] 00403286 . 51 push ecx 00403287 . 50 push eax 00403288 . 8995 E8FEFFFF mov dword ptr ss:[ebp-0x118],edx
0040328E处到00403291处,将每一位假码字符对应的“2000”的字符转换成16进制数值,存入[ax]中;
[Asm] 纯文本查看 复制代码
0040328E > . FFD3 call ebx ; var_44=CStr(var_98) 00403290 . 50 push eax ; /String = NULL 00403291 . FF15 0C614000 call dword ptr ds:[<&MSVBVM50.#rtcAnsiValueBstr_516>] ; \rtcAnsiValueBstr
00403297到004032AA处,假码与对应的“2000”的每一位字符的16进制数值进行异或运算,存入[edx],并从ASCII码转为字符,存入var_A8即SS:[ebp-0x118]中;
[Asm] 纯文本查看 复制代码
00403297 . 8B95 E8FEFFFF mov edx,dword ptr ss:[ebp-0x118] 0040329D . 0FBFC8 movsx ecx,ax 004032A0 . 33D1 xor edx,ecx ; 异或运算: 004032A2 . 8D85 58FFFFFF lea eax,dword ptr ss:[ebp-0xA8] 004032A8 . 52 push edx 004032A9 . 50 push eax 004032AA > . FF15 64614000 call dword ptr ds:[<&MSVBVM50.#rtcVarBstrFromAnsi_608>; var_A8=Chr(Asc(var_40)`xor`ecx) 【rtcVarBstrFromAnsi:ASCII码转为字符】
004032B0到004032 CD处,将异或运算后转换成的字符先连接起来,存入var_B8中,再复制回var_38中:
[Asm] 纯文本查看 复制代码
004032B0 . 8D4D C8 lea ecx,dword ptr ss:[ebp-0x38] 004032B3 . 8D95 58FFFFFF lea edx,dword ptr ss:[ebp-0xA8] 004032B9 . 51 push ecx 004032BA . 8D85 48FFFFFF lea eax,dword ptr ss:[ebp-0xB8] 004032C0 . 52 push edx 004032C1 . 50 push eax 004032C2 > . FF15 70614000 call dword ptr ds:[<&MSVBVM50.__vbaVarCat>] ; var_B8=var_38`&`var_A8 004032C8 . 8BD0 mov edx,eax 004032CA . 8D4D C8 lea ecx,dword ptr ss:[ebp-0x38] 004032CD > . FF15 F8604000 call dword ptr ds:[<&MSVBVM50.__vbaVarMove>] ; var_38=var_B8
0040332F到0040334E处,将var_38中的字符与“qBQSYdXUe_B\V”进行比较,相同则成功,不同则失败。
[Asm] 纯文本查看 复制代码
0040332F <> > \8D45 C8 lea eax,dword ptr ss:[ebp-0x38] ; End`If 00403332 . 8D8D 38FFFFFF lea ecx,dword ptr ss:[ebp-0xC8] 00403338 . 50 push eax ; /var18 =0012F428 00403339 . 51 push ecx ; |var28 = 0012F4A8 0040333A . C785 40FFFFFF C827>mov dword ptr ss:[ebp-0xC0],cracking.004027C8 ; |qBQSYdXUe_B\V 00403344 . C785 38FFFFFF 0880>mov dword ptr ss:[ebp-0xC8],0x8008 ; | 0040334E . FF15 44614000 call dword ptr ds:[<&MSVBVM50.__vbaVarTstEq>] ; \关键比较:关系运算,if [eax]=[ecx],ax=-1;else ax=0
由异或运算的性质可反推出注册算法,即取“qBQSYdXUe_B\V”与“2000200020002”的每一对应字符的ASCII值进行异或运算,所得结果连接起来即是注册码了:用VB编写的主要代码段如下:
[Visual Basic] 纯文本查看 复制代码
key = "qBQSYdXUe_B\V" source = "2000200020002" For i = 1 To 13 p(i) = Asc(Mid(key, i, 1)) Xor Asc(Mid(source, i, 1)) password = password & Chr(p(i)) Next Text1.Text = Trim(password)
计算出的密码是“CrackTheWorld”,验证了一下,是正确的。
附件
030.zip
(134.26 KB, 下载次数: 0)
2019-7-14 08:06 上传
点击文件名下载附件
下载积分: 吾爱币 -1 CB
,含CM原程序、爆破后的程序、注册机、OD的调试文件等。百度链接是:http://pan.baidu.com/s/1skMkJY9,密码: 86pm,160个CM、我已练习过的前30个crackme程序(不含012)都在里面。