本帖最后由 海天一色001 于 2017-8-19 23:19 编辑
第16个CM程序,仍然是VB编程。先点击“About”菜单,弹出信息框,大意是“这个CM程序制作出来是为了提高新手们在VB方面的R.C.E知识的!(R.C.E是什么意思?)希望你们能从中学习到一些知识!”没有可以利用的地方;
在注册码文本框中随意输入字符,点击“Check it”按钮,程序弹出错误对话框:
先查壳,程序用VB编写,未加壳:
第一步,爆破程序:将程序载入OD中,智能搜索字符串,可以看出下面四个地址处分别是错误信息框及正确信息信息框的标题字符串和内容字符串。
双击00403ACE地址,进入CPU窗口:
向上滚动,来到地址00403AA4处,这是一个跳转命令的目的地址,明显跳过了失败提示:
此处信息栏中显示“跳转来自00403787”:
要让00403787地址处的这条跳转命令生效,在信息窗口中“跳转来自00403787”一行上右键点击,选“转到jg来自00403787”来到地址00403787处:
这里的上一行是比较命令,如果堆栈中的值大于/不小于等于cx寄存器中的值时才跳转,那么将此处改为无条件跳转命令jmp试一试:
F9运行程序,随意输入字符,还是弹出错误信息框!说明在执行00403787地址处的命令之前有跳转命令跳过了00403787地址,使正确跳转未实现,来到了错误信息框的地方。
所以在地址00403AA4处上方继续查看代码:
大致上从地址00403A22处至00403AA2处为弹出错误信息框的代码段,00403A22处的跳转来自004038AD, 00403A04地址处,而这两处地址均在00403787地址后,所以不会执行;而00403A24处的跳转来自00403704地址,则在00403787地址之前了!所以要将00403704地址处的跳转命令nop掉!
如上图所示进行操作,来到地址00403704处,将“jnz BJCM20A.00403A24”指令改成“nop”指令:
F9运行程序,此时不管是不输入还是随意输入字符,均弹出正确信息框,爆破成功!将所有修改另存为BJCM20A_nop.EXE,运行BJCM20A_nop.EXE,验证几次,均弹出正确信息框。 第二步,追码:其实这个CM与第14个CM的算法是一样的,所以我在追码过程中感到很熟悉,可能写的时候就不如第14个CM那么详细,大家可以直接看我那一篇《160个CrakeMe程序之014》就行。但是这一次要有所进步,所以自己没有象第14个程序那样去一个数字一个数字的试,而是按照作者的思路去找规律,最终找到了注册算法。重新将CM程序载入OD中,因为在爆破的过程中知道了00403787地址处的指令为关键跳,所以直接Ctrl+G跳转到00403787处:
向上查看代码,找到本段代码段首处00403620下断,F9运行程序,随意输入字符,点击“Check it”按钮,程序中断。
F8单步运行,注意查看寄存器、信息栏、堆栈窗口的信息:
【004036DC地址至00403704地址处代码作用是检测注册码长度,如果长度不为9,则跳至失败:】
[Asm] 纯文本查看 复制代码 004036DC . 50 push eax ; /假码“23445645636346346”
004036DD . FF15 08104000 call dword ptr ds:[<&MSVBVM60.__vbaLenBstr>] ; \假码长度“0X11”
004036E3 . 33C9 xor ecx,ecx ; ecx清零
004036E5 . 83F8 09 cmp eax,0x9 ; 假码长度与9比较,不等则ZF=0,等则ZF=1
004036E8 . 0f95c1 setne cl ; if ZF=1 then cl=0;if ZF=0 then cl=1
004036EB . F7D9 neg ecx ; 求补
004036ED . 8BF1 mov esi,ecx ; esi=ecx
004036EF . 8D4D E4 lea ecx,dword ptr ss:[ebp-0x1C]
004036F2 . FF15 C0104000 call dword ptr ds:[<&MSVBVM60.__vbaFreeStr>] ; msvbvm60.__vbaFreeStr
004036F8 . 8D4D D4 lea ecx,dword ptr ss:[ebp-0x2C]
004036FB . FF15 C4104000 call dword ptr ds:[<&MSVBVM60.__vbaFreeObj>] ; msvbvm60.__vbaFreeObj
00403701 . 66:3BF3 cmp si,bx ; 比较si/bx寄存器中的值
00403704 0F85 1A030000 jnz BJCM20A.00403A24 ; 不等则跳至失败
单步至00403704地址,因为长度不为9,所以此时要跳至失败;
为了追码,双击寄存器窗口中的“Z”标志,使其变成1,此时程序不再跳,继续单步向下进行:运行到00403748处开始又一次检测注册码长度,至00403760处给堆栈ss:[ebp-0x18] 赋值0x1;
[Asm] 纯文本查看 复制代码 00403748 . 50 push eax ; /String = "23445645636346346"
00403749 . FF15 08104000 call dword ptr ds:[<&MSVBVM60.__vbaLenBstr>] ; \__vbaLenBstr=0X11
【再继续向下至0040377C地址处开始至00403A1D处为检测计算注册码的代码,其中代码段中进行了删节:】
[Asm] 纯文本查看 复制代码 0040377C > 66:8B8D 14FFF>mov cx,word ptr ss:[ebp-0xEC] ; 将ss:[ebp-0xEC]的值传递给cx
00403783 . 66:394D E8 cmp word ptr ss:[ebp-0x18],cx ; ss:[ebp-0x18]和ss:[ebp-0xEC]的值进行比较
00403787 0F8F 17030000 jg BJCM20A.00403AA4 ; 关键跳,循环完成才能跳至正确信息框
【00403826至004038 AD地址处,是取假码的第一个字符与数字“9”、“0”的比较,也就是要检测注册码是不是数字,不是则失败。】
[Asm] 纯文本查看 复制代码 00403826 . FF15 44104000 call dword ptr ds:[<&MSVBVM60.#rtcMidCharBstr_631>] ; 取假码的第一个字符存入eax中,此时为Unicode值“9”
。。。。。。。。。。。
00403833 . 50 push eax
00403834 . FF15 1C104000 call dword ptr ds:[<&MSVBVM60.#rtcAnsiValueBstr_516>] ; \转换成ANSI值,存入EAX中
0040383A . 8B4D E4 mov ecx,dword ptr ss:[ebp-0x1C]
0040383D . 33DB xor ebx,ebx
0040383F . 66:3D 3900 cmp ax,0x39 ; 与0X39比较
00403843 . 8D45 C0 lea eax,dword ptr ss:[ebp-0x40]
00403846 . 50 push eax
00403847 . 57 push edi
00403848 . 0f9fc3 setg bl
0040384B . 51 push ecx
0040384C . F7DB neg ebx
0040384E . FF15 44104000 call dword ptr ds:[<&MSVBVM60.#rtcMidCharBstr_631>] ; msvbvm60.rtcMidCharBstr
00403854 . 8BD0 mov edx,eax
00403856 . 8D4D E0 lea ecx,dword ptr ss:[ebp-0x20]
00403859 . FFD6 call esi ; msvbvm60.__vbaStrMove
0040385B . 50 push eax
0040385C . FF15 1C104000 call dword ptr ds:[<&MSVBVM60.#rtcAnsiValueBstr_516>] ; \rtcAnsiValueBstr
00403862 . 33D2 xor edx,edx
00403864 . 66:3D 3000 cmp ax,0x30 ; 与0X30比较
00403868 . 0f9cc2 setl dl
0040386B . F7DA neg edx
。。。。。。。。。。。。。。。。。。
004038AA . 66:85DB test bx,bx
004038AD . 0F85 6F010000 jnz BJCM20A.00403A22 ; 跳至错误
。。。。。。。。。。。。。。。。。。
004038F1 > \66:8B45 E8 mov ax,word ptr ss:[ebp-0x18] ; AX=循环次数,
004038F5 . 8B1D 74104000 mov ebx,dword ptr ds:[<&MSVBVM60.#rtcStrFromVar_536>] ; msvbvm60.rtcStrFromVar
004038FB . 66:35 0200 xor ax,0x2 ; ax=ax xor 0x2
00403909 . 66:8945 A8 mov word ptr ss:[ebp-0x58],ax ; ss:[ebp-0x58]=ax
0040390D . C745 A0 02000>mov dword ptr ss:[ebp-0x60],0x2
00403914 . FFD3 call ebx ;eax=ss:[ebp-0x58]]转换成的字符串
00403916 . 8BD0 mov edx,eax ; edx=eax=0016001C, (UNICODE " 3")
00403918 . 8D4D D8 lea ecx,dword ptr ss:[ebp-0x28]
0040391B . FFD6 call esi ; msvbvm60.__vbaStrMove
0040391D . 8B45 E4 mov eax,dword ptr ss:[ebp-0x1C] ; eax=假码
。。。。。。。。。。。。。。。
00403934 . FF15 44104000 call dword ptr ds:[<&MSVBVM60.#rtcMidCharBstr_631>] ; eax的值为假码中取出的字符Unicode"9"
。。。。。。。。。。。。。。。
【00403941地址开始对取的假码每一位进行运算,到0040397D地址,对假码运算的结果存入了ss:[ebp-0xc8]:】
[Asm] 纯文本查看 复制代码 00403941 . 50 push eax
00403942 . FF15 1C104000 call dword ptr ds:[<&MSVBVM60.#rtcAnsiValueBstr_516>] ; eax=第N个假码中的字符ANSI的16进制值
。。。。。。。。。。。。。。。
00403957 . FFD3 call ebx ; eax=中的字符ANSI的16进制值转换成10进制的字符值,
00403959 . 8BD0 mov edx,eax
0040395B . 8D4D DC lea ecx,dword ptr ss:[ebp-0x24]
0040395E . FFD6 call esi ; msvbvm60.__vbaStrMove
00403960 . 50 push eax
00403961 . FF15 84104000 call dword ptr ds:[<&MSVBVM60.__vbaR8Str>] ; 把10进制的字符值转成浮点数放入ST0
00403967 . DC25 D8104000 fsub qword ptr ds:[0x4010D8] ; 此时st0=st0-48
。。。。。。。。。。。。。。。
0040397D . DD9D 38FFFFFF fstp qword ptr ss:[ebp-0xC8] ; ss:[ebp-0xc8]=st0
【从0040398D处开始一直到004039A5地址是对真码的运算:】
[Asm] 纯文本查看 复制代码 0040398D . 8B45 D8 mov eax,dword ptr ss:[ebp-0x28] ; eax= ss:[ebp-0x28] (空格+一个0至9之间的数字形式)
。。。。。。。。。。。。。。
004039A5 . FF15 B0104000 call dword ptr ds:[<&MSVBVM60.#rtcRightCharVar_619>] ; 取字串的最右侧字符,返回值存入堆栈ss:[eax+8]中
。。。。。。。。。。。。。。
004039B6 . FF15 A0104000 call dword ptr ds:[<&MSVBVM60.__vbaVarTstNe>] ; 真假码比较,相等,eax=0,不等,eax=-1
004039BC . 8BF8 mov edi,eax ; edi=eax
。。。。。。。。。。。。。。。。。
00403A01 . 66:85FF test di,di ; DI=0 ?
00403A04 . 75 1C jnz short BJCM20A.00403A22 ; 不等跳向失败
00403A06 . 8B7D 08 mov edi,dword ptr ss:[ebp+0x8]
00403A09 . B8 01000000 mov eax,0x1
00403A0E . 66:0345 E8 add ax,word ptr ss:[ebp-0x18] ; ax=ax+ss:[ebp-0x18]
00403A12 . 0F80 94010000 jo BJCM20A.00403BAC ; 溢出错误则跳
00403A18 . 8945 E8 mov dword ptr ss:[ebp-0x18],eax ; ss:[ebp-0x18]=eax
00403A1B . 33DB xor ebx,ebx ; msvbvm60.rtcStrFromVar
00403A1D .^ E9 5AFDFFFF jmp BJCM20A.0040377C ; 循环
总结一下,注册算法是1到9依次与2异或后的结果取右侧的一个字符,注册机可以直接使用第14个CM的注册机。
[Visual Basic] 纯文本查看 复制代码 Private Sub Command1_Click()
For i = 1 To 9
a= i Xor 2
a= Right(a, 1)
code = code & a
Text1.Text = code
End Sub
VB中从堆栈中存取数据,还是不知道该从哪里入手!在练习过程中,肯定还有不到位及分析错误的地方,欢迎各位坛友讨论指导!
附件
016.rar
(14.24 KB, 下载次数: 10)
,含CM原程序、爆破后的程序及016注册机。百度链接是:http://pan.baidu.com/s/1skMkJY9密码: 86pm,160个CM、我已练习过的前16个crackme程序(不含012)都在里面。 |