吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7901|回复: 10
收起左侧

[原创] 160 个 CrackMe 之 112 - BaSiLik 和 138 - Sortof 的p-code代码算法分析和注册机实现

[复制链接]
solly 发表于 2019-7-3 12:30
本帖最后由 solly 于 2019-7-3 13:20 编辑

160 个 CrackMe 之 112 - BaSiLik 是一个 VB6 p-code 程序。并且使用 upx 1.0.1 打包压缩了,在其反调试代码中还有这方面的检查。
启动 CrackMe 后,如下图:
00.png
这个 Unique 码,是根据机器硬盘的信息生成的。另外还要输入用户名,公司名,序列号,一起进行验证。
用 VB Decompiler 打开,可以看到主要调用在 Form.Load() 和 cmdCheck_Click()中。如下两图所示:
12.png
以及:
13.png
具体的代码如下:
[Visual Basic] 纯文本查看 复制代码
Private Sub Form_Load() '404420
  'Data Table: 4030F8
  loc_4043FC: Proc_1_5_404640()  ' SmartCheck 检查,通过 FindWindow("NMSCMW50", 0) 检查
  loc_404401: Proc_1_8_404C24()  ' crack 文件改名和 unpack 检查(文件大小检查)
  loc_404406: Proc_1_6_404A48()  ' w32dasm8 检查,这个检查有问题,没有 %windir%\\w32dasm8.ini 文件也报安装了 W32Dasm,是由于UAC权限不够的原因导致的。
  loc_40440B: Proc_1_4_404580()  ' Registry Monitor 检查,通过 FindWindow("RegmonClass", 0) 检查
  loc_404410: Proc_1_3_404810()  ' IDA 检查。通过注册表检查,注册表项 "HKEY_CURRENT_USER\Software\Datarescue\IDA"
  loc_404415: Proc_1_8_404C24()  ' 再一次crack 文件改名和 unpack 检查(文件大小检查)
  loc_40441A: Proc_1_2_405180()  ' GetVolumeInformationA("C:\")
  loc_40441F: Exit Sub
End Sub

以及:
[Visual Basic] 纯文本查看 复制代码
Private Sub cmdCheck_Click() '404474
  'Data Table: 4030F8
  loc_404450: Proc_1_5_404640()  ' SmartCheck 检查,通过 FindWindow("NMSCMW50", 0) 检查
  loc_404455: Proc_1_8_404C24()  ' crack 文件改名和 unpack 检查(文件大小检查)
  loc_40445A: Proc_1_6_404A48()  ' w32dasm8 检查,这个检查有问题,没有 %windir%\\w32dasm8.ini 文件也报安装了 W32Dasm,是由于UAC权限不够的原因导致的。
  loc_40445F: Proc_1_4_404580()  ' Registry Monitor 检查,通过 FindWindow("RegmonClass", 0) 检查
  loc_404464: Proc_1_3_404810()  ' IDA 检查。通过注册表检查,注册表项 "HKEY_CURRENT_USER\Software\Datarescue\IDA"
  loc_404469: Proc_1_7_404720()  ' SoftICE 检查。扫描 C 盘根目录文件,将每个文件通过调用 Proc_1_9_404920() 进行处理,就是检查 Autoexec.bat 文件中有没有包含 winice.exe 的命令行,这个检查会引起文件访问冲突,导致 Run-time error '70'。
  loc_40446E: Proc_1_1_404EAC()  ' 对输入的用户名,公司名和序列号进行检查,只有这些数据的长度都大于8个字符时,才进行序列号验证,验证函数为 Proc_1_0_405730()。
  loc_404473: Exit Sub
End Sub

我们主要分析其序列号验证过程,其它反调试代码不在这说明。
主要有两个过程,一个是生成 Unique 码(Proc_1_2_405180()),另一个是序列号验证(Proc_1_1_404EAC())。
我们通过 VB Decompiler 静态分析,Proc_1_2_405180() 反编译代码如下:
[Visual Basic] 纯文本查看 复制代码
Public Sub Proc_1_2_405180
  'Data Table: 402C8C
  loc_404F05: Me(40) = CStr(Space(&H100))
  loc_404F1F: Me(60) = CStr(Space(&H100))
  loc_404F36: var_A0 = Me(60)
  loc_404F85: Me(64) = GetVolumeInformationA("C:\", Me(40), Len(Me(40)), Me(44))
  loc_404FC3: Me(40) = CStr(Left(Me(40), (InStr(1, Me(40), vbNullString, 0) - 1)))
  loc_404FFC: Me(60) = CStr(Left(Me(60), (InStr(1, Me(60), vbNullString, 0) - 1)))
  loc_405026: Me(48) = CStr(Trim(Hex(Me(44))))
  loc_405062: Me(48) = CStr(String((8 - Len(Me(48))), "0") & CVar(Me(48)))
  loc_4050B3: Me(48) = CStr(Left(Me(48), 4) & "-" & Right(Me(48), 4))
  loc_4050E3: Me(48) = Replace(Me(48), "-", vbNullString, 1, -1, 0)
  loc_4050F3: Me(48) = StrReverse(Me(48))
  loc_40515C: Set var_148 = MemVar_406008.Text4
  loc_405162: frmMain.Text4.Text = CStr(Left(Me(60), 1) & "54-" & CVar(Me(48)) & "-05" & Right(Me(60), 1))
  loc_40517C: Exit Sub
End Sub

其中除了有一行反编译不正确其它基本还是正确的,翻译成 VB 代码如下:
[Visual Basic] 纯文本查看 复制代码
Private Declare Function GetVolumeInformation Lib "kernel32.dll" _
                                Alias "GetVolumeInformationA" _
                                (ByVal p1 As String, _
                                 ByVal p2 As String, _
                                 ByVal p3 As Long, _
                                 ByRef p4 As Long, _
                                 ByRef p5 As Long, _
                                 ByRef p6 As Long, _
                                 ByVal p7 As String, _
                                 ByVal p8 As Long) As Boolean

Public Function getUnique()
  Dim result As Boolean
  Dim nVolumeNameSize As Long, lpVolumeSerialNumber As Long, p2 As Long, p3 As Long
  Dim lpVolimeNameBuffer As String
  Dim lpFileSystemNameBuffer As String
  Dim s1, s2, s3 As String
  
  nVolumeNameSize = 255
  lpVolimeNameBuffer = Space(256)
  lpFileSystemNameBuffer = Space(256)
  lpVolumeSerialNumber = 0
  
  result = GetVolumeInformation("C:\", lpVolimeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, p2, p3, lpFileSystemNameBuffer, nVolumeNameSize)
  If lpVolumeSerialNumber <> 0 Then
      's1 = Left(lpVolimeNameBuffer, (InStr(1, lpVolimeNameBuffer, vbNullChar, vbBinaryCompare) - 1)) '去掉'\0'及后面的空格符
      s2 = Left(lpFileSystemNameBuffer, (InStr(1, lpFileSystemNameBuffer, vbNullChar, vbBinaryCompare) - 1)) '去掉'\0'及后面的空格符,文件系统格式:"NTFS","FAT32" 等。
      
      s3 = Trim(Hex(lpVolumeSerialNumber)) '序列号转成 Hex 格式字符串
      s3 = String(8 - Len(s3), "0") & s3
      's3 = Left(s3, 4) & "-" & Right(s3, 4)
      's3 = Replace(s3, "-", vbNullString, 1, -1, vbBinaryCompare)
      s3 = StrReverse(s3) '反转换序列号字符串
      ' 返回 Unique 字符串
      getUnique = Left(s2, 1) & "54-" & s3 & "-05" & Right(s2, 1)
      
  Else
      getUnique = ""
  End If

End Function

主要用到了磁盘C:\的序列号和文件系统格式(如 "NTFS","FAT32"等)。CrackMe 这段代码参考了以下地址的 Example 部分,连没有用到的代码都复制过来了(上面代码注释掉的部分):
http://www.jasinskionline.com/wi ... umeinformation.html

另一个过程 Proc_1_1_404EAC() 先验证输入的信息是否合法(输入信息的长度要大于或等于8),然后调用 Proc_1_0_405730() 验证序列号,这个验证过程(Proc_1_0_405730())内容如下:
[Visual Basic] 纯文本查看 复制代码
Public Sub Proc_1_0_405730
  'Data Table: 402C8C
  Dim var_D0 As Integer
  Dim var_E4 As Variant
  Dim var_88 As TextBox
  loc_4051E4: Set var_88 = MemVar_406008.Text4
  loc_40520C: Me(68) = Replace(frmMain.Text4.Text, "-", vbNullString, 1, -1, 0)
  loc_40521C: Me(76) = CStr(0)
  loc_405230: For var_90 = 1 To CInt(Len(Me(68))): Me(96) = var_90 'Integer
  loc_405257:   Me(72) = CStr(Mid$(Me(68), CLng(Me(96)), 1))
  loc_405279:   Me(76) = CStr((CDbl(Asc(Me(72))) + CDbl(Me(76))))
  loc_405284: Next var_90 'Integer
  loc_40528D: Me(80) = CStr(0)
  loc_4052A6: Set var_88 = MemVar_406008.Text1
  loc_4052BC: For var_D4 = 1 To CInt(Len(frmMain.Text1.Text)): Me(98) = var_D4 'Integer
  loc_4052CE:   Set var_88 = MemVar_406008.Text1
  loc_4052F6:   Me(84) = CStr(Mid$(CVar(frmMain.Text1.Text), CLng(Me(98)), 1))
  loc_40531D:   Me(80) = CStr((CDbl(Asc(Me(84))) + CDbl(Me(80))))
  loc_405328: Next var_D4 'Integer
  loc_405331: Me(88) = CStr(0)
  loc_40534A: Set var_88 = MemVar_406008.Text2
  loc_405360: For var_E8 = 1 To CInt(Len(frmMain.Text2.Text)): Me(100) = var_E8 'Integer
  loc_405372:   Set var_88 = MemVar_406008.Text2
  loc_40539A:   Me(92) = CStr(Mid$(CVar(frmMain.Text2.Text), CLng(Me(100)), 1))
  loc_4053C1:   Me(88) = CStr((CDbl(Asc(Me(92))) + CDbl(Me(88))))
  loc_4053CC: Next var_E8 'Integer
  loc_4053DD: Set var_88 = MemVar_406008.Text1
  loc_405424: Me(104) = CStr(Mid$(CVar(Replace(frmMain.Text1.Text, " ", vbNullString, 1, -1, 0)), 4, 2))
  loc_405449: Set var_88 = MemVar_406008.Text2
  loc_405490: Me(108) = CStr(Mid$(CVar(Replace(frmMain.Text2.Text, " ", vbNullString, 1, -1, 0)), 5, 3))
  loc_4054B5: Set var_88 = MemVar_406008.Text4
  loc_4054FC: Me(112) = CStr(Mid$(CVar(Replace(frmMain.Text4.Text, " ", vbNullString, 1, -1, 0)), 5, 3))
  loc_405521: Set var_88 = MemVar_406008.Text3
  loc_40552F: var_E4 = CVar(frmMain.Text3.Text) 'String
  loc_40558C: var_D0 = Ucase(CVar("34" & Me(112) & "-" & Me(76) & StrReverse(Me(80)) & "-" & Me(108) & Me(88) & "-" & Me(104)))
  loc_4055B7: If CBool(var_E4 <> var_D0) Then
  loc_4055D3:   MsgBox "Incorrect Serial Number!", 0, var_D0, var_E4, var_11C
  loc_4055EF:   Set var_88 = MemVar_406008.Text1
  loc_4055F5:   frmMain.Text1.Text = vbNullString
  loc_405609:   Set var_88 = MemVar_406008.Text2
  loc_40560F:   frmMain.Text2.Text = vbNullString
  loc_405623:   Set var_88 = MemVar_406008.Text3
  loc_405629:   frmMain.Text3.Text = vbNullString
  loc_405631:   Exit Sub
  loc_405635: Else
  loc_405646:   (0).Visible = %x1b
  loc_405659:   Set var_88 = MemVar_406008.Text2
  loc_40565F:   frmMain.Text2.Visible = False
  loc_405672:   Set var_88 = MemVar_406008.Text3
  loc_405678:   frmMain.Text3.Visible = False
  loc_40568B:   Set var_88 = MemVar_406008.Text4
  loc_405691:   frmMain.Text4.Visible = False
  loc_4056A4:   Set var_88 = MemVar_406008.Label1
  loc_4056AA:   frmMain.Label1.Visible = False
  loc_4056BD:   Set var_88 = MemVar_406008.Label2
  loc_4056C3:   frmMain.Label2.Visible = False
  loc_4056D6:   Set var_88 = MemVar_406008.Label3
  loc_4056DC:   frmMain.Label3.Visible = False
  loc_4056EF:   Set var_88 = MemVar_406008.Label4
  loc_4056F5:   frmMain.Label4.Visible = False
  loc_405708:   Set var_88 = MemVar_406008.cmdCheck
  loc_40570E:   frmMain.cmdCheck.Visible = False
  loc_405721:   Set var_88 = MemVar_406008.Label5
  loc_405727:   frmMain.Label5.Visible = True
  loc_40572F: End If
  loc_40572F: Exit Sub
End Sub

跟据以上反编译代码,实现序列号的计算过程如下:
[Visual Basic] 纯文本查看 复制代码
Public Function getSerial(unique As String, name As String, company As String) As String
  Dim i As Long, j As Long, k As Long
  Dim s1 As String, s2 As String, s3 As String, s4 As String
  Dim s5 As String, s6 As String, s7 As String, s8 As String
  
  Dim ss1 As Long, ss2 As Long, ss3 As Long
  
  s1 = Replace(unique, "-", vbNullString, 1, -1, vbBinaryCompare)
  
  ss1 = 0
  For i = 1 To Len(s1)
    ss1 = ss1 + Asc(Mid(s1, i, 1))
  Next i
  
  ss2 = 0
  For i = 1 To Len(name)
    ss2 = ss2 + Asc(Mid(name, i, 1))
  Next i
  
  ss3 = 0
  For i = 1 To Len(company)
    ss3 = ss3 + Asc(Mid(company, i, 1))
  Next i
  
  s3 = Replace(name, " ", vbNullString, 1, -1, vbBinaryCompare)
  s4 = Mid(s3, 4, 2)
  
  s5 = Replace(company, " ", vbNullString, 1, -1, vbBinaryCompare)
  s6 = Mid(s5, 5, 3)
  
  s7 = Replace(unique, " ", vbNullString, 1, -1, vbBinaryCompare)
  s8 = Mid(s7, 5, 3)
  
  getSerial = UCase("34" & s8 & "-" & CStr(ss1) & StrReverse(ss2) & "-" & s6 & ss3 & "-" & s4)
  
  ' clipboard
  VB.Clipboard.Clear
  VB.Clipboard.SetText getSerial, vbCFText
  
End Function


生成序列号后,返回界面输入:
02.png
点“Check it!”,得到成功信息提示:
03.png

实现的注册机的界面如下:
05.png
也是用 VB6 完成的。

下面针对 CrackMe 的问题进行相应的修改,让其可以在最新系统上可以正常运行,前面的反编译代码我也进行了注释,下面是修改内容:
[Visual Basic] 纯文本查看 复制代码
'(1)
' 函数  loc_404469: Proc_1_7_404720(),会引起错误:Run-time error '70': Permission denied
' 可以将此函数中的 For 循环的开始值改大(loc_4046DA: push 1 ),从而不进入循环来避免出错。
' 004046DA  F4 01 AD 1A 74 FF FE 63 6E FF 96 00 04 68 FF 93
' 将 push 01 改成 push 7F, C 盘根目录一般不会有127个以上的文件吧(文件中的位置:0x000046DA)
' 004046DA  F4 7F AD 1A 74 FF FE 63 6E FF 96 00 04 68 FF 93

'(2)
' 将文件名改名判断patch掉
' 00404AD3  1C 89 00 27 F4 FE 27 34 FF 27 54 FF F5 00 00 00
' 改成(文件中的位置:0x00004AD3)
' 00404AD3  1E 89 00 27 F4 FE 27 34 FF 27 54 FF F5 00 00 00

'(3)
' 将文件大小判断patch掉
' 00404BDC  1C 92 01 27 F4 FE 27 34 FF 27 54 FF F5 00 00 00
' 改成(文件中的位置:0x00004BDC)
' 00404BDC  1E 92 01 27 F4 FE 27 34 FF 27 54 FF F5 00 00 00

'(4) 
' 函数 loc_404406: Proc_1_6_404A48() 由于 UAC 限制,需要管理员权限才能正常运行,也Patch掉
' 004049FE  1C DC 00 27 F4 FE 27 14 FF 27 34 FF F5 00 00 00
' 改成(文件中的位置:0x000049FE)
' 004049FE  1E DC 00 27 F4 FE 27 14 FF 27 34 FF F5 00 00 00



改完后,对比一下修改是否正确:
[HTML] 纯文本查看 复制代码
I:\Downloads\crack\112_BaSiLiK>fc /b CrackMe_unpacked_cracked.exe CrackMe_unpacked.exe
正在比较文件 CrackMe_unpacked_cracked.exe 和 CRACKME_UNPACKED.EXE
000046DB: 7F 01
000049FE: 1E 1C
00004AD3: 1E 1C
00004BDC: 1E 1C


修改过程中用的二进制工具 UltraEditor。通过上面的反编译可以找到指令地址,在OD数据区可以找到指令数据,如下图:
14.png
上面的 1C 就是要修改的指令,复制出指令数据,直接在 UltraEditor 中搜索即可,不用去计算RAV之类的了:
15.png
可以搜到指令在文件中的位置:
16.png
然后直接修改保存就可以了。

完毕!!!

免费评分

参与人数 3威望 +1 吾爱币 +11 热心值 +3 收起 理由
Hmily + 1 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
pk8900 + 3 + 1 谢谢@Thanks!楼主加油~~~~~~~~~~
笙若 + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| solly 发表于 2019-7-3 12:31

160 个 CrackMe 之 138 - Sortof 的注册算法分析和注册机实现

本帖最后由 solly 于 2019-7-4 09:09 编辑

160 个 CrackMe 之 138 - Sortof 是一个 VB5 p-code的 CrackMe。
启动后界面如下,需要输入用户名和序列号进行验证:
10.png
使用 VB Decompliler 进行静态反编译分析,其验证算法在按钮事件处理过程内,如下:
[Visual Basic] 纯文本查看 复制代码
Private Sub Command1_Click() '41AAF4
  'Data Table: 401D40
  Dim var_194 As String
  Dim var_B4 As Variant
  Dim var_1EC As Variant
  loc_41A54C: On Error Goto loc_41AABF
  loc_41A559: If Not((X = 1)) Then
  loc_41A55C:   GoTo loc_41AABF
  loc_41A55F: End If
  '  X 是一个全局变量,在 Form_Load() 事件中赋值,X = 1
  '  If X = 0 Then
  '    Exit Sub()
  '  End If 
  loc_41A564: var_94 = vbNullString 'Variant
  loc_41A578: var_C4 = Chr(&H32) 'Variant
  loc_41A58C: var_D4 = Chr(&H33) 'Variant
  loc_41A5A0: var_E4 = Chr(&H34) 'Variant
  loc_41A5B4: var_F4 = Chr(&H35) 'Variant
  loc_41A5C8: var_104 = Chr(&H36) 'Variant
  loc_41A5DC: var_114 = Chr(&H37) 'Variant
  loc_41A5E5: var_124 = 0 'Variant
  ' 初始化变量
  '  var_94 = ""
  '  var_C4 = "2", var_D4 = "3", var_E4 = "4", var_CF4 = "5", var_C104 = "6", var_C114 = "7"
  '  var_124 = 0
  '
  loc_41A6C3: var_194 = Me.Text1.Text & Me.Text1.Text & Me.Text1.Text & Me.Text1.Text & Me.Text1.Text & Me.Text1.Text & Me.Text1.Text & Me.Text1.Text & Me.Text1.Text
  loc_41A711: var_1BC = CVar(var_194 & Me.Text1.Text & Me.Text1.Text & Me.Text1.Text) 'Variant
  '  取用户名,并重复12次
  '  var_1BC =  Text1.Text & Text1.Text & Text1.Text & Text1.Text & Text1.Text & Text1.Text & Text1.Text & Text1.Text & Text1.Text & Text1.Text & Text1.Text & Text1.Text
  '
  loc_41A75F: ' Referenced from: 41A9C5
  loc_41A7AF: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A811: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A873: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A87D: var_B4 = var_94 & (var_C4 + CVar(Asc(CStr(Left(var_1BC, 1))))) & (var_D4 + CVar(Asc(CStr(Left(var_1BC, 1))))) & (var_E4 + CVar(Asc(CStr(Left(var_1BC, 1)))))
  loc_41A8D5: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A937: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A999: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A9A3: var_B4 = var_B4 & (var_F4 + CVar(Asc(CStr(Left(var_1BC, 1))))) & (var_104 + CVar(Asc(CStr(Left(var_1BC, 1))))) & (var_114 + CVar(Asc(CStr(Left(var_1BC, 1)))))
  loc_41A9A7: var_94 = var_B4 'Variant
  ' 上面这几行伪代码的顺序有问题,var_B4 是分开多次赋值,这里全合并在一起,取值就不对了(是 VB Decompiler 优化的显示的问题)。正确应该如下顺序:
  '  var_B4 = var_94 & (var_C4 + CVar(Asc(CStr(Left(var_1BC, 1)))))
  '  var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  '  var_B4 = var_B4 & (var_D4 + CVar(Asc(CStr(Left(var_1BC, 1)))))
  '  var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  '  var_B4 = var_B4 & (var_E4 + CVar(Asc(CStr(Left(var_1BC, 1)))))
  '  var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  ' 另外半部分  
  '  var_B4 = var_B4 & (var_F4 + CVar(Asc(CStr(Left(var_1BC, 1)))))
  '  var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  '  var_B4 = var_B4 & (var_104 + CVar(Asc(CStr(Left(var_1BC, 1)))))
  '  var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  '  var_B4 = var_B4 & (var_114 + CVar(Asc(CStr(Left(var_1BC, 1)))))
  '  var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  '  将值转赋给另一个变量,后面用新变量进行判断
  ' var_94 = var_B4
  '
  loc_41A9B6: If (var_124 = 1) Then
  loc_41A9B9:   GoTo loc_41A9DC
  loc_41A9BC: End If
  loc_41A9C1: var_124 = 1 'Variant
  loc_41A9C5: GoTo loc_41A75F
  '  If var_124 = 0 Then
  '    var_124 = 1
  '  End If
  '
  loc_41A9D8: var_200 = CVar(Me.Left) 'Variant
  loc_41A9DC: ' Referenced from: 41A9FE
  loc_41A9DC: ' Referenced from: 41A9B9
  loc_41A9EB: If (Len(var_94) < 12) Then
  loc_41A9FA:   var_94 = "0" & var_94 'Variant
  loc_41A9FE:   GoTo loc_41A9DC
  loc_41AA01: End If
  '  当计算的序列号长度不足12位时,前面补"0"  
  '  While Len(var_94) <12
  '    var_94 = "0" & var_94
  '  Wend
  loc_41AA1B: var_210 = "1012041024412" 'Variant
  loc_41AA22: var_94 = var_94 'Variant
  loc_41AA35: If (Len(var_94) > 12) Then
  loc_41AA4B:   var_94 = Left(var_94, &HC) 'Variant
  loc_41AA4F: End If
  '  var_210 = "1012041024412"  ' 迷惑用的,没有用到这个变量
  '  计算的序列号长度大于12时截成12位长度
  '  If (Len(var_94) > 12) Then
  '    var_94 = Left(var_94, 12)
  '  End If
  loc_41AA58: If (X = 1) Then
  loc_41AA7B:   var_1EC = Not (CVar(Me.Text2.Text) = var_94)
  loc_41AA87:   If CBool(var_1EC) Then
  loc_41AA8A:     GoTo loc_41AABF
  loc_41AA8D:   End If
  loc_41AA8D: End If
  loc_41AAAE: MsgBox "Well I" & Chr(39) & "ll be damned!!  nice job", 0, "correct", var_1EC, var_260
  loc_41AABE: Exit Sub
  '  If X = 1 Then
  '   计算的注册码与输入的注册码进行比较
  '    If Text2.Text = var_94 Then  
  '      提示注册成功 
  '      MsgBox "Well I" & Chr(39) & "ll be damned!!  nice job", 0, "correct"
  '      Exit Sub()
  '    End If
  '  End If  
  '  下面是提示注册失败
  loc_41AABF: ' Referenced from: 41AA8A
  loc_41AABF: ' Referenced from: 41A55C
  loc_41AABF: ' Referenced from: 41A54C
  loc_41AAE0: MsgBox "sorry! try again", 0, "try again", var_1EC, var_260
  loc_41AAF0: Exit Sub
End Sub

不过,VB Decompiler 进行伪代码显示优化时,调动了代码顺序,会有问题,主要是下面几行中代码,那个 var_B4 变量的赋值合并有问题,见我后面的代码:
[Visual Basic] 纯文本查看 复制代码
  loc_41A7AF: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A811: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A873: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A87D: var_B4 = var_94 & (var_C4 + CVar(Asc(CStr(Left(var_1BC, 1))))) & (var_D4 + CVar(Asc(CStr(Left(var_1BC, 1))))) & (var_E4 + CVar(Asc(CStr(Left(var_1BC, 1)))))
  loc_41A8D5: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A937: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A999: var_1BC = Right(var_1BC, CLng((Len(var_1BC) - 1))) 'Variant
  loc_41A9A3: var_B4 = var_B4 & (var_F4 + CVar(Asc(CStr(Left(var_1BC, 1))))) & (var_104 + CVar(Asc(CStr(Left(var_1BC, 1))))) & (var_114 + CVar(Asc(CStr(Left(var_1BC, 1)))))


去掉VB Decompiler 代码框上面的两个优化选项,重新反编译,就会恢复正常。

在 Excel 中将上面代码翻译成 VBA 代码,代码进行了优化,不完全与上面一致,如下:
[Visual Basic] 纯文本查看 复制代码
Sub button1_Click()
  Dim i As Long, n As Long
  Dim name As String, name1 As String, base As String, sn As String

  name = Sheet1.Cells(4, 4)

  If name = "" Then
    MsgBox "Please inter a name!", vbOKOnly, "ERROR"
    Exit Sub
  End If

  While Len(name) < 6
    name = name & name
  Wend

  sn = ""
  'base = "234567"
  
  For i = 1 To 6 Step 1
    'sn = sn & (Val(Mid(base, i, 1)) + Asc(Mid(name, i, 1)))
    sn = sn & ((i + 1) + Asc(Mid(name, i, 1)))
  Next i
  
  n = Len(sn)
  If n < 12 Then
    sn = String(12 - n, "0") & sn
  End If
  If n > 12 Then
    sn = Left(sn, 12)
  End If
  
  Sheet1.Cells(5, 4) = sn
  
  Range("D5").Select
  Selection.Copy '可能有回车符的问题,复制出去的字符串后面带有隐藏的 vbCrLf,需要手动删除这2个不可见字符。
  
End Sub




并在 Excel 中做一个界面,如下图所示:
keygen_ui.png


计算序列号并输入 CrackMe,如下:
11.png
点 "register",得到:
12.png

另外,如果用 OD 进行动态跟踪,核对算法的话,CrackMe 中有一个定时器事件,其代码会引发浮点精度的异常,当OD会断下来时,用 Shift+F9 忽略就可以了,就不会再对调试过程产生干扰了。
完毕!!!
FS丶yongye 发表于 2019-7-3 14:37
wenxue1994 发表于 2019-7-3 15:22
pk8900 发表于 2019-7-4 12:17
楼主加油,看来我以前没弄明白的可以一个一个的弄明白了。
飘飘Casey 发表于 2020-3-25 21:53
亲,我有个P-code 文件,有偿求高人破解,请联系rainrui15@gmail.com
fenghl 发表于 2020-8-6 22:18
大佬求助,怎么分析出Run-time error '70'的错误位置的,可以判断出问题出在 Proc_1_7_404720调用,但是对应在这个函数内部的0X004046DA处是怎么测试出来的呢
 楼主| solly 发表于 2020-8-6 22:30
fenghl 发表于 2020-8-6 22:18
大佬求助,怎么分析出Run-time error '70'的错误位置的,可以判断出问题出在 Proc_1_7_404720调用,但是对 ...

执行打开文件操作时,VB运行库会报错。
fenghl 发表于 2020-8-6 22:39
solly 发表于 2020-8-6 22:30
执行打开文件操作时,VB运行库会报错。

谢谢大佬回复,我是小菜,在点击check时报错,报错后查看调用和堆栈,啥都没看出来,大佬怎么定位到导致错误发生的地址的,是在函数内部用断点测试么,还是有好办法呢。
 楼主| solly 发表于 2020-8-6 23:23
fenghl 发表于 2020-8-6 22:39
谢谢大佬回复,我是小菜,在点击check时报错,报错后查看调用和堆栈,啥都没看出来,大佬怎么定位到导致 ...

在 vb decompiler 中找到事件函数,在od中下断点,F8或F7一步步找。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 18:24

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表