- UID
- 65036
注册时间2010-1-1
阅读权限10
最后登录1970-1-1
周游历练
该用户从未签到
|
【文章标题】: 破解 VB CrackMe 全实录
【文章作者】: xiaojiam
【软件名称】: CM123.exe
【软件大小】: 24 KB
【下载地址】: 见以下附件
【保护方式】: 时钟检测+注册码
【编写语言】: VB
【使用工具】: PEID,OD
【操作平台】: D-Windows XP3
【连接地址】: http://bbs.pediy.com/showthread.php?t=107570
【程序介绍】: 供大家学习交流的小程序;
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【分析前闲谈】
--------------------------------------------------------------------------------
整个程序里有四个时钟,但是时钟的扰乱作用要远远大于它真正提示作用。若是能去掉这些干扰因素
,这个CM绝对是一个很好的练手程序啊!不过值得一提的是这个程序的验证手段设计相当巧妙,验证过程
中需要字符串校验正确一个字符给出一个正确提示的字符。要是没有钢强的毅力那就真的没法看完整个过
程咯!
--------------------------------------------------------------------------------
一、用PEID对程序进行查壳 → Microsoft Visual Basic 5.0 / 6.0 ,无壳练手程序啊!不过不要高兴
的太早了。
二、用OD载入程序进行分析。
载入OD后运行程序,试注册一下,有错误提示。用F12暂停法来到下面的地方(00402ED0)。然后我们再
在段首(00402E50)设置断点.再跑下结果发现是没用的不关键地方,然后再查查字符串结果也是一样!看来
关键地方还隐藏蛮深的哦!那我们就用VB的万能断点吧,查找二进字符串(816C24),来到00402184我们
在有JMP的地方都下断,然后跑起来发现(004021C0)和(004021CD)老是被断下来跟下去也没有用的,干脆把
它们都给取消掉。接着又在(004021A6)和(004021B3)断下,再跟跟发现(004021A6)是只对用户名作检测,
而(004021B3)就总在(004028A4)跳过,那么我们试试不让它跳,看到它对用户名和注册码都有操作,如是
我们大胆猜测这就是关键地方了。就在(004028AA)下断再按一下铵钮看看,结果断下来了。看看分析:
--------------------------------------------------------------------------------
代码:
004028AA 8B96 94000000 mov edx,dword ptr ds:[esi+94] ; 记次数给EDX;
004028B0 8B1D 70104000 mov ebx,dword ptr ds:[<&MSVBVM60.__vbaU>; MSVBVM60.__vbaUbound
004028B6 8D7E 78 lea edi,dword ptr ds:[esi+78]
004028B9 8995 BCFEFFFF mov dword ptr ss:[ebp-144],edx
004028BF 57 push edi
004028C0 6A 01 push 1
004028C2 FFD3 call ebx ; 赋值循环次数为10;
004028C4 8B8D BCFEFFFF mov ecx,dword ptr ss:[ebp-144] ; 记载循环次数;
004028CA 3BC8 cmp ecx,eax ; 比较循环次数够10次了没;
004028CC 0F85 D6020000 jnz CM1237.00402BA8 ; 不够则跳;
--------------------------------------------------------------------------------
一下子就跳下来(00402BA8)怪不得这算法会那么难搞啊!
--------------------------------------------------------------------------------
代码:
00402BA8 83F9 0B cmp ecx,0B
00402BAB 72 06 jb short CM1237.00402BB3
00402BAD FF15 48104000 call dword ptr ds:[<&MSVBVM60.__vbaGene>;
MSVBVM60.__vbaGenerateBoundsError
00402BB3 8B9E 94000000 mov ebx,dword ptr ds:[esi+94]
00402BB9 83FB 0B cmp ebx,0B
00402BBC 72 06 jb short CM1237.00402BC4
00402BBE FF15 48104000 call dword ptr ds:[<&MSVBVM60.__vbaGene>;
MSVBVM60.__vbaGenerateBoundsError
00402BC4 8BBE 94000000 mov edi,dword ptr ds:[esi+94]
00402BCA 83FF 0B cmp edi,0B
00402BCD 72 06 jb short CM1237.00402BD5
00402BCF FF15 48104000 call dword ptr ds:[<&MSVBVM60.__vbaGene>;
MSVBVM60.__vbaGenerateBoundsError
00402BD5 8B46 68 mov eax,dword ptr ds:[esi+68] ; 假码:1234567890;
00402BD8 8B4E 4C mov ecx,dword ptr ds:[esi+4C] ; 用户明:8JAD8K7CZW;
00402BDB 66:8B1458 mov dx,word ptr ds:[eax+ebx*2] ; 取注册码(1234567890)每
个字符的UNICODE值传递给DX;
00402BDF 8B85 BCFEFFFF mov eax,dword ptr ss:[ebp-144] ; 循环记次数;
00402BE5 66:331441 xor dx,word ptr ds:[ecx+eax*2] ; 取用户名每个字符的
UNICODE与DX的值XOR;
00402BE9 8B8E 84000000 mov ecx,dword ptr ds:[esi+84] ; 把XOR后的数值转换为字符
串给ECX;
00402BEF 66:891479 mov word ptr ds:[ecx+edi*2],dx ; XOR所得数值(DX)转换好放
在[ECX+EDI*2]这地址上;
00402BF3 8B96 94000000 mov edx,dword ptr ds:[esi+94] ; 记次数给EDX;
00402BF9 83C2 01 add edx,1 ; EDX加1;
--------------------------------------------------------------------------------
以上就运算出一段字符串了,只是简单的用户名和注册码对位异或一下。关键是检证地方了:
--------------------------------------------------------------------------------
代码:
00402A14 FF15 48104000 call dword ptr ds:[<&MSVBVM60.__vbaGene>;
MSVBVM60.__vbaGenerateBoundsError
00402A1A 8B96 84000000 mov edx,dword ptr ds:[esi+84] ; 转换后所得的字符给EDX;
00402A20 66:0FB68D DCFEF>movzx cx,byte ptr ss:[ebp-124] ; 取“You Win! ”每个值
给CX;
00402A28 66:8B045A mov ax,word ptr ds:[edx+ebx*2] ; 取转换后所得的字符每位
的UNICODE值给AX;
00402A2C C785 F0FEFFFF 0>mov dword ptr ss:[ebp-110],0B
00402A36 66:2BC1 sub ax,cx ; AX-CX;
00402A39 66:B9 0700 mov cx,7 ; 把7给CX;
00402A3D 0F80 31020000 jo CM1237.00402C74
00402A43 66:99 cwd
00402A45 66:F7F9 idiv cx ; 除于CX;
....................
....................
00402A6D FF15 94104000 call dword ptr ds:[<&MSVBVM60.#681>] ; MSVBVM60.rtcImmediateIf
00402A73 8D85 E0FEFFFF lea eax,dword ptr ss:[ebp-120]
00402A79 8D8D 70FFFFFF lea ecx,dword ptr ss:[ebp-90]
00402A7F 50 push eax
00402A80 8D95 60FFFFFF lea edx,dword ptr ss:[ebp-A0]
00402A86 51 push ecx
00402A87 52 push edx
00402A88 FF15 78104000 call dword ptr ds:[<&MSVBVM60.__vbaVarC>; MSVBVM60.__vbaVarCat
00402A8E 50 push eax
00402A8F FF15 10104000 call dword ptr ds:[<&MSVBVM60.__vbaStrV>;
MSVBVM60.__vbaStrVarMove
00402A95 8BD0 mov edx,eax ; 判断字符是否与“You
Win! ”的字符相同;
00402A97 8D4D E4 lea ecx,dword ptr ss:[ebp-1C]
00402A9A FF15 AC104000 call dword ptr ds:[<&MSVBVM60.__vbaStrM>; MSVBVM60.__vbaStrMove
00402AA0 8D4D E0 lea ecx,dword ptr ss:[ebp-20]
00402AA3 FF15 BC104000 call dword ptr ds:[<&MSVBVM60.__vbaFree>; MSVBVM60.__vbaFreeStr
--------------------------------------------------------------------------------
检证所用的VB函数实在太BT了我看了大半天才看出来这是意思!汗颜!最后来看看比较CALL是怎么样的:
--------------------------------------------------------------------------------
代码:
00402AF6 B9 08400000 mov ecx,4008
00402AFB 8D46 38 lea eax,dword ptr ds:[esi+38]
00402AFE 8D56 34 lea edx,dword ptr ds:[esi+34]
00402B01 898D 30FFFFFF mov dword ptr ss:[ebp-D0],ecx
00402B07 898D 40FFFFFF mov dword ptr ss:[ebp-C0],ecx
00402B0D 8B4D E4 mov ecx,dword ptr ss:[ebp-1C] ; 校检后所得的字符
;
00402B10 8995 48FFFFFF mov dword ptr ss:[ebp-B8],edx
00402B16 8B10 mov edx,dword ptr ds:[eax] ; 最终比较字符:“
You Win! ”
00402B18 6A 01 push 1
00402B1A 51 push ecx
00402B1B 52 push edx
00402B1C 6A 00 push 0
00402B1E 8985 38FFFFFF mov dword ptr ss:[ebp-C8],eax
00402B24 FF15 84104000 call dword ptr ds:[<&MSVBVM60.__vbaInStr>] ; 关键CALL;
00402B2A 33C9 xor ecx,ecx
00402B2C 83F8 01 cmp eax,1 ; 关键比较EAX为1时
注册成功;
--------------------------------------------------------------------------------
VB注册机源码:
--------------------------------------------------------------------------------
代码:
Private Sub Command1_Click()
Const key = "You Win! " '定义一个常量
Dim i, x, y, z As Integer
Dim name, code As String
Randomize
z = 1
For i = 1 To 1000000
x = Int(Rnd * 43) + 48 '设定用户名的取值范围
y = Asc(Mid(key, z, 1)) Xor x
If y > 32 And y < 127 Then '判断注册码是否在“!至~”之间
name = name + Chr(x)
code = code + Chr(y)
z = z + 1
If z = 11 Then
Exit For '够十位就跳出循环
End If
End If
Next
Text1.Text = name
Text2.Text = code
End Sub
Private Sub Command2_Click()
Const key = "You Win! "
Dim sn As String
Dim i As Integer
Dim code As String * 10 '定义一个数量为10字符数组
code = Text1.Text
For i = 1 To 10
sn = sn + Chr(Asc(Mid(key, i, 1)) Xor Asc(Mid(code, i, 1)))
Next
Text2.Text = sn
End Sub
--------------------------------------------------------------------------------
【经验总结】
--------------------------------------------------------------------------------
1.要撑握一些常用的语言断如VB,DELPHI等铵钮断点;
2.要善于寻找关键点以及去除一些没用的干扰因素,本CM就是时钟干扰很强的那中;
3.写算法注册机:因为只是简单的异或注册机就写的简短些,不过这种注册机制不是什么用户名都有它所
对应的注册码,所以有手动模式和自动模式供大家选择,看你好运么;
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看学技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2010年02月22日 15:52:58 |
评分
-
查看全部评分
|