Start
0x01 信息收集
查壳,VB程序:
运行存在两个CrackMe:
CM1.0为Serial:
CM2.0为Serial/Name:
CM2中如果Name长度小于5会在Serial中显示At least 5 characters
0x02 流程分析
CM1.0,下vb的api断点_vbaStrComp
运行程序,输入111111,点击Try程序断下:
单步往下可以看到将两个字符串以及输入的字符串的长度压入栈中,然后调用msvbvm50.dll的函数,猜测应该就是比较字符串的长度:
经过测试可以发现Serial是固定值7730050
重新运行程序,输入7730050
,成功Crack:
选择CM2.0,在SetWindowsTextA的函数头下断,然后往回跟,这里就是注册失败的地方,往上的je指令是跳过提示失败的地方:
由于堆栈的内容是不会清空的,所以往下翻,翻到了疑似真正Serial的地方:26023-94362
VB Decompiler反编译找到关键回调函数,关键处理就在两个For循环:
Dim var_90 As Long
Dim var_1CC As Variant
If (Len(Me.Text1.Text) < 5) Then
Me.Text2.Text = "At least 5 characters!"
Exit Sub
End If
var_94 = "0110617121214051216101106141404110614140411091211100810101608040610121608100416"
var_98 = Me.Text1.Text
var_A8 = 1 'Variant
For var_108 = 4 To CVar(Len(var_98)): var_C8 = var_108 'Variant
var_90 = CLng((CDbl(var_90) + (CDbl(Asc(Mid$(var_98, CLng(var_C8), 1))) * Val(Mid$(var_94, CLng((var_A8 * 3)), 3)))))
If ((var_A8 + 1) >= 39) Then
var_A8 = 0 'Variant
End If
Next var_108 'Variant
var_A8 = 1 'Variant
For var_168 = 4 To CVar(Len(var_98)): var_C8 = var_168 'Variant
var_1CC = CVar((CDbl((Asc(Mid$(var_98, CLng(var_C8), 1)) * Asc(Mid$(var_98, CLng((var_C8 - 1)), 1)))) * Val(Mid$(var_94, CLng((var_A8 * 2)), 2)))) 'Double
var_178 = (var_178 + var_1CC) 'Variant
If ((var_A8 + 1) >= 39) Then
var_A8 = 0 'Variant
End If
Next var_168 'Variant
If (Me.Text2.Text = LTrim$(Str$(var_90)) & "-" & LTrim$(Str$(var_178))) Then
Me.Command2.Visible = False
Me.Command1.Visible = False
Me.Command5.Visible = True
Me.Command3.Visible = False
Me.Text2.Visible = False
Me.Frame3.Visible = True
Me.Label3.Caption = "Congratulation " & Me.Text1.Text & " !"
Else
Me.Text2.Text = "Try Again!"
End If
Exit Sub
比较长拆分一下:
a = Mid$(var_98, CLng(var_C8), 1)
b = Mid$(var_94, CLng(var_A8 * 3), 3)
res1 = CLng(CDbl(Asc(a)) * Val(b))
a = Mid$(var_98, CLng(var_C8), 1)
b = Mid$(var_98, CLng((var_C8 - 1)), 1)
c = CDbl(Asc(a) * Asc(b))
d = Mid$(var_94, CLng((var_A8 * 2)), 2)
res2 = CVar(c * Val(d))
VB相关函数:
Asc: Asc("ab")=Asc("a")=97
Val: Val("123")=123; Val("011")=11
Mid: Mid("123", 1, 1)="1" ;注意这里的索引从1开始索引,类似于sql的substr也是从1开始索引
Str: Str(123)="123"
CDbl: 转成双精度浮点数
CLng: 转成长整型整数
0x03 注册机
这里是想用Python写注册机的,不过发现有点问题,所以直接用VB写,顺便学一下VB的语法,翻了一下教程基本上可以速成,这里反编译的语法跟实际的语法还是有区别:
Console Application版本:
Imports System
Module Program
Sub Main(args As String())
Dim a As String
Dim b As String
Dim name As String
Dim j As VariantType
Dim index As VariantType
Dim res1 As VariantType
Dim res2 As VariantType
Dim key As String
index = 1 'Variant
'自己改name的值就行了'
name = "123456"
key = "0110617121214051216101106141404110614140411091211100810101608040610121608100416"
res1 = 0
For i = 4 To Len(name) : j = i 'Variant
Console.WriteLine(i)
a = Asc(Mid(name, i, 1))
b = Val(CLng(Mid(key, index * 3, 3)))
index += 1
res1 += a * b
Next i 'Variant
index = 1 'Variant
For i = 4 To Len(name) : j = i 'Variant
Console.WriteLine(i)
a = CDbl(Asc(Mid(name, j, 1)) * Asc(Mid(name, j - 1, 1)))
b = Val(Mid(key, index * 2, 2)) 'Double
index += 1
res2 += a * b
Next i 'Variant
Console.WriteLine("Serial:" & res1 & "-" & res2)
End Sub
End Module
Form Applicaton 版本:
Public Function GenerateSerial(name) As String
Dim a As String
Dim b As String
Dim j As VariantType
Dim index As VariantType
Dim res1 As VariantType
Dim res2 As VariantType
Dim key As String
index = 1 'Variant
key = "0110617121214051216101106141404110614140411091211100810101608040610121608100416"
res1 = 0
For i = 4 To Len(name) : j = i 'Variant
Console.WriteLine(i)
a = Asc(Mid(name, i, 1))
b = Val(CLng(Mid(key, index * 3, 3)))
index += 1
res1 += a * b
Next i 'Variant
index = 1 'Variant
For i = 4 To Len(name) : j = i 'Variant
Console.WriteLine(i)
a = CDbl(Asc(Mid(name, j, 1)) * Asc(Mid(name, j - 1, 1)))
b = Val(Mid(key, index * 2, 2)) 'Double
index += 1
res2 += a * b
Next i 'Variant
GenerateSerial = res1 & "-" & res2
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
SerialText.Text = GenerateSerial(NameText.Text)
End Sub
Result:
ps: CM12 是16位的DOS程序没有运行环境就不写了
Comments NOTHING