關於VB P-CODE的一些總結 (10千字)
關於VB P-CODE的一些總結
前言:到網上查PCODE的資料,到了一個講Fight Against Crack的網站上,那個作者講了許多陰毒的招數後,還特別說明,如果是VB程式,最好把它做成P-CODE,這會大大增加破解的難度。事實真的如此嗎?WKT的一個大蝦卻說:We are going to show that protecting a VB application is a very difficult task.The last Microsoft's invention on VB, the 'p-code', it's a delicious bite for reverse engineers. I'll show that a 'p-compiled' application may be easier to crack that a conventional compiled one.
不知是不是我孤陋寡聞,總覺得現在關於VB P-CODE的資料少之又少,不管國內國外只能找到各位老大們為數不多的幾篇教程(很多也是說“我猜想”之類拿不準的話),《加密與解密》上關於這個也是一筆帶過(大概是為續集著想^_^),可能是大蝦覺得這個太簡單不屑於講,或是哪裡已經有非常系統全面的介紹。總之以前我是一見是VB就害怕,再見是PCODE就投降,這大概就是人家用P-CODE對付破解的原因。這幾天終於下決心自己寫了幾個程式試驗,再結合各位老大的文章,總結出一點東西,非常不全面,希望大家多多指教,多多補充。
“工欲善其事,必先利其器。”那句古話好像是這麼說的。我們找的工具有:WKTVBDebug(動態破解用,相當於PCODE裡的SOFTICE)EXDEC(靜態分析,相當於W32DASM)SmartCheck(可以作輔助用)
要想破解PCODE程式,關鍵要理解裡面的“助記符”(它又不同於組合語言的“mnemonics”,我不知道該怎麼表示了)的作用,PCODE的助記符乍看上去很亂,好像比彙編還難,其實它們都是由幾部分組成的。比如CVarStr就是由三部分組成(詳見下文)。VB PCODE中常見的“助記符”如下面所示:(只總結出了一點,懇請各位補充)
表示資料型別的:
I2 ---- Integer,佔一個位元組的整數(彙編裡的BYTE)
I4 ---- Integer,佔兩個位元組的整數(彙編裡的WORD)
I8 ---- Integer,佔四個位元組的整數(彙編裡的DWORD)
UI4---- Unsigned Integer,無符號整數
UI8---- Unsigned Integer,無符號整數
R4 ---- Real,單精度實數(Single)
R8 ---- Real,雙精度實數(Double)
Str---- String,字串型別
Var---- Variant,變數型別。這就是BASIC特殊的地方,它允許使用者在使用變數前不進行宣告,這種不宣告的變數就用這種型別儲存,它可以包括數字、字串等各種型別。我看M$的這個玩意兒沒給使用者帶來方便,只能讓一些初學程式設計的菜鳥思維混亂,讓我們們破解時也非常鬱悶:(。它的儲存方式非常奇怪,比方說你看到一個VARIANT型別的資料被放到記憶體裡了,你跟過去找,結果什麼也找不到。看雪書上說應該D *(EAX+8),原來它真正的資料往後挪了8個位元組,真不知在搞什麼.....BTW:如果是一個數值型別的資料,它的地址向後移8個位元組即為真正的數值,如果是一個字串型的資料,它的地址向後移8個位元組即為指向一個UNICODE字串的指標。
表示堆疊操作的:(PCODE沒有暫存器,全部透過堆疊傳送資料,因此非常重要)
St ---- Store,把當前棧頂的資料放在記憶體裡
Ld ---- Load,把記憶體某處的資料壓入堆疊
Lit---- Literal,把一個“立即數”壓入堆疊
其它重要的:
C ---- Convert,資料轉換。如CI4I2即把BYTE擴充為WORD(I2->I4)
Eq ---- Equal,判斷是否相等,並把結果(0或1)入棧
Lt ---- 判斷是否小於
Gt ---- 判斷是否大於
Len---- 得到字串長度
跳轉指令:
Branch ---- 無條件跳轉
BranchT ---- 棧頂資料為真則跳
BranchF ---- 棧頂資料為假則跳
一些算術運算:
Add , Sub 等等應該都比較好認吧。
從一篇介紹PCODE的文章裡抄來一些,不知有沒有用:
Prefix Control
------------------------------------------------------------------------------------
cbo Combo box
chk Check box
cmd Command Button
dir Directory box
drv Drive list box
fil File list box
fra Frame
frm Form
grd Grid
hsb Horizontal scrollbar
img Image
lbl Label
lin Line
lst List box
mnu Menu
ole OLE client
opt Option button
pic Picture Box
shp Shape
tmr Timer
txt Text box
vsb Vertical scrollbar
-----------------------------------------------------------------------------------------
還有一些不太清楚的,都是我的猜想,希望大蝦解釋:
Call ---- 呼叫過程
Free ---- 釋放記憶體空間
Rf ---- 區域性變數????
Pr ---- ????
Ad ---- 是不是Address??
HardType--是幹什麼的?
這些組合在一起就成了多種多樣的指令,很有趣吧。
還有一個要特別強調的是PCODE的堆疊,PCODE幾乎所有的指令都要對堆疊進行操作,有許多指令都是針對棧頂的一個或兩個資料進行操作,因此在動態除錯PCODE時要十分注意右邊顯示的堆疊區,並經常檢視記憶體,這樣才能理解指令的意義。
下面來實踐一下,執行起塵封已久的VB,在FORM上放一個TEXT1,一個BUTTON1,雙擊Button1,在下面輸入:
Private Sub Command1_Click()
st1 = Text1.Text
st2 = ""
m = Len(Text1.Text)
For i = 1 To m
st2 = st2 + Mid$(Text1.Text, m - i + 1, 1)
Next i
MsgBox st2, vbOKOnly, "CRACK"
End Sub
呵呵,很簡單是不是。按一下按鈕就把TEXT裡的文字反過來顯示在訊息框裡。
下面來“生成工程”,注意一定要在“選項”裡選擇生成P-CODE檔案。然後用Exdec分析一下:
Proc: 401a90
4019B0: 04 FLdRfVar local_008C 好像是一個指向TEXT的指標
4019B3: 21 FLdPrThis 先給一個下馬威,前幾句全不太明白!
4019B4: 0f VCallAd text 用WKTVBDebug過這一句時能看到Form1.text1
4019B7: 19 FStAdFunc local_0088 猜想應該是取得控制程式碼之類的事情
4019BA: 08 FLdPr local_0088
4019BD: 0d VCallHresult get__ipropTEXTEDIT 呼叫,從字面上可以看出是GetText
4019C2: 3e FLdZeroAd local_008C 好像壓入一個指向上面文字的指標,不太清楚,反正上面這個過程很經典啦,幾乎從文字框讀數都是這樣
4019C5: 46 CVarStr local_00AC 把上面得到的字串轉為Var格式
4019C8: Lead1/f6 FStVar 再把這個VAR資料入棧 st1
4019CC: 1a FFree1Ad local_0088 釋放前面的空間
4019CF: 3a LitVarStr: ( local_00CC ) 壓入一個立即數:空字串st2=""
4019D4: Lead2/00 FStVarCopy
4019D8: 04 FLdRfVar local_008C
4019DB: 21 FLdPrThis
4019DC: 0f VCallAd text
4019DF: 19 FStAdFunc local_0088
4019E2: 08 FLdPr local_0088
4019E5: 0d VCallHresult get__ipropTEXTEDIT 和上面相同,得到字串
4019EA: 6c ILdRf local_008C 壓入字串
4019ED: 4a FnLenStr 得到字串的長度m
4019EE: Lead2/69 CVarI4 local_00CC 轉為VAR型別
4019F2: Lead1/f6 FStVar VAR型別的長度入棧
4019F6: 2f FFree1Str local_008C 釋放記憶體空間
4019F9: 1a FFree1Ad local_0088
4019FC: 28 LitVarI2: ( local_00FC ) 0x1 (1) 壓入一個立即數0x1
401A01: 04 FLdRfVar local_00EC local_00EC是迴圈變數i
401A04: 04 FLdRfVar local_00DC 這個是上面得到的長度m
401A07: Lead3/68 ForVar: (when done) 401A67 FOR i=1 to m 開始迴圈
401A0D: 04 FLdRfVar local_008C
401A10: 21 FLdPrThis
401A11: 0f VCallAd text
401A14: 19 FStAdFunc local_0088
401A17: 08 FLdPr local_0088
401A1A: 0d VCallHresult get__ipropTEXTEDIT 和上面相同的過程,得到字串
401A1F: 04 FLdRfVar local_00BC 把local_BC壓入,這實際上是st2
401A22: 28 LitVarI2: ( local_013C ) 0x1 (1) 壓一個0x1,CALL的引數
401A27: 04 FLdRfVar local_00DC 字串長度m
401A2A: 04 FLdRfVar local_00EC 迴圈變數i
401A2D: Lead0/9c SubVar 相減 m-i
401A31: 28 LitVarI2: ( local_00CC ) 0x1 (1) 再壓入一個0x1
401A36: Lead0/94 AddVar local_012C 再加1, m-i+1,CALL的引數
401A3A: Lead1/22 CI4Var 轉成整數型
401A3C: 6c ILdRf local_008C 壓入,作為下面CALL的引數
401A3F: 0b ImpAdCallI2 這是rtcMidCharBStr,原始碼中的Mid$()
401A44: 46 CVarStr local_014C 把取得的字元轉成Var型
401A47: Lead0/94 AddVar local_015C 把新取得的字元和上面的401A1F處的st2連起來
401A4B: Lead1/f6 FStVar
401A4F: 2f FFree1Str local_008C
401A52: 1a FFree1Ad local_0088 釋放
401A55: 36 FFreeVar
401A5E: 04 FLdRfVar local_00EC 設好迴圈變數
401A61: Lead3/7e NextStepVar: (continue) 401A0D NEXT i,迴圈變數+1,直到結束
401A67: 27 LitVar_Missing VB裡面那些帶[]的可選引數,如果不加設定
401A6A: 27 LitVar_Missing 就會變成這種Missing或NULL的形式
401A6D: 3a LitVarStr: ( local_00CC ) CRACK 壓入字串,MsgBox的標題
401A72: 4e FStVarCopyObj local_00AC 把剛壓入的字串複製到local_AC
401A75: 04 FLdRfVar local_00AC 再壓進去一次(???)
401A78: f5 LitI4: 0x0 0 (....) 訊息框的樣式 vbOKOnly
401A7D: 04 FLdRfVar local_00BC 這是上面計算得到的反轉字串
401A80: 0a ImpAdCallFPR4: 這個是rtcMsgBox,共有五個引數
401A85: 36 FFreeVar
401A8E: 13 ExitProcHresult 結束過程
我儘量想把分析寫得明白一些,但還是有幾句解釋不清,希望精通PCODE的大俠解釋一下,小弟代表廣大菜鳥同胞感激不盡。
相關文章
- 關於破解以p-code方式編譯的VB程式一例 (2千字)2002-04-01編譯
- 關於Mysql使用的一些總結2019-05-10MySql
- MySql關於鎖的一些總結2021-10-15MySql
- 關於繼承的一些小總結2014-02-28繼承
- 關於EM配置的一些總結2015-04-04
- 關於BUFFER POOL的一些總結2007-04-01
- 關於Oracle塊的一些總結2009-09-15Oracle
- 關於Code Review的一些思考總結2019-04-30View
- 總結關於CPU的一些基本知識2019-07-06
- 關於sqlplus用法的一些總結2015-06-03SQL
- 關於查詢轉換的一些總結2008-04-28
- 關於 變址影像(indexed image) 的一些總結2023-01-21Index
- 關於字元函式的一些應用總結2015-04-05字元函式
- 關於使用者體驗的一些總結2011-12-05
- 關於查詢最佳化的一些總結2024-04-09
- 關於DDD和COLA的一些總結和思考2024-05-10
- 有關VB程式P-CODE程式碼逆向工程入門淺說2015-11-15
- 關於學習 Linux 系統結構的一些總結2020-12-03Linux
- 關於程式和執行緒 自我的一些總結2019-05-09執行緒
- 關於分割槽表Local索引Rebuild的一些總結2009-12-26索引Rebuild
- 【原創】VB
P-code -- 虛擬碼的奧祕2004-12-26
- 關於近期的總結2018-03-20
- 關於UIWebView的總結2016-10-06UIWebView
- 關於BeautifulSoup的總結2016-04-11
- 關於HTML的總結2015-04-12HTML
- 關於學習-Linux-系統結構的一些總結2020-12-03Linux
- 一些關於VB中字串操作的問題和回答 (轉)2008-05-27字串
- 微信小程式關於分享一些簡單總結2018-10-09微信小程式
- 關於前端工程化(基建)的一些總結和思考2020-03-01前端
- 關於集合中一些常考的知識點總結2019-03-10
- android 關於記憶體優化的一些總結2019-01-10Android記憶體優化
- 關於程式碼質量度量和分析的一些總結2023-12-10
- 關於電腦(window)後門檢視的一些總結2018-01-24
- 關於個人開源專案(vue app)的一些總結2017-09-21VueAPP
- 【原創】VB
P-code -- 虛擬機器的藝術2004-12-26虛擬機
- VB課本總結2013-06-13
- sqlserver關於always on的總結2019-12-31SQLServer
- mysql關於variable的總結2018-09-29MySql