淺談VB6逆向工程(1)
前言
VB的編譯有兩種方式,一種是P-Code方式,一種是本機程式碼。P_Code方式是VB
從早期版本保留下來的,也是比較難逆向的一種。而本機程式碼方式編譯的程式已經
和VC很接近了。這裡只探討以本機程式碼方式編譯的程式。由於微軟在VB的實現方面
的資料很少,使人覺得VB的逆向比較難。其實掌握一些規律,VB的程式還是很容易
入門的。
這裡所提到的知識都是個人的經驗,沒有什麼官方的資料作為依據。所以錯誤
之處難免,如果你發現什麼錯誤,歡迎指正。
1. 從簡單變數的實現開始
一個VB簡單變數的表示至少需要12個位元組。通常前2個位元組是表示型別資訊的。
從第5個位元組到第8個位元組並不總是使用到,實際上很少被使用。我們不妨先叫它
輔助型別資訊。從第9個位元組開始就是真正的變數的值了。這裡有可能儲存一個指標
值,也可能是資料,具體是什麼取決於變數型別。
另一個值得注意的事實是VB的記憶體是以4個位元組對齊的。即使你使用一個位元組,
那至少也要4個位元組來表示。而且編譯器只初始化它需要的那些位元組,剩餘的位元組
可能是隨機資料。下面我們將會看到這些。
想弄明白編譯器在內部怎麼實現的,最好的方法就是編一段程式跟蹤執行看看。
我編寫的程式碼如下:
Dim a, i As Byte
Dim b, j As Integer
Dim c, k As Long
Dim d, l As Boolean
Dim e, m As String
Dim f, n As Date
Dim g, o As Double
Dim h, p As Single
a = &H30
b = 330
c = 66000
d = True
e = "hello"
f = Now
g = 3.1415
h = 1.27
i = a
j = b
k = c
l = d
m = e
n = f
o = g
p = h
這段程式碼在VB的預設設定(速度最佳化)下編譯。然後用od反彙編出來如下:
去掉了部分無關內容,其餘的我在這段程式碼的實現裡做了註釋:
00401B02 MOV ESI,DWORD PTR DS:[<&MSVBVM60.__vbaVa>; MSVBVM60.__vbaVarMove
00401B08 XOR EDI,EDI
00401B0A MOV EBX,2
00401B0F MOV DWORD PTR SS:[EBP-DC],EDI
00401B15 LEA EDX,DWORD PTR SS:[EBP-DC]
00401B1B LEA ECX,DWORD PTR SS:[EBP-4C]
00401B1E MOV DWORD PTR SS:[EBP-28],EDI
00401B21 MOV DWORD PTR SS:[EBP-4C],EDI
00401B24 MOV DWORD PTR SS:[EBP-5C],EDI
00401B27 MOV DWORD PTR SS:[EBP-6C],EDI
00401B2A MOV DWORD PTR SS:[EBP-7C],EDI
00401B2D MOV DWORD PTR SS:[EBP-8C],EDI
00401B33 MOV DWORD PTR SS:[EBP-9C],EDI
00401B39 MOV DWORD PTR SS:[EBP-AC],EDI
00401B3F MOV DWORD PTR SS:[EBP-BC],EDI
00401B45 MOV DWORD PTR SS:[EBP-CC],EDI
00401B4B MOV DWORD PTR SS:[EBP-D4],30 //30h = &H30
00401B55 MOV DWORD PTR SS:[EBP-DC],EBX //EBX = 2: integer型
00401B5B CALL ESI ; <&MSVBVM60.__vbaVarMove>
**** a =&H30 即[ebp-4c]
00401B5D LEA EDX,DWORD PTR SS:[EBP-DC]
00401B63 LEA ECX,DWORD PTR SS:[EBP-5C] //變數b
00401B66 MOV DWORD PTR SS:[EBP-D4],14A //14Ah = 330
00401B70 MOV DWORD PTR SS:[EBP-DC],EBX //EBX = 2: integer型
00401B76 CALL ESI
**** b = 330 即[ebp-5c]
00401B78 LEA EDX,DWORD PTR SS:[EBP-DC]
00401B7E LEA ECX,DWORD PTR SS:[EBP-6C]
00401B81 MOV DWORD PTR SS:[EBP-D4],101D0 //101D0 = 66000
00401B8B MOV DWORD PTR SS:[EBP-DC],3 //3:long型
00401B95 CALL ESI
**** c = 66000 即[ebp-6c]
00401B97 LEA EDX,DWORD PTR SS:[EBP-DC]
00401B9D LEA ECX,DWORD PTR SS:[EBP-7C]
00401BA0 MOV DWORD PTR SS:[EBP-D4],-1 //-1 TRUE
00401BAA MOV DWORD PTR SS:[EBP-DC],0B //12:boolean型
00401BB4 CALL ESI
**** d = TRUE 即[ebp-7c]
00401BB6 LEA EDX,DWORD PTR SS:[EBP-DC]
00401BBC LEA ECX,DWORD PTR SS:[EBP-8C]
00401BC2 MOV DWORD PTR SS:[EBP-D4],工程1.00401948 ; UNICODE "hello" //"hello"
00401BCC MOV DWORD PTR SS:[EBP-DC],8 //8:string型
00401BD6 CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarCo>; MSVBVM60.__vbaVarCopy
**** e = "hello" 即[ebp-8c]
00401BDC LEA EAX,DWORD PTR SS:[EBP-CC]
00401BE2 PUSH EAX
00401BE3 CALL DWORD PTR DS:[<&MSVBVM60.#546>] //Now
00401BE9 LEA EDX,DWORD PTR SS:[EBP-CC] //Now
00401BEF LEA ECX,DWORD PTR SS:[EBP-9C]
00401BF5 CALL ESI
**** f = Now 即[ebp-9c]
00401BF7 MOV EBX,5
00401BFC LEA EDX,DWORD PTR SS:[EBP-DC]
00401C02 LEA ECX,DWORD PTR SS:[EBP-AC]
00401C08 MOV DWORD PTR SS:[EBP-D4],C083126F
00401C12 MOV DWORD PTR SS:[EBP-D0],400921CA //3.1415
00401C1C MOV DWORD PTR SS:[EBP-DC],EBX //EBX = 5 :double型
00401C22 CALL ESI
**** g = 3.1415 即[ebp-ac]
00401C24 LEA EDX,DWORD PTR SS:[EBP-DC]
00401C2A LEA ECX,DWORD PTR SS:[EBP-BC]
00401C30 MOV DWORD PTR SS:[EBP-D4],851EB852
00401C3A MOV DWORD PTR SS:[EBP-D0],3FF451EB //1.27
00401C44 MOV DWORD PTR SS:[EBP-DC],EBX //EBX = 5 :double型
00401C4A CALL ESI
// h = 1.27
00401C4C LEA ECX,DWORD PTR SS:[EBP-4C]
00401C4F PUSH ECX
00401C50 CALL DWORD PTR DS:[<&MSVBVM60.__vbaUI1Va>; MSVBVM60.__vbaUI1Var
//取byte, al中
**** i = a
00401C56 LEA EDX,DWORD PTR SS:[EBP-5C]
00401C59 PUSH EDX
00401C5A CALL DWORD PTR DS:[<&MSVBVM60.__vbaI2Var>; MSVBVM60.__vbaI2Var
//取integer, ax中
**** j = b
00401C60 LEA EAX,DWORD PTR SS:[EBP-6C]
00401C63 PUSH EAX
00401C64 CALL DWORD PTR DS:[<&MSVBVM60.__vbaI4Var>; MSVBVM60.__vbaI4Var
//取long, eax中
**** k = c
00401C6A LEA ECX,DWORD PTR SS:[EBP-7C]
00401C6D PUSH ECX
00401C6E CALL DWORD PTR DS:[<&MSVBVM60.__vbaBoolV>; MSVBVM60.__vbaBoolVar
//取boolean, ax中
**** l = d
00401C74 LEA EDX,DWORD PTR SS:[EBP-8C]
00401C7A PUSH EDX
00401C7B CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrVa>; MSVBVM60.__vbaStrVarCopy
//取string, eax中是地址
**** m = e
00401C81 MOV EDX,EAX
00401C83 LEA ECX,DWORD PTR SS:[EBP-28]
00401C86 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>; MSVBVM60.__vbaStrMove
00401C8C LEA EAX,DWORD PTR SS:[EBP-9C]
00401C92 PUSH EAX
00401C93 CALL DWORD PTR DS:[<&MSVBVM60.__vbaDateV>; MSVBVM60.__vbaDateVar
//取date, 浮點棧中
**** n = f
00401C99 LEA ECX,DWORD PTR SS:[EBP-AC]
00401C9F FSTP ST
00401CA1 PUSH ECX
00401CA2 CALL DWORD PTR DS:[<&MSVBVM60.__vbaR8Var>; MSVBVM60.__vbaR8Var
//取double, 浮點棧中
**** o = g
00401CA8 LEA EDX,DWORD PTR SS:[EBP-BC]
00401CAE FSTP ST
00401CB0 PUSH EDX
00401CB1 CALL DWORD PTR DS:[<&MSVBVM60.__vbaR4Var>; MSVBVM60.__vbaR4Var
00401CB7 FSTP ST
//取single, 浮點棧中
**** p = h
==========================================
先總結一下:byte 和 integer一樣,內部都是使用integer型別表示,single和double一樣,
內部都是使用double型別表示。date佔用8個位元組。boolean型別佔用2個位元組&HFFFF表示TRUE,而
0表示FALSE.
這些簡單變數在記憶體中的表示如下:前4個位元組含有變數型別,接著4個位元組(意義還不清楚),
我們不妨先叫他輔助型別資訊,過了這8個位元組就是真正的變數資料了。
如變數a的記憶體表示如下:63F3C4 : 02 00 00 00
63F3C8 : 00 00 00 00
63F3CC : 30 00 00 00
可以看到,63F3CC處是真正的變數值。如果是字串,這個位置可以看到一個指標。
簡單變數裡沒有提到的型別是Currency,Decimal,這些你可以自己實際觀察一下。
關於簡單變數就總結這些,不知道你看懂了沒有。我沒有辦法把機器搬上來讓你看。所以還是
那句話:如果你想弄明白我所講的到底是怎麼一回事,就把上面那段程式編譯一下,然後用ollydbg
跟蹤一下看看。
在本文即將結束時要提到的一個事實是:VB並不是強型別語言。例如你可以把一個boolean型別
的變數賦值給一個整數,然後再列印出這個整數的值,你可以看到TRUE的輸出為-1,而FALSE的輸
出為0。當然在你決定這樣做的時候你要保證兩個變數所佔記憶體空間大小一樣或者被賦值的變數的
空間要大於所賦值的變數的空間。否則你可能會得到一個溢位錯誤。你可以試試把date型別的變數
賦值給一個integer型別的變數 :)
相關文章
- 淺談VB6逆向工程(2)2004-12-23
- 淺談VB6逆向工程(3)2004-12-25
- 淺談VB6逆向工程(4)2004-12-27
- 淺談VB6逆向工程(5)2004-12-27
- 逆向工程核心原理(1)逆向基礎2023-03-16
- Delphi逆向工程筆記[1]2004-10-27筆記
- 海外IT工程師淺談2020-09-11工程師
- 逆向工程 O1模型架構2024-09-16模型架構
- iOS逆向工程2016-08-31iOS
- Mybatis逆向工程2024-03-10MyBatis
- Database | 淺談Query Optimization (1)2021-04-09Database
- 淺談0/1切換2015-04-30
- mybatis的逆向工程2020-10-03MyBatis
- 有關VB程式P-CODE程式碼逆向工程入門淺說2015-11-15
- 淺談java之設計模式(1)2020-11-18Java設計模式
- 淺談Java String內幕(1)2016-08-29Java
- 淺談C# vs Java (1) (轉)2008-03-01C#Java
- 小白的MyBatis逆向工程2020-05-01MyBatis
- ios逆向工程連結2017-08-09iOS
- Mybatis逆向工程和新版本MybatisPlus3.4逆向工程的使用2021-10-01MyBatisS3
- 《逆向工程核心原理》作者李承遠訪談問題有獎徵集2014-06-13
- 淺談推進全站HTTPS專案-工程篇2019-03-02HTTP
- 淺談軟體工程中的程式碼評審2018-10-14軟體工程
- 淺談軟體工程師的程式碼素養2018-05-18軟體工程工程師
- 淺談 : iOS工程中哪些需要建立基類(MVC)2016-07-15iOSMVC
- 淺談“工程專案經理”這個角色 (轉)2007-08-13
- 淺談電力工程造價的合理控制(轉)2007-08-16
- iOS開發之逆向工程2019-04-09iOS
- 收藏的爬蟲逆向工程2018-10-17爬蟲
- 逆向工程加密函式:AES2021-12-17加密函式
- iOS逆向工程 iOS工具篇2018-06-19iOS
- 【SSM-MyBatis框架】逆向工程2016-04-13SSMMyBatis框架
- Delphi逆向工程筆記[2]2004-10-27筆記
- Delphi逆向工程筆記[3]2004-10-27筆記
- Delphi逆向工程筆記[4]2004-10-28筆記
- Delphi逆向工程筆記[5]2004-11-11筆記
- 淺談微視推薦系統中的特徵工程2019-12-11特徵工程
- 淺談前端/軟體工程師的程式碼素養2018-05-08前端軟體工程工程師