不输入name,直接点击“Check”按钮,弹出第一个错误窗口;输入name=52pojie,再点击“Check”按钮,弹出第二个错误窗口;输入key=“1234567890”, 再点击“Check”按钮,弹出第三个错误窗口。
第一步、查壳:
无壳,VB程序。
第二步、追码:
用OD载入CyberBlade.2.exe,先出现代码压缩的提示,直接确定进入CPU窗口,中文搜索看看:
内容很少,而且显示内容没有任何错误提示或正确提示的文本,一直以来的文本搜索这次不管用了。那么还有一个查找按钮事件特征码的“816C24”,竟然也没找到,这就比较麻烦了。
先用VB Decompiler来反编译一下本程序吧。
左侧窗口中看到Crackmefrm窗体中有6段子程序,分别是退出按钮、窗体加载、窗体初始化、关于菜单、检查注册码按钮、键盘输入检查,
点击Checkcmd_Click_40E680,在右侧查看对应代码,这里看到了错误或正确提示的文本内容了。然后生成bas文件,再使用bas转map工具生成map文件,在OD中导入,再Ctrl+G,定位于0040E680处这个Check按钮事件的段首,下断点。好象有点不对,这个地址的内容显示不正常:使劲向上向下看,反汇编内绝大数都显示“dd 00”之类的东东。右键选“分析-分析代码”,弹出提示,确定后没有任何改变;
右键再选“分析-从模块中删除分析”,反汇编的内容显示倒是变了,但是内存地址都不对了,0040E680没了!
先不管显示结果了,F9运行,输入name=“52pojie”,key=“123456”,点击“Check”按钮,程序中断于……没有中断!情况有些不对,弹出内存不能读的错误!点击确定,程序中止。反复试了几次,都是这种现象!!!
于是想用其他反编译工具试一试,如SMARTCHK,可以看出在Command1_Click事件里分别取每个字符的ASC码值,但不知道取了之后干什么,所以没有什么用,或者说是自己还不会用:
还有一个WKTVBDebugger,一旦运行引导程序后进入主界面后就出现运行错误,在几个不同的虚拟机中均是同一情况,可能是WKTVBDebugger程序的问题吧。
没办法,回到VB Decompiler这个静态反编译程序中来,将Command1_Click事件反编译代码全部复制下来,再仔细查看:
Private Sub Command1_Click() '40E680
'Data Table: 402AEC
Dim var_98 As Variant ‘定义var_98 变量 类型为 变体数据类型
Dim var_DC As Variant ‘变体
Dim var_BC As Variant ‘变体
Dim var_150 As String ‘字符型
Dim var_11C As Variant ‘变体
Dim var_176 As Integer ‘整数型
loc_40E279: var_9C = Me.txtname.Text ‘var_9C=输入的名字
loc_40E289: var_98 = vbNull 'Ignore this ‘var_98 =没有或者是空?
loc_40E28C: If (var_9C = vbNullString) Then ‘如果没有输入内容,则弹出提示窗口,必须先键入名字
loc_40E2B0: MsgBox("You have to enter you name first.", &H40, "Error", var_FC, var_11C)
loc_40E2B5: var_BC = "": var_DC = "": var_FC = "" 'Ignore this
loc_40E2C0: Exit Sub
loc_40E2C1: End If
以上部分,作用是要求名字不能为空:
loc_40E2CE: var_9C = Me.txtkey.Text ‘此处‘var_9C=输入的注册码
loc_40E2DE: var_98 = vbNull 'Ignore this
loc_40E2E1: If (var_9C = vbNullString) Then
loc_40E305: MsgBox("You have to enter a key first.", &H40, "Error", var_FC, var_11C) ‘“你必须先键入一个注册码”
loc_40E30A: var_BC = "": var_DC = "": var_FC = "" 'Ignore this
loc_40E315: Exit Sub
loc_40E316: End If
以上部分,作用要求注册码不能为空:
loc_40E323: var_9C = Me.txtkey.Text
loc_40E333: var_98 = vbNull 'Ignore this
loc_40E336: If (var_9C = vbNullString) Then ‘注册码至少5个字符
loc_40E35A: MsgBox("You have to enter at least 5 chars.", &H40, "Error", var_FC, var_11C)
loc_40E35F: var_BC = "": var_DC = "": var_FC = "" 'Ignore this
loc_40E36A: Exit Sub
loc_40E36B: End If
作用是要求注册码至少输入5个字符:
loc_40E38D: var_9C = "" 'Ignore this
loc_40E390: var_98 = vbNull 'Ignore this
loc_40E393: For var_14C = 1 To CVar(Len(Me.txtname.Text)): var_12C = var_14C 'Variant ‘以名字长度为循环变量的循环计算,Var_12C=Var_14C
loc_40E3C1: var_FC = Mid(CVar(Me.txtname.Text), CLng(var_12C), 1) ‘取每一个字符
loc_40E3D5: var_11C = var_94 & CVar(Asc(CStr(var_FC))) ‘得到每个字符的ASC值并连接起来
loc_40E3D9: var_94 = var_11C 'Variant
loc_40E3DD: var_150 = "" 'Ignore this
loc_40E3E0: var_98 = vbNull 'Ignore this
loc_40E3E3: var_BC = "": var_DC = "" 'Ignore this
loc_40E3EF: Next var_14C 'Variant
loc_40E3F5: ' Referenced from: 40E422
loc_40E401: HardType 'Ignore this
loc_40E404: If (Len(var_94) > 9) Then ‘如果新得到的数值长度大于9
loc_40E41E: var_94 = Fix((var_94 / 3.141592654)) 'Variant ‘这个数值除以圆周率,并取整
loc_40E422: GoTo loc_40E3F5 ‘直到数字串少于10位
loc_40E425: End If
作用是从Name字符串得出注册码相关的数值:
loc_40E45A: For var_170 = 1 To 10: var_12C = var_170 'Variant ‘这一段代码将注册码与global_52(CLng(var_12C)))反复比较了10次,却什么都不输出
loc_40E46D: var_9C = Me.txtkey.Text
loc_40E486: var_98 = vbNull 'Ignore this
loc_40E489: If (var_9C = global_52(CLng(var_12C))) Then ‘global_52(CLng(var_12C)))是10个假码,从Form_Load()中定义出数值
loc_40E48C: End If
loc_40E48F: Next var_170 'Variant
本段代码作用不明:
loc_40E4CE: HardType 'Ignore this
loc_40E4D1: var_150 = "" 'Ignore this
loc_40E4D4: var_98 = "" 'Ignore this
loc_40E4DB: var_BC = "" 'Ignore this
loc_40E4DE: If ((CVar(Me.txtkey.Text) - var_94) = CVar(Len(Me.txtname.Text))) Then ‘关键跳 如果输入的注册码 - 上面用name计算出的数值 = 输入名字的字符数,则弹出两个正确提示框
loc_40E502: MsgBox("Wow, you have found a correct key!", &H40, "Correct key", var_FC, var_11C)
loc_40E507: var_BC = "": var_DC = "": var_FC = "" 'Ignore this
loc_40E533: MsgBox("Mail me, how you got it: CyberBlade@gmx.net ", &H40, "Correct key!", var_FC, var_11C)
loc_40E538: var_BC = "": var_DC = "": var_FC = "" 'Ignore this
loc_40E550: Me.Command2.Caption = "Exit" loc_40E555: var_98 = vbNull 'Ignore this
以上是注册码正确则弹出正确提示来:
loc_40E55B: Else ‘否则弹出 错误提示框
loc_40E567: global_80 = (global_80 + 1) ‘global_80 全局变量 loc_40E570: var_176 = global_80
loc_40E579: If (var_176 = 6) Then
loc_40E587: var_DC = "I can't stand it anymore"
loc_40E597: var_BC = "-=Do you need a hint ?=-"
loc_40E5B3: If (MsgBox("": var_DC = "": var_FC = "", &H24, var_DC, var_FC, var_11C) = 7) Then
loc_40E5B6: Exit Sub
loc_40E5BA: Else
loc_40E5DB: MsgBox("Forget it.", &H40, "he, he...", var_FC, var_11C)
loc_40E5E0: var_BC = "": var_DC = "": var_FC = "" 'Ignore this
loc_40E5F0: global_80 = 0
loc_40E5F3: End If
loc_40E5F6: Else
loc_40E5FC: If (var_176 > 3) Then
loc_40E620: MsgBox("Have you ever been trying to be successful in cracking my password ?", &H20, "Failed", var_FC, var_11C)
loc_40E625: var_BC = "": var_DC = "": var_FC = "" 'Ignore this
loc_40E633: Else
loc_40E639: If (var_176 <= 3) Then
loc_40E65D: MsgBox("Sorry, wrong key.", &H40, "Failed", var_FC, var_11C)
loc_40E662: var_BC = "": var_DC = "": var_FC = "" 'Ignore this
loc_40E66D: End If
loc_40E66D: End If
loc_40E66D: End If
loc_40E66D: End If
以上是注册码错误,则弹出错误提示窗口。
loc_40E677: Me.txtkey.SetFocus
loc_40E67C: var_98 = vbNull 'Ignore this
loc_40E67F: Exit Sub
End Sub
从中可以得出注册算法(VB代码):
Option ExplicitPrivate Sub Command1_Click()
Dim Name As String Dim var_94 As Variant 'var_94是CM程序中反编译出的地址,作为注册码使用
Dim i, global_76 As Integer 'global_76是CM程序中的全局变量,在Form_Load()和Form_Initialize()中定义并计算出数值
Name = Text1.Text
If Len(Name) < 5 Then MsgBox ("请输入至少5个字符,如果不够5个字符,默认用户名为“52pojie”!")
Text1.Text = "52pojie"
Text2.Text = "346288390"
Exit Sub
End If
For i = 1 To Len(Name)
var_94 = var_94 & CVar(Asc(Mid(Name, i, 1)))
'Form1.Print var_94
Next
Text1.Text = Name
While (Len(var_94) > 9) '如果新得到的数字串长度大于9
var_94 = Int(var_94 / 3.141592654) 'Variant '反复除以圆周率,并取整,直到数字少于10位
Wend
'var_94 = var_94 Xor &H30F85678 - global_76 '这个运算顺序是先减再异或,从CM中看到是先异或后减,所以结果老出错,郁闷了很久才找到问题所在
'var_94 = (var_94 Xor &H30F85678) - global_76 'Variant '&H30F85678 (821581432) global_76为全局变量,从哪里找到?
var_94 = (var_94 Xor 821581432) - 55475 + Len(Name)
Text2.Text = var_94
End Sub
用注册机算出Name=“52pojie”,Key=“346288390”;Name=“haitianyise”,Key=“717489583”,分别输入CyberBlade.2.exe中运行,均成功了。
第三步、爆破:
从追码过程中已知loc_40E4DE一句是关键跳,跳走则是失败,那么就让它不跳即可。
在VB Decompiler的反编译窗口中0040E4DE处显示为
loc_40E4DE: If ((CVar(Me.txtkey.Text) - var_94) = CVar(Len(Me.txtname.Text))) Then
在反汇编窗口0040E4DE则显示为下图中
loc_40E4DE: BranchF loc_40E55B
从网上查看了许多参考资料,包括论坛中大神鬼手56的《160个Crackme038之P-Code初窥门径》、Pnmker的《160个CrackMe练手之038》、china豪的《160个CrackMe之038 菜鸟初探p-code》等文章,基本上明白是将BranchF 改为BranchT。
习惯性用OD加载上CyberBlade.2.exe,在CPU窗口右键转到0040E4DE处,在HEX数据栏中右键点击“1C”,选择“二进制—编辑”选项,在弹出窗口中将C改成D,