160个Crackme之030学习笔记
本帖最后由 海天一色001 于 2019-7-14 16:34 编辑第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函数,这就是关键比较了,=则失败,不等则成功;
继续向上看,__vbaVarTstEq函数的两个要比较的参数分别是= ss:,= ss:,实际参数地址应该是ss:【ebp-0x30】与ss:【ebp-0xC0】,从堆栈窗口中看到,ss:= “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字符串存入中;
从004031D3至004031DA处,得到假码的长度,并存入ss:中,作为下一步循环的次数:
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 ;=len(password.text)
004031E1 .FF15 74614000 call dword ptr ds:[<&MSVBVM50.__vbaI2Var>] ; msvbvm50.__vbaI2Var
004031E7 > .8985 F8FEFFFF mov dword ptr ss:,eax ;var_108=CInt(Me)
004031ED .8BFE mov edi,esi
从004031EF到0040332A是一个大循环。循环次数是假码的长度值:[其中004031FC、00403206、00403312、00403319等处由导入的注释有点小问题,不知道该怎么说好,前面两个是将标志位ZF用00000001h来表示了,后面两个地址处是将di、si用00000001h来表示,感觉不太合适,需要自己根据情况修改调整一下。]
004031EF >66:3BBD F8FEFFFF cmp di,word ptr ss: ;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:中;
00403210 .8D45 A8 lea eax,dword ptr ss:
00403213 .8D55 D8 lea edx,dword ptr ss:
00403216 .50 push eax ; /Length8 = 0x0
00403217 .51 push ecx ; |Start = 0x12F4B8
00403218 .8D45 98 lea eax,dword ptr ss: ; |
0040321B .52 push edx ; |dString8 = 0012F488
0040321C .50 push eax ; |RetBUFFER = NULL
0040321D .C745 B0 01000000 mov dword ptr ss:,0x1 ; |
00403224 .C745 A8 02000000 mov dword ptr ss:,0x2 ; |
0040322B > .FF15 38614000 call dword ptr ds:[<&MSVBVM50.#rtcMidCharVar_632>] ; \var_68=Mid(var_28,`di,`1) /取假码的每一个字符
继续到0040325C处,将2000(0x7D0)存入ss:中,在00403263处循环取“2000”的每一个字符,存入var_98即SS:中;
00403231 .B8 02000000 mov eax,0x2
00403236 .8D8D 78FFFFFF lea ecx,dword ptr ss:
0040323C .0FBFD6 movsx edx,si
0040323F .8985 78FFFFFF mov dword ptr ss:,eax
00403245 .8945 88 mov dword ptr ss:,eax
00403248 .51 push ecx ; /Length8 =0x12F4B8
00403249 .8D45 88 lea eax,dword ptr ss: ; |
0040324C .52 push edx ; |Start = 0x12F488
0040324D .8D8D 68FFFFFF lea ecx,dword ptr ss: ; |
00403253 .50 push eax ; |dString8 =NULL
00403254 .51 push ecx ; |RetBUFFER = 0012F4B8
00403255 .C745 80 01000000 mov dword ptr ss:,0x1 ; |
0040325C .C745 90 D0070000 mov dword ptr ss:,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:中;
00403269 .8D55 98 lea edx,dword ptr ss:
0040326C .8D45 C0 lea eax,dword ptr ss:
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:
00403283 .8D45 BC lea eax,dword ptr ss:
00403286 .51 push ecx
00403287 .50 push eax
00403288 .8995 E8FEFFFF mov dword ptr ss:,edx
0040328E处到00403291处,将每一位假码字符对应的“2000”的字符转换成16进制数值,存入中;
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进制数值进行异或运算,存入,并从ASCII码转为字符,存入var_A8即SS:中;
00403297 .8B95 E8FEFFFF mov edx,dword ptr ss:
0040329D .0FBFC8 movsx ecx,ax
004032A0 .33D1 xor edx,ecx ;异或运算:
004032A2 .8D85 58FFFFFF lea eax,dword ptr ss:
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中:
004032B0 .8D4D C8 lea ecx,dword ptr ss:
004032B3 .8D95 58FFFFFF lea edx,dword ptr ss:
004032B9 .51 push ecx
004032BA .8D85 48FFFFFF lea eax,dword ptr ss:
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:
004032CD > .FF15 F8604000 call dword ptr ds:[<&MSVBVM50.__vbaVarMove>] ;var_38=var_B8
0040332F到0040334E处,将var_38中的字符与“qBQSYdXUe_B\V”进行比较,相同则成功,不同则失败。
0040332F <> > \8D45 C8 lea eax,dword ptr ss: ;End`If
00403332 .8D8D 38FFFFFF lea ecx,dword ptr ss:
00403338 .50 push eax ; /var18 =0012F428
00403339 .51 push ecx ; |var28 = 0012F4A8
0040333A .C785 40FFFFFF C827>mov dword ptr ss:,cracking.004027C8 ; |qBQSYdXUe_B\V
00403344 .C785 38FFFFFF 0880>mov dword ptr ss:,0x8008 ; |
0040334E .FF15 44614000 call dword ptr ds:[<&MSVBVM50.__vbaVarTstEq>] ; \关键比较:关系运算,if =,ax=-1;else ax=0
由异或运算的性质可反推出注册算法,即取“qBQSYdXUe_B\V”与“2000200020002”的每一对应字符的ASCII值进行异或运算,所得结果连接起来即是注册码了:用VB编写的主要代码段如下:
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”,验证了一下,是正确的。
附件,含CM原程序、爆破后的程序、注册机、OD的调试文件等。百度链接是:http://pan.baidu.com/s/1skMkJY9,密码: 86pm,160个CM、我已练习过的前30个crackme程序(不含012)都在里面。
论坛有你更精彩! 哇支持大佬! 好强大.... 学习下! 楼主幸苦了 谢谢分享~!! 我的头本来就不小,看到你发的这一串数字。。。更大了 感谢分享纯支持 辛苦 感谢分享,支持一下
页:
[1]