零基础VB6无壳P-CODE逆向分析(VB Decompiler应用与避坑)

> 前言

最近从朋友那里拿到了一个加密狗授权的软件安装包,秉承着LCG的精神,开启了逆向之路,经过查壳和综合分析确定是VB6编写的程序(这年头使用VB6开发商业程序的还真少见),作为一名C# Winform的业余程序员,靠着C#的知识勉强分析个大概.

> 授权简介

软件共分三种授权模式:
1.账号密码模式:免费,但功能有限制
2.硬盘绑定模式:收费,绑定电脑硬盘ID
3.加密狗模式:插着加密狗就可以使用
经过对程序代码分析,软件是在编译前通过更改内部变量标志位实现不同授权模式,并且编译后只能识别对应的授权模式

所需工具

这里是引用

1.VB Decompiler 11 (爱盘里面下载)
2.文本批量查找工具

源程序

aHR0cHM6Ly93d3cuMTIzcGFuLmNvbS9zL1FMaVJWdi00WHZoaA==

分析过程[由浅入深,正向推进]
分析软件结构
1.安装软件,并打开安装目录
通过编译时间和经验筛选,除软件主程序外,只有
FT_ET299_API.dll
FD181.dll
RCGrandDogW32.dll
三种加密狗的库,具体用的是哪一种,后文会有分析过程

设置VB Decompiler参数

1.这个软件不能在WIN10系统上运行,解析不出来code段代码,我用的是WIN7的虚拟机.
2.打开VB Decompiler,按F11(或者菜单栏工具→选项),设置完成后保存,重启软件
在这里插入图片描述

逆向分析1 验证窗口的来源(正向推进)

1.打开软件,弹出登录界面/验证界面(因为我获得了加密狗版的安装包,所以知道不同的软件界面,这个是后话)
2.记住这个登录界面,我们打开VB Decompiler,导入软件的主程序,并反编译.
3.在树形分支窗口中在forms里面找到刚才的界面(frmlogin)
4.CTRL+S(菜单栏文件→保存反编译的项目),将反编译的内容保存在单独的文件夹里面.
5.使用文本批量查找工具,在刚刚保存的目录下查找"frmlogin"
通过查找定位可找到frmmain.frm和frmzc.frm两个调用了这个登录界面.
6.通过具体跟进代码,发现在frmmain的Form_Load窗体加载事件中调用了这个窗体的显示

NewIfNullPr frmlogin 'Ignore this
frmlogin.Show var_C8, var_D8

通过上下文代码内容得知:

var_98 = "软件启动检测"var_F6 = 1If (var_F6 = 1) Thenvar_88 = "NET"ElseIf (var_F6 = 2) Thenvar_88 = "HDD"ElseIf (var_F6 = 3) Thenvar_88 = "DOG"End IfEnd IfEnd If
通过对var_F6的赋值来决定模式,但是经过上下文跟进和实际测试这个只会影响软件各窗口标题内容
7.继续对上下文代码分析复制代码 隐藏代码loc_66AB02: var_98 = "软件验证"loc_66AB0B: Call Proc_42_11_585008(var_B0)var_98 = "软件验证"Call Proc_42_11_585008(var_B0)MemVar_6AF114 = CStr(var_B0)var_B0 = "" 'Ignore thisIf &HFF Then         //这个值是那里来的,望VB的程序员帮忙解答一下,这个直接决定软件授权验证窗口的类型(授权模式)var_D8 = CVar(Me) 'AddressPopAdLdVar 'Ignore thisvar_C8 = 1PopAdLdVar 'Ignore thisNewIfNullPr frmlogin 'Ignore thisfrmlogin.Show var_C8, var_D8              //免费版网络验证窗口ElseIf 0 ThenProc_30_2_56F550(var_B0)Proc_30_4_56DE7C(var_B0)var_B0 = "" 'Ignore thisIf (MemVar_6AFF20 = vbNullString) ThenNewIfNullPr Me 'Ignore thisvar_9C = Me.Global.Appvar_B4 = "" 'Ignore thisvar_9C = vbNull 'Ignore thisvar_B0 = "" 'Ignore thisIf (Dir(CVar(App.Path & "\sn.bmp"), 0) <> vbNullString) ThenPopAdLdVar 'Ignore thisPopAdLdVar 'Ignore thisPopAdLdVar 'Ignore thisPopAdLdVar 'Ignore thisNewIfNullPr Me 'Ignore thisvar_9C = Me.Global.AppPopAdLdVar 'Ignore thisNewIfNullPr Me 'Ignore thisMe.Global.LoadPicture CVar(App.Path & "\sn.bmp"), var_C8, var_D8, var_164, var_184Me.picSn.Picture = var_188var_B4 = "" 'Ignore thisvar_9C = "":   var_18C = "" 'Ignore thisvar_B0 = "" 'Ignore thisMemVar_6AFF34 = Call Proc_60_5_57F48C(Proc_59_1_58D9AC(Me.picSn), "F1DD7CDB1328DB1E")     //modRij对称加密程序处理部分var_B4 = "" 'Ignore thisvar_9C = vbNull 'Ignore thisvar_B4 = "" 'Ignore thisvar_B0 = "" 'Ignore thisMemVar_6AFF20 = Split(MemVar_6AFF34 & "||||||||||||||||||||||||||||||||||||||||||||||||", "|", -1, 0)(0)End IfEnd IfIf (Proc_30_12_5968F0(MemVar_6AFF34) = 0) Then     //盲猜应该是硬盘绑定授权模式的验证PopAdLdVar 'Ignore thisPopAdLdVar 'Ignore thisNewIfNullPr frmzc 'Ignore thisfrmzc.Show 1, CVar(Me)End IfIf 0 ThenIf (Proc_30_1_5A0AA4(var_188) = 0) ThenIf (Proc_30_1_5A0AA4(MemVar_6AF114) = 0) Then    //经过跟进分析应该是加密狗授权模式的验证PopAdLdVar 'Ignore thisPopAdLdVar 'Ignore thisNewIfNullPr frmzc 'Ignore thisfrmzc.Show 1, CVar(Me)End IfEnd IfSet var_9C = Me.picsqMe.picsq(0).Picture = Me(2).Picturevar_9C = "":   var_188 = "":   var_190 = "":   var_19C = "" 'Ignore thisElseIf (Proc_30_1_5A0AA4("Times New Roman") = 0) ThenPopAdLdVar 'Ignore thisPopAdLdVar 'Ignore thisNewIfNullPr frmzc 'Ignore thisfrmzc.Show 1, CVar(Me)End IfSet var_9C = Me.picsqMe.picsq(0).Picture = Me(1).Picturevar_9C = "":     var_188 = "":     var_190 = "":     var_19C = "" 'Ignore thisEnd IfEnd IfEnd If

经过以上的分析,没有获得什么有价值的线索,忽略

逆向分析2 通过机器码文本跟进(正向推进) 在账号密码验证模式下左下角有一个机器码文本,点进去之后可以生成机器码. 1.我们在VB Decompiler 的forms分支找到frmlogin,查看这个文本的空间名(Lable1),然后到code分支找到Lable1.Click事件的代码

2.代码内容:

NewIfNullPr frmGetZCHao 'Ignore thisfrmGetZCHao.Show 1, CVar(Me)

这样我们就知道生成机器码的窗口是frmGetZCHao[Get注册号]

3.继续在forms分支找到这个窗口 得知下拉框控件名Combo1,文本框Text1 跳转到Code分支的frmGetZCHao代码段 在Form_Load加载事件中

   For var_A8 = 0 To 3:   var_86 = var_A8 'IntegerNewIfNullPr clsdno 'Ignore thisvar_8C.CurrentDrive = CByte(var_86)          //获取硬盘名NewIfNullPr clsdno 'Ignore thisvar_94 = var_8C.GetSerialNumber()          //获取硬盘序列号If (var_94 <> vbNullString) ThenPopAdLdVar 'Ignore thisNewIfNullPr clsdno 'Ignore thisMe.Combo1.AddItem var_8C.GetModelNumber(), var_A4   //将硬盘模块号添加到下拉列表中var_94 = "" 'Ignore thisvar_90 = vbNull 'Ignore thisElsePopAdLdVar 'Ignore thisMe.Combo1.AddItem Call Proc_42_6_57E0AC("Msg_DiskUnAble"), var_A4var_94 = "" 'Ignore thisvar_90 = vbNull 'Ignore thisEnd IfNext var_A8 'Integer
在Combo1_Click点击事件方法中复制代码 隐藏代码If CBool((Left(var_88, 3) <> "ERR") And (Len(var_88) = &H10)) Thenvar_B4 = CVar(Call Proc_60_4_583C44("UsbDogFD181" & "<r>" & var_88 & "<r>", "F1DD7CDB1328DB1E")) 'String    //初步判断是FD181加密狗Call Proc_88_0_5C2170(var_E4)var_88 = CStr(var_E4)var_A0 = "": var_A4 = "" 'Ignore thisvar_B4 = "" 'Ignore thisElseIf (var_88 = "ERR:open") Thenvar_88 = Call Proc_42_6_57E0AC("Err_Dog_Open")End IfEnd If复制代码 隐藏代码If (var_A0 <> vbNullString) ThenNewIfNullPr clsdno 'Ignore thisNewIfNullPr clsdno 'Ignore thisvar_B4 = CVar(Call Proc_60_4_583C44(var_94.GetModelNumber() & "<r>" & var_94.GetSerialNumber() & "<r>" & CStr(CLng(var_B4)) & "<r>", "F1DD7CDB1328DB1E")) 'String   //对获取到的硬盘信息进行加密,这个值在下面的代码会赋值到Text1文本框中Call Proc_88_0_5C2170(var_E4)var_88 = CStr(var_E4)var_A0 = "":   var_108 = "":   var_A4 = "":   var_10C = "":   var_110 = "":   var_114 = "":   var_118 = "" 'Ignore thisvar_B4 = "" 'Ignore thisElsevar_88 = "NoDiseAvailable"End If
4.通过跟进Proc_60_4_583C44可知是modRij对称加密类逆向分析3 通过加密狗导入函数库跟进(正向推进)
1.通过IDA PRO对三个加密狗API文件进行分析导出表,可获得参数头文件和数据类型,利用文本查找工具定位到frmmain的code段中有加载外部DLL文件的函数复制代码 隐藏代码
Private Declare Sub et_AdjustTimer Lib "ft_et299_api"()
'VA: 4EC034
Private Declare Sub et_GetTimeLicense Lib "ft_et299_api"()
'VA: 4EBFE8
Private Declare Sub et_SetTimeLicense Lib "ft_et299_api"()
'VA: 4EBF9C
Private Declare Sub et_GetCountLicense Lib "ft_et299_api"()
'VA: 4EBF50
Private Declare Sub et_SetCountLicense Lib "ft_et299_api"()
'VA: 4EBF04
Private Declare Sub et_RSAPrivateDecrypt Lib "ft_et299_api"()
'VA: 4EBEB4
Private Declare Sub et_RSAPrivateEncrypt Lib "ft_et299_api"()
'VA: 4EBE58
Private Declare Sub et_RSAPublicDecrypt Lib "ft_et299_api"()
'VA: 4EBE0C
Private Declare Sub et_RSAPublicEncrypt Lib "ft_et299_api"()
'VA: 4EBDC0
Private Declare Sub et_RSASetKey Lib "ft_et299_api"()
'VA: 4EBD78
Private Declare Sub et_RSAGenKey Lib "ft_et299_api"()
'VA: 4EBD30
Private Declare Sub et_TDesDecrypt Lib "ft_et299_api"()
'VA: 4EBCE8
Private Declare Sub et_TDesEncrypt Lib "ft_et299_api"()
'VA: 4EBCB4
Private Declare Sub et_SetKeyEx Lib "ft_et299_api"()
'VA: 4EBC70
Private Declare Sub MD5_HMAC Lib "ft_et299_api"()
'VA: 4EBC2C
Private Declare Sub et_HMAC_MD5 Lib "ft_et299_api"()
'VA: 4EBBE8
Private Declare Sub et_SetKey Lib "ft_et299_api"()
'VA: 4EBBA4
Private Declare Sub et_GetSNEx Lib "ft_et299_api"()
'VA: 4EBB60
Private Declare Sub et_SetSNEx Lib "ft_et299_api"()
'VA: 4EBB1C
Private Declare Sub et_GetSN Lib "ft_et299_api"()
'VA: 4EBAC0
Private Declare Sub et_TurnOffLED Lib "ft_et299_api"()
'VA: 4EBA78
Private Declare Sub et_TurnOnLED Lib "ft_et299_api"()
'VA: 4EBA30
Private Declare Sub et_GenRandom Lib "ft_et299_api"()
'VA: 4EB9E8
Private Declare Sub et_ResetSecurityState Lib "ft_et299_api"()
'VA: 4EB998
Private Declare Sub et_SetupToken Lib "ft_et299_api"()
'VA: 4EB950
Private Declare Sub et_ChangeUserPIN Lib "ft_et299_api"()
'VA: 4EB918
Private Declare Sub et_ResetPIN Lib "ft_et299_api"()
'VA: 4EB8D4
Private Declare Sub et_GenSOPIN Lib "ft_et299_api"()
'VA: 4EB890
Private Declare Sub et_Verify Lib "ft_et299_api"()
'VA: 4EB84C
Private Declare Sub et_GenPID Lib "ft_et299_api"()
'VA: 4EB808
Private Declare Sub et_Write Lib "ft_et299_api"()
'VA: 4EB7C4
Private Declare Sub et_Read Lib "ft_et299_api"()
'VA: 4EB784
Private Declare Sub et_CloseToken Lib "ft_et299_api"()
'VA: 4EB72C
Private Declare Sub et_OpenToken Lib "ft_et299_api"()
'VA: 4EB6E4
Private Declare Sub et_FindToken Lib "ft_et299_api"()
'VA: 4EB5C0
Private Declare Sub FD181ChkCalc Lib "fd181"()
'VA: 4EB560
Private Declare Sub FD181GetRand Lib "fd181"()
'VA: 4EB518
Private Declare Sub FD181CloseDev Lib "fd181"()
'VA: 4EB4D0
Private Declare Sub FD181SetPID Lib "fd181"()
'VA: 4EB48C
Private Declare Sub FD181GetPID Lib "fd181"()
'VA: 4EB448
Private Declare Sub FD181SetDispInfo Lib "fd181"()
'VA: 4EB3FC
Private Declare Sub FD181GetAuthorityData Lib "fd181"()
'VA: 4EB3C0
Private Declare Sub FD181SetAuthorityData Lib "fd181"()
'VA: 4EB370
Private Declare Sub FD181SetUserPassword Lib "fd181"()
'VA: 4EB320
Private Declare Sub FD181SetSuperPassword Lib "fd181"()
'VA: 4EB2D0
Private Declare Sub FD181VerifyUserPassword Lib "fd181"()
'VA: 4EB280
Private Declare Sub FD181VerifySuperPassword Lib "fd181"()
'VA: 4EB22C
Private Declare Sub FD181GetDID Lib "fd181"()
'VA: 4EB1C8
Private Declare Sub FD181LedClose Lib "fd181"()
'VA: 4EB180
Private Declare Sub FD181LedOpen Lib "fd181"()
'VA: 4EB138
Private Declare Sub FD181DevRead Lib "fd181"()
'VA: 4EB0F0
Private Declare Sub FD181DevWrite Lib "fd181"()
'VA: 4EB0A8
Private Declare Sub FD181OpenDev Lib "fd181"()
'VA: 4EB060
Private Declare Sub FD181FindDev Lib "fd181"()
'VA: 4EAF28
Private Declare Sub rc_GetLicenseInfo Lib "rcgranddogw32"()
'VA: 4EAEDC
Private Declare Sub rc_Upgrade Lib "rcgranddogw32"()
'VA: 4EAE98
Private Declare Sub rc_GetUpgradeRequestString Lib "rcgranddogw32"()
'VA: 4EAE44
Private Declare Sub rc_ExecuteFile Lib "rcgranddogw32"()
'VA: 4EADFC
Private Declare Sub rc_DefragFileSystem Lib "rcgranddogw32"()
'VA: 4EADB0
Private Declare Sub rc_VisitLicenseFile Lib "rcgranddogw32"()
'VA: 4EAD64
Private Declare Sub rc_DeleteDir Lib "rcgranddogw32"()
'VA: 4EAD1C
Private Declare Sub rc_DeleteFile Lib "rcgranddogw32"()
'VA: 4EACD4
Private Declare Sub rc_WriteFile Lib "rcgranddogw32"()
'VA: 4EAC6C
Private Declare Sub rc_ReadFile Lib "rcgranddogw32"()
'VA: 4EAC28
Private Declare Sub rc_CreateFile Lib "rcgranddogw32"()
'VA: 4EABE0
Private Declare Sub rc_CreateDir Lib "rcgranddogw32"()
'VA: 4EAB98
Private Declare Sub rc_GetRandom Lib "rcgranddogw32"()
'VA: 4EAB50
Private Declare Sub rc_ConvertData Lib "rcgranddogw32"()
'VA: 4EAB08
Private Declare Sub rc_SignData Lib "rcgranddogw32"()
'VA: 4EAAA8
Private Declare Sub rc_DecryptData Lib "rcgranddogw32"()
'VA: 4EAA60
Private Declare Sub rc_EncryptData Lib "rcgranddogw32"()
'VA: 4EAA18
Private Declare Sub rc_SetKey Lib "rcgranddogw32"()
'VA: 4EA9D4
Private Declare Sub rc_ChangePassword Lib "rcgranddogw32"()
'VA: 4EA988
Private Declare Sub rc_VerifyPassword Lib "rcgranddogw32"()
'VA: 4EA93C
Private Declare Sub rc_CheckDog Lib "rcgranddogw32"()
'VA: 4EA8E4
Private Declare Sub rc_GetDogInfo Lib "rcgranddogw32"()
'VA: 4EA89C
Private Declare Sub rc_GetProductCurrentNo Lib "rcgranddogw32"()
'VA: 4EA84C
Private Declare Sub rc_OpenDog Lib "rcgranddogw32"()
'VA: 4EA5A8
Private Declare Sub rc_CloseDog Lib "rcgranddogw32"()
'VA: 4EA494

然后根据加密狗常规函数调用经验,使用文本批量查找工具对以上函数名进行查找.
常规加密狗验证,首先要查找设备,打开设备,读取数据,为了高效我们只定位以上几个关键API.

2.示例:

比如我们查找rc_OpenDog,这个是和狗建立连接,我们在所有代码中搜索,定位到modReg.bas文件的Proc_30_13_5EBBF4方法中,然后我们再搜索Proc_30_13_5EBBF4,发现这个子方法并没有被任何程序调用,所以我们就可以软件中并不是使用这个加密狗模块.

3.最后通过排除法最终确定通过搜索FD181OpenDev,定位到了

modfd181.bas文件中的Proc_79_9_573054方法
所以我们确定在VB Decompiler中code段的modfd181类中就是处理加密狗数据的代码内容了

整理笔记1

frmmain的Form_Load负责弹窗/验证授权
frmlogin是免费版网络验证窗口
frmzc是硬盘版授权&加密狗授权验证窗口
frmGetZCHao是生成加密硬盘ID的窗口(生成注册号)
ModRij是调用对称加密解密的模块 Proc_60前缀标志
modFD181是加密狗通信模块 Proc_79前缀标志

第一阶段总结

主框架的核心代码段分布已经完成,找到了主要的分析节点,接下来就是继续深入解析,并找到关键点
在不更改源程序的情况下只有两种过验证的方法
1.通过生成硬盘绑定模式的注册信息来实现正版验证
技术要点:将软件改为硬盘版(需要改代码),通过分析验证过程来伪造验证文件.[具体验证文件是什么还需深入分析]
2.通过伪造加密狗来实现验证(需要改代码,因为我已经有了加密狗版的安装程序,所以优先考虑这种方法)
技术要点:需要C++编写FD181.dll文件,补齐所有头文件
3.网络验证本身就是功能受限,所以不考虑
那么接下来的工作就是分析代码了

分析过程[由深到浅,逆向推进]
加密狗验证逆向推进

1.首先工具中(VB Decompiler,以下简称工具),code段定位到modFD181类的Proc_79子方法组,选中子方法并在每个子方法右键,选择查看引用(Find references),如果没有弹出窗口就说明这个子方法没有被使用过,最后结果为:

Proc_79_9
Proc_79_10
Proc_79_13
Proc_79_16

共4个子方法被调用过,而且均指向Proc_30_15,
双击后跳转到modReg的Proc_30_15方法,所以可以确定modReg类就是软件验证的类,重点关注!

Proc_79_9分析:将传入的16位String转成byte数组并传给FD181OpenDev来获取返回值,
通过官方资料SDK资料
aHR0cHM6Ly93d3cudGFvZG9jcy5jb20vcC00OTY5OTA0ODIuaHRtbA==
返回handle(大于0的整数/指针)
Proc_79_10分析:效验密码,具体略
Proc_79_13分析:FD181GetDID:获取设备编号
Proc_79_16:FD181DevRead:读取数据
2.我们转到Proc_30_15,具体分析加密狗数据交互流程(需参考以上四个子方法)

Private Sub Proc_30_15_59651C'Data Table: 4979BCDim var_A8 As LongDim var_CC As VariantPopAdLdVar 'Ignore thisvar_A8 = Proc_79_9_573054(CVar("F92DB2AFE056B4B5"))   //获取设备指针,大于0If (var_A8 < 1) Thenvar_8C = "ERR:open"Elsevar_98 = Call Proc_79_13_56DD84(var_A8)    //返回加密狗IDIf (var_98 = vbNullString) Thenvar_8C = "ERR:GetDID"Elsevar_98 = CStr(Left(CVar(Call Proc_28_24_62E754(var_98)), &H10))    //返回MD5后的设备IDvar_E0 = "" 'Ignore thisvar_CC = "" 'Ignore thisCall Proc_79_10_57DE04(var_CC, var_A8, var_98)  //效验密码var_CC = "" 'Ignore thisIf (CLng(var_CC) < 0) Thenvar_8C = "ERR:password"Elsevar_A4 = Call Proc_79_16_576E3C(var_A8, 1, &H24)  //读取加密狗数据,36位If (var_A4 = vbNullString) Thenvar_8C = "ERR:ReadData"Elsevar_AC = Split(var_A4, "#", -1, 0)     //字符串拆分数组var_CC = "" 'Ignore thisvar_98 = var_98 & var_AC(1)    //组合数据var_98 = Call Proc_31_14_606B88(var_98)  //自定义加密var_98 = CStr(Left(CVar(Call Proc_31_15_606408(var_98 & "QuickMake")), &H10))     //二次自定义加密var_E0 = "" 'Ignore thisvar_CC = "" 'Ignore thisIf (var_98 <> var_AC(2)) Then   //比较处理后数据(数据效验)var_8C = "ERR:NOTCMP"Elsevar_8C = var_98End IfEnd IfEnd IfEnd IfEnd Ifvar_88 = var_8CExit Sub
End Sub

总结

:只需要按照上面代码及其调用的子方法代码梳理清楚并通过C++编译,并返回对应的数据即可完全实现加密狗的数据交互,

3.继续通过查找引用,查找Proc_30_15被调用的方法

Private Sub Proc_30_14_55447C(arg_10) '55447C'Data Table: 4979BCvar_94 = CVar(Proc_30_15_59651C()) 'VariantResult = arg_10: Exit Sub
End Sub

,然后继续查找引用,定位Proc_30_14被哪些方法引用了

结果如下:

frmzc.Combo1_Click
modReg.Proc_30_0
modReg.Proc_30_16
frmGetZCHao.Combo1_Click
frmDog.Tmer1_Timer
由此可见,Proc_30_14就是所有检测获取加密狗数据的最终方法,也算是一个爆破点,只要在这里返回正确的加密数据即可,至于这个数据有什么限制还需要具体分析,这里不做过多说明.
当然不排除以上这些代码内容中有没有写入在其他目前未知的地方进行的全局变量的标志检测.

硬盘授权模式逆向推进

1.继续上面提到的frmGetZCHao类Form_Load窗体加载事件和

Combo1_Click下拉框点击事件中的clsdno类
查看引用Proc_55两个子方法,只在当前类调用,忽略
然后使用文本批量查找工具查找导出的工程,
搜索:
GetModelNumber
GetSerialNumber 硬盘序列号,这个很重要
在这四个frmgetzchao,frmzc,modreg,modwmihdd类中有使用
然后我们用查看引用逆推看哪些是未被使用的代码
frmgetzchao,frmzc这两个类是获取硬盘数据,不太可能是启动验证的代码块,所以我们暂时分析后两个
2.查看引用逆向跟踪引用
GetSerialNumber
Proc_106_3(modWMIHDD)
Proc_81_13(modDiscSize)

frmzc.Combo1_Click
frmzc.Command5_Click
modReg.Proc_30_12
frmGetZCHao.Combo1_Click
最终还是回到了这三个方法里面
所以我们我们可以得出结论:
modreg是最有可能是后台验证数据的方法段.

3.我们分析一下这个申请码是怎么生成的 frmGetZCHao类的Combo1_Click点击事件

 ElseCall Proc_81_13_56B030(CLng(MemVar_6AFF28))  //获取硬盘容量NewIfNullPr clsdno 'Ignore thisvar_94.CurrentDrive = CByte(MemVar_6AFF28)NewIfNullPr clsdno 'Ignore thisvar_A0 = var_94.GetSerialNumber()If (var_A0 <> vbNullString) Then   //硬盘序列号不为空NewIfNullPr clsdno 'Ignore thisNewIfNullPr clsdno 'Ignore thisvar_B4 = CVar(Call Proc_60_4_583C44(var_94.GetModelNumber() & "<r>" & var_94.GetSerialNumber() & "<r>" & CStr(CLng(var_B4)) & "<r>", "F1DD7CDB1328DB1E")) 'String   //组合硬盘名和序列号,进行加密Call Proc_88_0_5C2170(var_E4)  //看不明白变量来源,代码是编码转换,常规加密手段var_88 = CStr(var_E4)var_A0 = "":   var_108 = "":   var_A4 = "":   var_10C = "":   var_110 = "":   var_114 = "":   var_118 = "" 'Ignore thisvar_B4 = "" 'Ignore thisElsevar_88 = "NoDiseAvailable"End IfEnd If'Ignore thisSet var_94 = NothingIf (var_88 = "NoDiseAvailable") Thenvar_88 = Call Proc_42_6_57E0AC("Msg_DiskUnAble")End IfMe.Text1.Text = var_88var_8C = vbNull 'Ignore thisExit Sub

反正也看不懂具体的代码功能,这个还需要VB的程序员具体分析

整理笔记2

modFD181类中使用了4个狗头(加密狗头文件)的函数
modReg类中Proc_30_14是加密狗数据交互的桥梁
硬盘版的申请代码加密方法已找到

第二阶段总结

1.如果要伪造加密狗,需要补全所有API,并转换VB代码为C++代码
2.爆破方式需要对Proc_30_14进行编译,根据上下文来构建数据
3.硬盘模式对虚拟机无效,因为虚拟机无法生成硬盘序列号.
似乎陷入了僵局…
别忘了前面提到的对称加密modRij类(Proc_60),无论是加密狗还是硬盘都是用了这个类的方法进行加密,那么我们看这个类里面的具体代码

分析过程[通过加密解密寻找硬盘验证逻辑]
分析Rij
Proc_4

NewIfNullPr cRijndael 'Ignore thisvar_D4 = var_CC.ArrayEncrypt(StrConv(var_8C, &H80, 0), var_9C, 0)   //数组加密var_88 = Call Proc_60_0_58C420(var_9C, (UBound(var_9C, 1) + 1), (&H80 / 8))   //编码转换

Proc_5

 Call Proc_60_1_59DE20(var_8C, var_9C)  //编码转换NewIfNullPr cRijndael 'Ignore thisvar_D4 = var_CC.ArrayDecrypt(var_98, var_9C, 0)  //数组解密

查看Proc_5的引用,哇塞,好多地方都使用了,包括各软件功能块的配置数据解密.大概有20个之多,
通过代码对比整合,得出结果
大部分功能类窗口都是用了

MemVar_6AFF34 = Call Proc_60_5_57F48C(Proc_59_1_58D9AC(MemVar_6AF9C0.picSn), "F1DD7CDB1328DB1E")

完整验证代码段

If (Dir(CVar(App.Path & "\sn.bmp"), 0) <> vbNullString) Then  //判断软件目录下是否存在sn.bmp文件PopAdLdVar 'Ignore thisPopAdLdVar 'Ignore thisPopAdLdVar 'Ignore thisPopAdLdVar 'Ignore thisNewIfNullPr Me 'Ignore thisvar_A0 = Me.Global.AppPopAdLdVar 'Ignore thisNewIfNullPr Me 'Ignore thisMe.Global.LoadPicture CVar(App.Path & "\sn.bmp"), var_B8, var_C8, var_D8, var_E8   //加载图片数据(字符)NewIfNullPr frmmain 'Ignore thisSet var_F4 = MemVar_6AF9C0.picSnfrmmain.picSn.Picture = var_EC   //这里应该就是存放数据的地方var_A4 = "" 'Ignore thisvar_A0 = "": var_F0 = "" 'Ignore thisvar_9C = "" 'Ignore thisNewIfNullPr frmmain 'Ignore thisMemVar_6AFF34 = Call Proc_60_5_57F48C(Proc_59_1_58D9AC(MemVar_6AF9C0.picSn), "F1DD7CDB1328DB1E")    //解密数据var_A4 = "" 'Ignore thisvar_A0 = vbNull 'Ignore thisEnd IfElseMemVar_6AFF34 = MemVar_6AFF20 & "|||||||||||||||||||||||||||||"End If

通过分析感觉应该是水印之类的东西,具体功能不详.略过

又失败了,没关系我们继续,换个思路
既然是硬件绑定模式,又没有输入注册码的框框,那肯定是给的授权文件,我们全文搜索 Dir( 和 App.Path
一个是目录拼接,另一个是软件当前路径

通过关键代码查找可用信息
1.工具内CTRL+F调出来搜索框,去掉在活动窗口搜索的选项,搜索Dir(
sn.bmp bip.bmp sn.txt
经过对已有文件数据和综合经验过滤,最终发现以上3个可疑文件

2.分析文件功能和行为
其中对sn.bmp我们排除掉,前面分析过了,没什么用
定位bip.bmp在modCheckID类中,我们要通过交叉引用分析具体功能和作用.
定位sn.txt在modReg模块中,只有Open关键字进行读取操作.

通过对modCheckID类中所有代码分析,应该是从服务器获取黑名单用户,跳过(frmmain的Form_Load最后代码使用,还有UnLoad关闭窗体事件中也使用了)
剩下的就是modReg类,这就是我在前面为什么不跟进这个类,这个类是个关键类,大概率所有验证的内容都在这个类里面

所有的地方都找遍了,最后专心搞modReg类,通过上面的反复横跳,大家应该对VB Decompiler比较了解了吧,呵呵~我专门坑新人

重头戏 分析关键类
1.我们对modReg类每个子方法进行查找引用,综合分析
Proc_30_0
Proc_30_1
Proc_30_2
Proc_30_3
Proc_30_4
Proc_30_5
Proc_30_12
Proc_30_14
以上方法被其他类调用了,

%%%%% 夜深了,有空继续更新内容 %%%%%%%%%%%

其他补充
关于反调试
在frmmain类的Form_Load事件中

var_98 = "参数设定"MemVar_6AF00C = Me.CaptionMe.findsomething.Enabled = True      //这个是定时器

事件代码:

Private Sub findsomething_Timer() '557180'Data Table: 4C132CDim var_8C As Stringvar_8C = Call Proc_53_1_585BB0(Me.hWnd)  //AntiCrack类If (var_8C <> vbNullString) ThenEndEnd IfExit Sub
End Sub

方法代码

Private Sub Proc_53_1_585BB0(arg_C) '585BB0'Data Table: 4933FCDim var_94 As Longvar_88 = vbNullStringSetLastSystemError 'Ignore thisvar_94 = GetForegroundWindow()   //获取活动窗口If (var_94 <> arg_C) ThenGetWindowText(var_94, var_8C, &H100)   //获取窗口标题SetLastSystemError 'Ignore thisvar_8C = var_A0var_9C = "" 'Ignore thisvar_9C = var_8Cvar_8C = var_9Cvar_90 = Left$(var_9C, CLng((InStr(1, CVar(var_8C), Chr(0), 0) - 1)))var_9C = "" 'Ignore thisvar_B0 = "" 'Ignore thisvar_B0 = "" 'Ignore thisIf CBool(InStr(1, LCase(var_90), "numega", 0)) Then   //检测调试器var_88 = "BADSOFT"End Ifvar_B0 = "" 'Ignore thisIf CBool(InStr(1, LCase(var_90), "softice", 0)) Then   //检测调试器var_88 = "BADSOFT"End IfEnd IfExit SubIDE.GoTo loc_585BAD 'Ignore thisIDE.GoTo loc_585C73 'Ignore this
End Sub

呵呵,我就笑了这都啥年代了,还用这种陈旧的调试工具?不过还真可以添加到工具库试试效果.

结束语 其实还没结束,毕竟只是分析程序,还没分析完成 小编对VB6知之甚少,毕竟是C#的业余程序员,只能靠着C#的知识储备对这个VB6的伪代码进行大体上的分析. 也欢迎各位VB的高手交流经验,给一些参考意见

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/79961.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一场深刻的开源聚会:KCC@北京 9.2 活动回顾

开源为我们带来了什么&#xff1f;这是这场聚会的宣传文的标题&#xff1a;https://mp.weixin.qq.com/s/5sR6TPEpQmYNBnCtVilkzg 同样这个问题也可以是极具个体化的&#xff1a;开源为我带来了什么&#xff1f;秋天的周末&#xff0c;预报有雨&#xff0c;北京的开源人还是相聚…

脚本:用python实现五子棋

文章目录 1. 语言2. 效果3. 脚本4. 解读5. FutureReference 1. 语言 Python 无环境配置、无库安装。 2. 效果 以第一回合为例 玩家X 玩家0 3. 脚本 class GomokuGame:def __init__(self, board_size15):self.board_size board_sizeself.board [[ for _ in range(board_…

对IP协议概念以及IP地址的概念进行简单整理

网络层重要协议 参考模型和协议栈IP协议IPv4数据报IP数据报格式IPv4地址特殊IP地址私有IP地址和公有IP地址子网划分 参考模型和协议栈 IP协议 IP协议定义了网络层数据传送的基本单元&#xff0c;也制定了一系列关于网络层的规则。 IPv4数据报 网络层的协议数据单元PDU 叫做分…

基于Java+SpringBoot+Vue+uniapp点餐小程序(包含协同过滤算法和会员系统,强烈推荐!)

校园点餐小程序 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序&#xff08;小蔡coding&#xff09;2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 系统功能结构设计4.2 主要功能描述 五…

【初阶数据结构】栈和队列——C语言(详解)

目录 一、栈 1.1栈的概念及结构 1.2栈的实现 1.2.1静态栈的实现 1.3动态栈的实现 1.3.1栈的创建 1.3.2栈的初始化 1.3.3栈的清空销毁 1.3.4栈的元素插入 1.3.5栈顶元素的删除 1.3.6返回栈顶数据 1.3.7求栈的大小 1.3.8判断栈是否为空 二、栈的实现完整代码 三、队…

Unity 动画系统

动画系统包含&#xff1a; 动画片段 Animation Clip&#xff0c;记录物体变化的信息&#xff0c;可以是角色的闪转腾挪&#xff0c;也可以是一扇门的开闭动画状态机 Animator Controller&#xff0c;根据设置切换动画片段动画组件 Animator&#xff0c;Animation替身 Avatar&a…

数据结构基础8:二叉树oj+层序遍历。

二叉树oj层序遍历 题目一&#xff1a;二叉树的销毁&#xff1a;方法一&#xff1a;前序遍历&#xff1a;方法二&#xff1a;后序遍历&#xff1a; 题目二&#xff1a;二叉树查找值为x的节点方法一&#xff1a;方法二&#xff1a;方法三&#xff1a; 题目三&#xff1a;层序遍历…

透视俄乌网络战之二:Conti勒索软件集团(下)

透视俄乌网络战之一&#xff1a;数据擦除软件 透视俄乌网络战之二&#xff1a;Conti勒索软件集团&#xff08;上&#xff09; Conti勒索软件集团&#xff08;下&#xff09; 1. 管理面板源代码2. Pony凭证窃取恶意软件3. TTPs4. Conti Locker v2源代码5. Conti团伙培训材料6. T…

【Linux从入门到精通】多线程 | 线程互斥(互斥锁)

上篇文章我们对线程 | 线程介绍&线程控制介绍后&#xff0c;本篇文章将会对多线程中的线程互斥与互斥锁的概念进行详解。同时结合实际例子解释了可重入与不被重入函数、临界资源与临界区和原子性的概念。希望本篇文章会对你有所帮助。 文章目录 引入 一、重入与临界 1、1 可…

多线程|多进程|高并发网络编程

一.多进程并发服务器 多进程并发服务器是一种经典的服务器架构&#xff0c;它通过创建多个子进程来处理客户端连接&#xff0c;从而实现并发处理多个客户端请求的能力。 概念&#xff1a; 服务器启动时&#xff0c;创建主进程&#xff0c;并绑定监听端口。当有客户端连接请求…

GitLab使用的最简便方式

GitLab介绍 GitLab是一个基于Git版本控制系统的开源平台&#xff0c;用于代码托管&#xff0c;持续集成&#xff0c;以及协作开发。它提供了一套完整的工具&#xff0c;以帮助开发团队协同工作、管理和部署代码。 往往在企业内部使用gitlab管理代码&#xff0c;记录一下将本地代…

VR航天航空巡展VR科技馆航天主题科普设备沉浸遨游太空

每当飞机飞过头顶&#xff0c;我们总是忍不住抬头去仰望。从嫦娥奔月的神话传说&#xff0c;到莱特兄弟实现了上天翱翔的梦想&#xff0c;人类一直在不断探索更辽阔的天空和浩瀚的宇宙。 航空科普 寻梦而行 普乐蛙VR航天航空巡展&#xff0c;正在湖南郴州如火如荼的进行中&…

arm day2(9.15)数据操作指令,跳转指令,特殊功能寄存器指令,

作业 1.求最大公约数&#xff1a; .text .global _start _start:mov r0,#0x9mov r1,#0x15bl Loop Loop:cmp r0,r1 比较r0寄存器和r1寄存器的中的值beq stop 当两数相同时,退出程序subhi r0,r0,r1 r0>r1 r0 r0 - r1subcc r1,r1,r0 r0<r1 r1 r1 - r0mov pc,lr 恢复现…

【算法与数据结构】108、LeetCode将有序数组转换为二叉搜索树

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;这道题给我们的是一个有序数组&#xff0c;并要求构成一个平衡二叉搜索树&#xff0c;二叉搜索树的很容…

CSS 之 grid 网格布局

一、简介 ​ display: grid;用于设置元素内部的布局类型为网格布局&#xff0c;其外显类型为块级元素。该类型的元素将内部分为行和列&#xff0c;划分成一个个单元格&#xff0c;并通过一系列相关属性控制单元格及其内容的布局和大小。 ​ 该属性值的主要应用场景为&#xf…

这个锂电池保护方案来自TIDA-010030

本篇博客只是作为个人记录&#xff0c;拆锂电池有危险&#xff0c;撬棒刺穿外壳可能爆炸&#xff0c;请勿模仿&#xff0c;误操作电池数据可能失效&#xff0c;请勿模仿。 1、简介 1.1、目的 得到该电池的电量计芯片型号、IIC从机地址、通信的实际波形&#xff1b; 1.2、步…

百度飞浆OCR识别表格入门python实践

1. 百度飞桨&#xff08;PaddlePaddle&#xff09; 百度飞桨&#xff08;PaddlePaddle&#xff09;是百度推出的一款深度学习平台&#xff0c;旨在为开发者提供强大的深度学习框架和工具。飞桨提供了包括OCR&#xff08;光学字符识别&#xff09;在内的多种功能&#xff0c;可…

Linux驱动IO篇——异步通知

文章目录 什么是异步通知异步通知和异步IO的区别信号含义应用层使用信号驱动如何实现异步信号驱动实例 什么是异步通知 异步通知在Linux的实现中是通过信号&#xff0c;而信号是在软件层次上对中断机制的一种模拟。这种机制和中断非常类似&#xff0c;所以可以以中断的思想来理…

重新认识交叉编译

1. 我以前对交叉编译的认知 引用正点原子的话来讲就是: 说得对&#xff0c;但是不全面&#xff0c;直到最近项目中遇到了一个例子我才重新认识什么是交叉编译。 2. build/host/target的概念 参考: Cross-Compilation (automake) 参考: Specifying Target Triplets (Autocon…

Python二级 每周练习题18

练习一: 从键盘输入任意字符串&#xff0c;按照下面要求分离字符串中的字符: 1、分别取出该字符串的第偶数位的元素(提醒注意:是按照从左往右数的方式确定字符串的位置) 2、并依次存储到一个列表中; 3、输出这个列表。 答案: ninput(请输入任意字符串:) #创建变量n存放用户…