吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 10266|回复: 20
上一主题 下一主题
收起左侧

[原创] VB5&6程序整理还原代码总结 例程:[反汇编练习] 160个CrackMe之064(execut...

  [复制链接]
跳转到指定楼层
楼主
pk8900 发表于 2017-12-31 15:00 回帖奖励
本帖最后由 pk8900 于 2017-12-31 18:56 编辑


【引言】最近一直进行[反汇编练习] 160个CrackMe的破解练习,发现其中有一大部分的VB5&6程序,在对这些程序练习的基础上总结了一个方法,分享给大家,有不对的地方还请大神指出。此方法前提是借助VB反编译软件VB Decompiler的分析结果,在此基础上对反编译的伪VB代码进行整理还原。选的这个CrackMe程序比较简单,方便我对此方法的讲解,使用此方法可能要求你懂一点VB或VBscript编程基础知识。
【适用对象】VB5&6程序,Native Code编码方式(动态调试方便),P-CODE编码方式(调试麻烦)
【工具软件】VB Decompiler、NotePad++、X64DBG(OD也可)、 Visual Basic 6.0
【例程】下载地址:http://pan.baidu.com/share/link?shareid=541269&uk=4146939145
【步骤一】获取程序反编译VB伪代码,找到关键代码部分, 例程:160个CrackMe之064(execution),VB Decompiler反编译,界面如下:

代码部分共三部分:
Code -> Form1 -> Command1_Click_40D8F0   -->关键代码,Register按钮事件。
Code -> Form1 -> About_Click_40D780    -->About对话框事件。
Code -> Form1 -> Exit_Click_40DCE0    -->关闭窗体事件。
这里的Command1_Click事件就是我们要寻找的关键代码,也有很多程序会在Text_OnChange事件里写代码,我们也必须关注。

【步骤二】代码还原下面我们就对这段Command1_Click事件代码进行整理还原。
将Command1_Click代码复制到NotePad++中,在NotePad++语言菜单中选择VB,之所以用NotePad++整理,是因为NotePad++中,你选择的部分NotePad++会自动匹配并高亮显示,这个功能很关键。如下图:

我双击选择了var_18,代码中引用的var_18都会自动高亮突出显示,你可以看到这些变量的引用情况。接下来对代码进行整理,反编译的VB伪代码为:
[Visual Basic] 纯文本查看 复制代码
Private Sub Command1_Click() '40D8F0
  loc_0040D930: var_eax = arg_8.AddRef 'Ignore this
  loc_0040D957: var_eax = Form1.Text1 'Ignore this
  loc_0040D965: var_3C = Form1.Text1 'Ignore this
  loc_0040D96F: var_54 = Ucase(Form1.Text1 'Ignore this)
  loc_0040D98A: var_28 = var_54
  loc_0040D996: call undef 'Ignore this '__vbaFreeVarList(00000002, 9, var_54, arg_8, edi, ebx, %ecx = %S_edx_S)
  loc_0040D9B1: var_B8 = Len(var_28)
  loc_0040D9C3: If 00000001h > 0 Then GoTo loc_0040DB03
  loc_0040D9D2: var_7C = var_28
  loc_0040D9FA: var_54 = Mid(var_28, si, 1)
  loc_0040DA0F: var_18 = var_54
  loc_0040DA1B: call undef 'Ignore this '__vbaFreeVarList(00000002, 2, var_54)
  loc_0040DA2E: Asc(var_18) = Asc(var_18) - 0040h
  loc_0040DA32: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DA38: Asc(var_18) = Asc(var_18) * 0082h
  loc_0040DA3D: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DA43: Asc(var_18) = Asc(var_18) + di
  loc_0040DA46: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DA4C: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DA50: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DA56: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DA5A: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DA60: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DA64: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DA6A: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DA6E: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DA74: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DA78: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DA7E: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DA82: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DA88: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DA8C: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DA92: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DA96: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DA9C: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DAA0: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DAA6: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DAAA: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DAB0: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DAB4: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DABA: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DABE: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DAC4: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DAC8: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DACE: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DAD2: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DAD8: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DADC: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DAE2: Asc(var_18) = Asc(var_18) + 0050h
  loc_0040DAE6: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DAF3: 00000001h = 00000001h + si
  loc_0040DAF6: If Err.Number <> 0 Then GoTo loc_0040DCD9
  loc_0040DAFE: GoTo loc_0040D9BC
  loc_0040DB03: 'Referenced from: 0040D9C3
  loc_0040DB09: var_eax = Form1.Text2 'Ignore this
  loc_0040DB23: var_2C = Text2.Text
  loc_0040DB44: call var_40F0E8(Asc(var_18), var_2C, arg_8)
  loc_0040DB4F: var_30 = var_40F0E8(Asc(var_18), var_2C, arg_8)
  loc_0040DB65: esi = ( = var_30) + 1
  loc_0040DB9C: If ( = var_30) + 1 = 0 Then GoTo loc_0040DBFC
  loc_0040DBBF: var_3C = "Nice Going!!! you Cracked the CrackMe!" & "vbCrLf" & "Contact HackerG or DEATH to get your Present..."
  loc_0040DBFA: GoTo loc_0040DC58
  loc_0040DBFC: 'Referenced from: 0040DB9C
  loc_0040DC20: var_3C = "You Lamer!!! Cant Crack This?!" & "vbCrLf" & "Try Again..."
  loc_0040DC58: 'Referenced from: 0040DBFA
  loc_0040DC5A: call undef 'Ignore this '__vbaFreeVarList(00000004, var_44, var_54, var_64, var_74, var_44, var_54, var_64, var_74)
  loc_0040DC6F: GoTo loc_0040DCA9
  loc_0040DC9F: call undef 'Ignore this '__vbaFreeVarList(00000004, var_44, var_54, var_64, var_74)
  loc_0040DCA8: Exit Sub
  loc_0040DCA9: 'Referenced from: 0040DC6F
  loc_0040DCB7: GoTo loc_00esi
End Sub

下面进行整理,具体的过程,参照下图:



【步骤三】VB调试:
上面两个整理过程,可能看起来有些乱,我想只要专注,应该可以看得懂。经过上面步骤,代码已经被整理的差不多了,接下来,打开 VB,新建一个EXE工程,添加两个文本框,一个按钮,在按钮事件中将代码贴入,对代码进行调试修改,发现计算器si初值未确定,加入si = 1,最终修改如下:
[Visual Basic] 纯文本查看 复制代码
Private Sub Command1_Click() '40D8F0
loc_0040D98A:   var_28 = UCase(Form1.Text1.Text)
loc_0040D9B1:   var_B8 = Len(var_28)
 loc_0040D9B2:    si = 1   '加入循环变量的初始值:1
loc_0040D9BC:
loc_0040D9C3:   If si > var_B8 Then GoTo loc_0040DB03
loc_0040D9D2:   var_7C = var_28
loc_0040D9FA:   var_54 = Mid(var_28, si, 1)
loc_0040DA0F:   var_18 = Asc(var_54)
loc_0040DA2E:   var_18 = var_18 - &H40
loc_0040DA32:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DA38:   var_18 = var_18 * &H82
loc_0040DA3D:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DA43:   var_18 = var_18 + di
loc_0040DA46:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DA4C:   var_18 = var_18 + &H50
loc_0040DA50:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DA56:   var_18 = var_18 + &H50
loc_0040DA5A:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DA60:   var_18 = var_18 + &H50
loc_0040DA64:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DA6A:   var_18 = var_18 + &H50
loc_0040DA6E:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DA74:   var_18 = var_18 + &H50
loc_0040DA78:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DA7E:   var_18 = var_18 + &H50
loc_0040DA82:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DA88:   var_18 = var_18 + &H50
loc_0040DA8C:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DA92:   var_18 = var_18 + &H50
loc_0040DA96:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DA9C:   var_18 = var_18 + &H50
loc_0040DAA0:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DAA6:   var_18 = var_18 + &H50
loc_0040DAAA:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DAB0:   var_18 = var_18 + &H50
loc_0040DAB4:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DABA:   var_18 = var_18 + &H50
loc_0040DABE:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DAC4:   var_18 = var_18 + &H50
loc_0040DAC8:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DACE:   var_18 = var_18 + &H50
loc_0040DAD2:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DAD8:   var_18 = var_18 + &H50
loc_0040DADC:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DAE2:   var_18 = var_18 + &H50
loc_0040DAE6:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DAF3:   si = si + 1
                           di = var_18   '伪代码中漏掉的,补上
loc_0040DAF6:   If Err.Number <> 0 Then GoTo loc_0040DCD9
loc_0040DAFE:   GoTo loc_0040D9BC
loc_0040DB03:   'Referenced from: 0040D9C3
loc_0040DB09:   'Ignore this
loc_0040DB23:   var_2C = Text2.Text
loc_0040DB44:   Text2.Text = CStr(di)    '加入这一句代码实现正确注册码的显示
loc_0040DB9C:   If var_2C <> CStr(di) Then GoTo loc_0040DBFC
loc_0040DBBF:   MsgBox "Nice Going!!! you Cracked the CrackMe!" & "vbCrLf" & "Contact HackerG or DEATH to get your Present..."
loc_0040DBFA:   GoTo loc_0040DC58
loc_0040DBFC:   'Referenced from: 0040DB9C
loc_0040DC20:   MsgBox "You Lamer!!! Cant Crack This?!" & "vbCrLf" & "Try Again..."
loc_0040DC58:   'Referenced from: 0040DBFA
loc_0040DCD9:
loc_0040DCA8:   Exit Sub
loc_0040DCA9:   'Referenced from: 0040DC6F
End Sub

经过在VB中的调试结果和原程序在X64DBG中的调试,代码中加入了两句:       
[Visual Basic] 纯文本查看 复制代码
 loc_0040D9B2:    si = 1   '加入循环变量的初始值:1
loc_0040DB44:   Text2.Text = CStr(di)    '加入这一句代码实现真正注册码的显示

实现了注册机的功能。VB中调试可以打开VB的监控窗口,将变量拖入,在代码上下断点,就可以观察变量值的变化了。
代码在VB6.0中运行并中断截图:

160个CrackMe之064(execution):用户名:52pojie.cn  注册码:16570,成功破解。
接下来说一下:for 循环代码的整理过程,程序为:160个CrackMe之059 (Eternal Bliss .02 .exe),伪代码为:
[Visual Basic] 纯文本查看 复制代码
402E34: For var_2C = 1 To 5 Step 1
  loc_00402E39: var_220 = var_2C
  loc_00402E3F: GoTo loc_00402FB9
  loc_00402E44: 
  loc_00402E4C: var_eax = Form1.Text1 'Ignore this
  loc_00402E7A: var_E0 = Text1.Text
  loc_00402E82: var_168 = var_E0
  loc_00402ED5: var_224 = var_E0
  loc_00402EE8: var_F0 = var_224
  loc_00402F17: var_118 = Mid(var_224, CLng(var_2C), 1)
  loc_00402F2A: var_E4 = CStr(var_118)
  loc_00402F35: var_140 = Asc(var_E4)
  loc_00402F62: var_7C = var_7C & Asc(var_E4)
  loc_00402F78: var_eax = %fobj
  loc_00402F94: call undef 'Ignore this '__vbaFreeVarList(00000003, 8, 2, var_118, arg_8, arg_8, arg_8, 00000001h, edi, esi, ebx)
  loc_00402FAE: Next var_2C
  loc_00402FB3: var_220 = Next var_2C
  loc_00402FB9: 'Referenced from: 00402E3F
  loc_00402FC0: If var_220 <> 0 Then GoTo loc_00402E44
  loc_00402FEF: var_E4 = CStr(var_4C & var_6C)
  loc_00403026: If Err.Number <> 0 Then GoTo loc_004043E9
  loc_00403042: var_DC = (Val(CStr(var_7C)) - var_160)

整理方法见下图:

经过整理:代码如下
[Visual Basic] 纯文本查看 复制代码
402E34:         For var_2C = 1 To 5 Step 1
                var_224=Text1.Text
  loc_00402F17: var_118 = Mid(var_224, CLng(var_2C), 1)
  loc_00402F2A: var_E4 = CStr(var_118)
  loc_00402F62: var_7C = var_7C & Asc(var_E4)
  loc_00402FAE: Next var_2C   '循环最终的结果值为:var_7C

【总结】
0x01:VB Decompiler反编译代码中有些常量值操作会被漏掉,需要查看汇编代码。
0x02:VB 的变量值经常通过中间变量来转化和赋值,造成反编译中变量被换了名字,可联系上下文,将换了名字的变量对上号。
0x03:伪代码中的十六进制常量:如 0050h,应整理更正为: &H50
0x04:伪代码中的var_7C,汇编中一般为EBP-7C,因VB数据结构的特殊性,真正var_7C的值大部分时候是EBP-70堆栈地址的值,代码中的:arg_8即汇编中的ESP+8。而EAX。ESI等就不用说了,也是汇编中的寄存器。
0x05:VB程序中有大多数据类型可自动进行转化,所以本例中伪代码: Asc(var_18) = Asc(var_18) + 0050h 应整理为:var_18 = var_18 + &H50
0x06:对于复杂的程序,可将跳转的行号用字符串替换,使代码流程更清晰。
0x07:动态分析时,可以将VB Decompiler的代码用我以前写的一个小工具转为MAP文件导入调试器中,帖子地址:https://www.52pojie.cn/thread-668710-1-1.html,方便对照。
以上就是我最近一段时间对VB程序进行伪代码整理分析的一点心得,供坛友借鉴,明天就是2018年了,写这篇帖子算是总结一下自己的心得吧,祝坛友2018年Crack水平日进。No failed.  Only Success!

免费评分

参与人数 6吾爱币 +12 热心值 +6 展开 理由
203156 + 1 + 1 楼主能吧 160carkme 分享下么? 论坛里能找到的 链接都挂了 万分感激
Poner + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
boyving + 2 + 1 我很赞同!
xgameboy + 1 + 1 热心回复!
Allyn0303 + 1 + 1 谢谢@Thanks!
kk1212 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

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

推荐
 楼主| pk8900 发表于 2018-1-9 14:39 |楼主
203156 发表于 2018-1-9 14:21
楼主能吧 160carkme 分享下么?  论坛里能找到的  链接都挂了  万分感激

下载地址:http://pan.baidu.com/share/link?shareid=541269&uk=4146939145,帖子顶部的能打开下载啊
推荐
田配 发表于 2018-1-1 23:24
学习了。                                   
沙发
lovejingqing 发表于 2017-12-31 15:33
3#
羊毛丶 发表于 2017-12-31 16:19
谢谢分享
4#
海盗小K 发表于 2017-12-31 16:30
感谢分享心得。
5#
kk1212 发表于 2017-12-31 18:16
CrackMe非常难得的练习资源
6#
a1069517910 发表于 2017-12-31 20:02
感谢楼主分享!!
7#
YINGDOBI 发表于 2018-1-1 10:39
感谢楼主分享
8#
xcr23 发表于 2018-1-1 12:08
看上去蛮深奥的
9#
yukestudy 发表于 2018-1-1 14:39
不错,学习了
10#
burnda 发表于 2018-1-1 15:18
VB虽然老古董,当是我还在用。。。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-12-22 15:54

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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