VB逆向基础(一)
VB逆向基础
编译模式
VB程序编译分成两种模式,如下图
- P-Code 模式。Microsoft推出的VB P-code,实际上也是一组自定义的指令集,必须通过基于堆栈的虚拟机翻译为80X86上的指令集才能执行,担任虚拟机任务的就是msvbvm50.dll和msvbvm60.dll这两个动态链接库文件。该模式的分析较为复杂,留个坑以后再来分析,我们直接用VB Decompiler。
- Native-Code。机器码,可以用VB Decompiler,也可以用x32dbg。VB Decompiler直接逆向出源码了,为了研究我们用x32dbg。
基本类型
以“vb逆向练习”为例子。
Boolean 类型
vb源代码如下
Private Sub DataType_Boolean_Click()Dim nn = CBool(Text1.text)MsgBox "Boolean Value:" & n
End Sub
汇编关键代码如下:
Byte类型
vb源代码如下
Private Sub DataType_Byte_Click()Dim nn = CByte(Text1.text)MsgBox "Byte Value:" & n
End Sub
汇编关键代码如下:
Int类型
vb源代码如下
Private Sub DataType_Int_Click()Dim nn = CInt(Text1.text)MsgBox "Integer Value:" & n
End Sub
汇编关键代码如下:
Long类型
vb源代码如下
Private Sub DataType_Long_Click()Dim nn = CLng(Text1.text)MsgBox "Long Value:" & n
End Sub
汇编关键代码如下:
Single类型
vb源代码如下
Private Sub DataType_Single_Click()Dim nn = CSng(Text1.text)MsgBox "Single Value:" & n
End Sub
汇编关键代码如下:
Double类型
vb源代码如下
Private Sub DataType_Double_Click()Dim nn = CDbl(Text1.text)MsgBox "Double Value:" & n
End Sub
汇编关键代码如下:
String类型
vb源代码如下
Private Sub DataType_String_Click()Dim nn = CStr(Text1.text)MsgBox "String Value:" & n
End Sub
汇编关键代码如下:
类型总结
基本类型名称 | 类型编号 | 宽度 | 实际值(首地址+0x08) |
---|---|---|---|
Boolean | 0x0B | 2字节 | True——0xFF,False——0x00 |
Byte | 0x11 | 1字节 | 8位值 |
Int | 0x02 | 2字节 | 16位值 |
Long | 0x03 | 4字节 | 32位值 |
Single | 0x04 | 4字节 | 32位浮点型 |
Double | 0x05 | 8字节 | 64位浮点型 |
String | 0x08 | 4字节 | 32位字符串首地址 |
运算符
加法
vb源代码如下
Private Sub Add_Click()Dim n1Dim n2Dim nResn1 = CInt(Text1.text)n2 = CInt(Text2.text)nRes = n1 + n2MsgBox "Add:" & nRes
End Sub
汇编关键代码如下:
减法
vb源代码如下
Private Sub Sub_Click()Dim n1Dim n2Dim nResn1 = CInt(Text1.text)n2 = CInt(Text2.text)nRes = n1 - n2MsgBox "Sub:" & nRes
End Sub
汇编关键代码如下:
乘法
vb源代码如下
Private Sub Mul_Click()Dim n1Dim n2Dim nResn1 = CInt(Text1.text)n2 = CInt(Text2.text)nRes = n1 * n2MsgBox "Mul:" & nRes
End Sub
汇编关键代码如下:
除法
vb源代码如下
Private Sub Div_Click()Dim n1Dim n2Dim nResn1 = CDbl(Text1.text)n2 = CDbl(Text2.text)nRes = n1 / n2MsgBox "Div:" & nRes
End Sub
汇编关键代码如下:
运算符总结
- 加法
lea eax,dword ptr ss:[ebp-34]
lea ecx,dword ptr ss:[ebp-44]
push eax ;加数1
lea edx,dword ptr ss:[ebp-5C]
push ecx ;加数2
push edx ;运算结果,也以eax当做返回值
call dword ptr ds:[<&__vbaVarAdd>] ;变量加法
- 减法
lea eax,dword ptr ss:[ebp-34]
lea ecx,dword ptr ss:[ebp-44]
push eax ;被减数
lea edx,dword ptr ss:[ebp-5C]
push ecx ;减数
push edx ;运算结果,也以eax当做返回值
call dword ptr ds:[<&__vbaVarSub>] ;变量减法
- 乘法
lea eax,dword ptr ss:[ebp-34]
lea ecx,dword ptr ss:[ebp-44]
push eax ;被乘数
lea edx,dword ptr ss:[ebp-5C]
push ecx ;乘数
push edx ;运算结果,也以eax当做返回值
call dword ptr ds:[<&__vbaVarMul>] ;变量乘法
- 除法
lea eax,dword ptr ss:[ebp-34]
lea ecx,dword ptr ss:[ebp-44]
push eax ;被除数
lea edx,dword ptr ss:[ebp-5C]
push ecx ;除数
push edx ;运算结果,也以eax当做返回值
call dword ptr ds:[<&__vbaVarDiv>] ;变量除法
- 变量拼接字符串
lea eax,dword ptr ss:[ebp-9C]
push edi
lea ecx,dword ptr ss:[ebp-24]
push eax ;左边变量
lea edx,dword ptr ss:[ebp-5C]
push ecx ;右边变量
push edx ;拼接结果
mov dword ptr ss:[ebp-94],vbtest.401F70
mov dword ptr ss:[ebp-9C],8
call dword ptr ds:[<&__vbaVarCat>]; 变量拼接
循环
For循环
vb源代码如下
Private Sub For_Loop_Click()Dim iDim textDim sumDim textLenDim charsum = 0text = Text2.texttextLen = Len(text)For i = 3 To textLen Step 2char = CStr(Mid(text, CLng(i), 1))sum = sum + Asc(char)Next iMsgBox "For_Loop sum:" & sum
End Sub
for循环关注两个函数 __vbaVarForInit和__vbaVarForNext以及循环退出判断
- __vbaVarForInit 表示循环条件初始化
lea ecx,dword ptr ss:[ebp-BC]
lea edx,dword ptr ss:[ebp-44]
push ecx ;参数6,Step值,Int类型
lea eax,dword ptr ss:[ebp-CC]
push edx ;参数5,循环变量上限 Long类型
lea ecx,dword ptr ss:[ebp-114]
push eax ;参数4,循环初始值固定值,Int类型
lea edx,dword ptr ss:[ebp-104]
push ecx ;参数3,循环临时上限,Long类型 给__vbaVarForNext用
lea eax,dword ptr ss:[ebp-24]
push edx ;参数2,循环临时步长,Long类型, 给__vbaVarForNext用
push eax ;参数1,当前循环值,Long类型
mov dword ptr ss:[ebp-B4],edi
mov dword ptr ss:[ebp-BC],edi
mov dword ptr ss:[ebp-C4],3
mov dword ptr ss:[ebp-CC],edi
call dword ptr ds:[<&__vbaVarForInit>]
- __vbaVarForNext用于更新下一次循环的当前循环变量的值,以及用于是否跳出循环的eax,ebx值更新,eax等于ebx等于等跳出循环,eax =1且ebx=0循环继续
lea edx,dword ptr ss:[ebp-114]
lea eax,dword ptr ss:[ebp-104]
push edx ;参数3,循环临时上限,Long类型
lea ecx,dword ptr ss:[ebp-24]
push eax ; 参数2,循环临时步长,Long类型
push ecx ; 参数1,当前循环值,Long类型
call dword ptr ds:[<&__vbaVarForNext>] ;更新循环标志值
- 循环退出判断
call dword ptr ds:[<&__vbaVarForInit>]
40493C: cmp eax,ebx ;是否继续循环
je vbtest.404A17; eax等于ebx时循环退出
...
xxx
...
call dword ptr ds:[<&__vbaVarForNext>]
jmp vbtest.40493C ;跳转到cmp判断
while 循环
vb源代码如下
Private Sub While_Loop_Click()Dim iDim textDim sumDim textLenDim charsum = 0text = Text2.texttextLen = Len(text)i = 1While i <= textLenchar = CStr(Mid(text, CLng(i), 1))sum = sum + Asc(char)i = i + 1WendMsgBox "While_Loop sum:" & sum
End Sub
while循环关注__vbaVarTstLe和jmp
- __vbaVarTstLe 第1个参数小于等于2个参数,ax等于FFFF表示参数1小于等参数2,ax等于0x00表示参数1大于参数2,ax等于0x00时循环退出
00404C85 | lea ecx,dword ptr ss:[ebp-24] |
00404C88 | lea edx,dword ptr ss:[ebp-44] |
00404C8B | push ecx | 参数2,左边被比较值
00404C8C | push edx | 参数1,右边被比较值
00404C8D | call dword ptr ds:[<&__vbaVarTstLe>] | 判断参数2小于等于参数1
00404C93 | test ax,ax |判断ax是否为0x00
00404C96 | je vbtest.404D7B |退出循环
- jmp循环继续
00404C85 | lea ecx,dword ptr ss:[ebp-24] |
00404C88 | lea edx,dword ptr ss:[ebp-44] |
00404C8B | push ecx | 参数2,左边被比较值
00404C8C | push edx | 参数1,右边被比较值
00404C8D | call dword ptr ds:[<&__vbaVarTstLe>] | 判断参数2小于等于参数1
00404C93 | test ax,ax |判断ax是否为0x00
00404C96 | je vbtest.404D7B |退出循环
...
xxx
...
00404D76 | jmp vbtest.404C85 |跳转到判断条件
do-while 循环
vb源代码如下
Private Sub Do_While_Loop_Click()Dim iDim textDim sumDim textLenDim charsum = 0text = Text2.texttextLen = Len(text)i = 1Do While i <= textLenchar = CStr(Mid(text, CLng(i), 1))sum = sum + Asc(char)i = i + 1LoopMsgBox "Do_While sum:" & sum
End Sub
- do-while循环汇编与while循环一样
条件语句
if-else
vb源代码如下
Private Sub If_Else_Click()If Text1.text = "1" ThenMsgBox "If Value:" & Text1.textElseMsgBox "Else Value:" & Text2.textEnd If
End Sub
- if-else的汇编结构如下
00405284 | mov eax,dword ptr ss:[ebp-18] |
00405287 | push eax |Text1.text
00405288 | push vbtest.402014 |常量"1"
0040528D | call dword ptr ds:[<&__vbaStrCmp>] |判断字符串是否相等,相等是eax等于0
00405293 | mov edi,eax |
00405295 | lea ecx,dword ptr ss:[ebp-18] |
00405298 | neg edi |
0040529A | sbb edi,edi |
0040529C | inc edi |
0040529D | neg edi |
0040529F | call dword ptr ds:[<&__vbaFreeStr>] |
004052A5 | lea ecx,dword ptr ss:[ebp-1C] |
004052A8 | call dword ptr ds:[<&__vbaFreeObj>] |
004052AE | mov ecx,80020004 |
004052B3 | mov eax,A |
004052B8 | test di,di |
004052CD | je vbtest.405362 |di为0,跳转到else分支
xxx |if分支
...
0040535D | jmp vbtest.4053EC |结束if分支跳转到end if的下一句
00405362 | xxx |else分支
switch-case
vb源代码如下
Private Sub Switch_Case_Click()Select Case Text1.textCase "1"MsgBox "Switch Case Value:" & "Case 1"Case "2"MsgBox "Switch Case Value:" & "Case 2"Case ElseMsgBox "Switch Case Value:" & "Case Default"End Select
End Sub
- switch-case的汇编结构如下
00405519 | 8B35 64104000 | mov esi,dword ptr ds:[<&__vbaStrCmp>] |
0040551F | 50 | push eax |Select Case值
00405520 | 68 14204000 | push vbtest.402014 | Case "1"值
00405525 | FFD6 | call esi |调用__vbaStrCmp
00405527 | 85C0 | test eax,eax |eax为0,继续进入到Case "1"分支
00405529 | 75 62 | jne vbtest.40558D |eax不为0,跳转到Case"2"判断
xxx | 到Case "1"分支
... |
0040558D | 8B85 68FFFFFF | mov eax,dword ptr ss:[ebp-98] |
00405593 | 50 | push eax |Select Case值
00405594 | 68 7C204000 | push vbtest.40207C |Case "2"值
00405599 | FFD6 | call esi |
0040559B | 85C0 | test eax,eax |eax为0,继续进入到Case "2"分支
0040559D | B9 04000280 | mov ecx,80020004 |
004055A2 | B8 0A000000 | mov eax,A | A:'\n'
004055A7 | 894D AC | mov dword ptr ss:[ebp-54],ecx |
004055AA | 8945 A4 | mov dword ptr ss:[ebp-5C],eax |
004055AD | 894D BC | mov dword ptr ss:[ebp-44],ecx |
004055B0 | 8945 B4 | mov dword ptr ss:[ebp-4C],eax |
004055B3 | 894D CC | mov dword ptr ss:[ebp-34],ecx |
004055B6 | 8945 C4 | mov dword ptr ss:[ebp-3C],eax |
004055B9 | 68 50204000 | push vbtest.402050 | 402050:L"Switch Case Value:"
004055BE | 75 3E | jne vbtest.4055FE |eax不为0,跳转到Case Else
xxx |Case "2"分支
... |
004055FE | 68 9C204000 | push vbtest.40209C | Case Else分支
参考文章
https://bbs.kanxue.com/article-3640.htm