標籤:運行 文章 ascii href 混合編程 編譯器 元素 read source
最近想用VMProtect和ASProtect 的SDK加密一個程式,結果搞了半天沒搞成,網上沒看到在VC中如何使用VMProtect的SDK加密,於是琢磨了一下,總算成功了,最後有一點點心得,與大家共用,免得還有人跟我一樣走彎路。
其實VMProtect和ASProtect的SDK編程都差不多,都是在編程時在語句裡面插入一個標記(Marker),然後在加殼時,加殼程式就會認出這些標記,並在有標記的地方進行保護。 我覺得這就是最基本的所謂加殼程式SDK編程吧。
1. VMProtect
新版的VMProtect沒看到好用的,所以這裡用的VMProtect v1.2。 (有新的好用的請說一聲). 編譯環境 VS.Net 2003. 主要參考了文章. VMProtect SDK+ASProtect SDK混合編程[代碼示範] 作 者: Anskya 鏈 接: http://bbs.pediy.com/showthread.php?threadid=20317
1.1 保護內建函式
Delphi需要設定Map檔案,那VS.Net 2003也需要設定一下,以便產生Map檔案,使VMProtect能夠識別內建函式,如果沒Map檔案,VMProtect只能識別匯出函數,到時就要自己加函數的地址了.
VS.Net 2003中,開啟 "項目 -> project1屬性(假設項目名為project1) -> 連結器 -> 調試 -> 產生對應檔", 改成 "是(/MAP)",這樣產生程式時會同時產生project1.map檔案。 將project1.exe與project1.map 都拷貝到VMProtect程式夾,用VMProtect加密時,添加新的函數時能夠列出很多內建函式,這時只需要選擇想加密的內建函式就行了。 如果沒Map,只有個輸入函數地址的輸入筐,沒有內建函式列表。
這裡可以省去有些朋友為了加密某個函數,還要用Ollydbg剖析器,找到函數入口地址,然後輸入到VMProtect裡面來保護的麻煩。
1.2 保護任意位置代碼
在Anskya和那個俄國作者的首頁上都只說了Delphi在程式中加入SDK標記。在Delphi 中的標記模式為:
代碼:
[plain] view plain copy
- db $EB,$10,‘VMProtect begin‘,0 //標記開始處.
- end;
- //想保護的程式碼
- asm
- db $EB,$0E,‘VMProtect end‘,0 //標記結束處.
- end;
在Delphi中可以直接用這種類似MASM的組合語言,比較方便,但是在VC中不支援 db 語句,只支援插入單個位元組的 _emit 語句。 我琢磨出了一個比較麻煩的方法,就是全部插入16進位位元組碼,不曉得還有更好的方法沒。此方法學自ASProtect的sdk例子裡面的aspr.h。
在VC中的標記模式為:
引用:
[cpp] view plain copy
- __asm //標記開始處.
- {
- _emit 0xEB
- _emit 0x10 //jmp 0x10
- _emit 0x56 //ascii "VMProtect begin",0
- _emit 0x4D
- _emit 0x50
- _emit 0x72
- _emit 0x6F
- _emit 0x74
- _emit 0x65
- _emit 0x63
- _emit 0x74
- _emit 0x20
- _emit 0x62
- _emit 0x65
- _emit 0x67
- _emit 0x69
- _emit 0x6E
- _emit 0x00
- }
- //想保護的程式碼
- __asm //標記結束處.
- {
- _emit 0xEB
- _emit 0x0E //jmp 0x0e
- _emit 0x56 //ascii "VMProtect end",0
- _emit 0x4D
- _emit 0x50
- _emit 0x72
- _emit 0x6F
- _emit 0x74
- _emit 0x65
- _emit 0x63
- _emit 0x74
- _emit 0x20
- _emit 0x65
- _emit 0x6E
- _emit 0x64
- _emit 0x00
- }
將這一對標記插入到任何想保護的程式碼處就行了。 這種方法能夠深入函數內部,精確的保護想要保護的某一段代碼。在插入成功後,你可以在VMProtect加殼時選擇內建函式的地方找到這種函數 "VMProtectMarker1", 這就是使用了標記的地方,有多處保護的話這些函數數字會遞增,如 VMProtectMarker2, VMProtectMarker3 等. 記得選上這些函數再進行保護。
2. ASProtect
ASProtect的sdk編程相對來說比較好學,因為它帶了一個很詳細的說明檔案ASProtect.chm。這裡我相當於翻譯了一下這個檔案的一部分。我使用的 ASProtect SKE 2.2 Release build 0425 這個版本,安裝後不但有說明文檔,還有不少例子,其實看這些例子就能學會了,很簡單.
2.1 怎麼使用 ASProtect 標記
最近版本的ASProtect 支援在以下程式設計語言中的使用標記: Delphi, C/C++ 和 Visual Basic. 需要注意的是這些標記宏不能支援.NET語言和用PCode模式編譯的Visual Basic.
限制:
為了成功的將ASProtect標記插入到你的程式中,需要滿足以下幾個條件:
§ 多態變形標記(Polymorphic) 不能位於迴圈語句內,如 for, do while 等,
§ CRC檢查標記不能嵌套, 即不能在CRC標記內部又放一個CRC標記,
§ 位於registered sections(註冊區段) 和CRC檢查標記內的代碼至少需要5個位元組大小.
C/C++ 形式的標記是通過 include(*.h or *.inc files) 檔案夾來定義的,並在編譯後將會體現為一些特殊序列的彙編代碼,這些彙編代碼將會在加殼時被ASProtect自動偵測到.
你可以在ASProtect的安裝資料夾內找到怎麼使用標記的例子.
2.2 多態變形標記(Polymorphic Markers)
可以用多態變形標記保護程式內任意位置的代碼. 為了使用多態變形標記, 需要在你想保護的函數內部的任意位置插入一個變形標記執行個體。 例如:在函數內代碼的頂部放置多態變形標記。 從這個標記到函數結尾的所有代碼片斷都將被抹去,並被替換為多態變形類比體。 ASProtect 用模擬方式來改變這個函數的內容(如進入點保護), 所以將不可能恢複甚至於理解原來程式的工作原理。
為了使用新的程式碼片段保護,你需要插入新型的標記,如下所示:
代碼:
[cpp] view plain copy
- #include "include\aspr.h"
- VOID Test
- {
- USER_POLYBUFFER
- // some code
- }
注意! 為了避開那些在多態變形標記前改變程式邏輯的操作符,這個版本不支援在迴圈語句內使用標記,所以,請將這些標記放在迴圈體外面,不要使用類似下面的代碼:
代碼:
[cpp] view plain copy
- do {
- USER_POLYBUFFER
- // some code
- } while();
- // some code
2.3 外殼完整性檢查(Envelope Checks)
ASProtect直接將程式包裹在一個安全殼層內保護起來,這外殼包含所有的保護選項。所以檢查這個外殼是否存在或者檢查這外殼是否有被試圖手動移除,對於保護程式非常重要。 為了使用外殼檢查,需要插入兩種外殼檢查標記中的任一種,如下所示:
方式 1 - 如果ASProtect外殼被移除,它將會產生一個異常,你可以處理這個異常並在此時做一些邪惡的事情。 @[email protected]
代碼:
[cpp] view plain copy
- #include "include\aspr.h"
- MessageBox(0,"Begin","",0);
- #include "include\CppEnvelopeCheck.inc" //可以在任何位置插入這一句話.
- MessageBox(0,"End","",0);
方式 2 - 如果ASProtect外殼被移除,這種方式將會像函數一樣工作,返回一個false值。如果是false你可以做一些邪惡的事情。
代碼:
[cpp] view plain copy
- BOOL EnvelopeCheck() //這個函數放在程式前面就行了。
- {
- #include "include\CppEnvelopeCheckFunc.inc"
- }
-
- if ( !EnvelopeCheck() ) // .. 邪惡的事情
2.4 CRC 檢查
這一章只應用於可執行程式。 代碼區段的CRC檢查對於對抗載入程式(loaders)非常有效。所以如果你想設定一些額外的程式碼片段的CRC檢查,只需要在程式碼片段的開頭與結尾放置CRC檢查的標記,如下所示:
代碼:
[cpp] view plain copy
- #include "include\aspr.h"
-
- #include "include\cppCrcBegin.inc"
- // some code
- #include "include\cppCrcEnd.inc"
注意! 這個版本不支援嵌套的標記,所以不要使用下面的代碼方式:
代碼:
[cpp] view plain copy
- #include "include\aspr.h"
-
- #include "include\cppCrcBegin.inc"
- // some code
- #include "include\cppCrcBegin.inc"
- // some code
- #include "include\cppCrcEnd.inc"
- // some code
- #include "include\cppCrcEnd.inc"
還有各種註冊,到期時間的加密方式需要用到ASProtect的API方式,在那個協助文檔裡面都有,想用的就看看吧,這部分我還沒用到,所以沒翻譯了。以上的程式編譯好後,用ASProtect加殼會自動識別標記,在加殼過程中可以看到提示。
以上的SDK加密方式掌握後,就可以將ASProtect與VMProtect 隨便亂混合加密了(先用VMProtect,再用ASProtect),加密的強度應該蠻高的吧。 不過最好能讓你的程式能運行。
值得注意的是有些標記完全由位元組碼組成,加殼時有可能某個標記被其他標記的保護破壞了就會出問題。 所以同一個代碼片斷不要用很多標記一起搞,這些都要實驗的。
還有,有時候SDK編程出來的可執行檔不能直接運行,加過殼後才能運行。
補充:前面的VMProtect的SDK標誌如果用得不多還好,用得多的話最好define一下,精簡一點。 如下:
引用:
[cpp] view plain copy
- #define VMPBEGIN __asm\
- { \
- __asm _emit 0xEB \
- __asm _emit 0x10 \
- __asm _emit 0x56 \
- __asm _emit 0x4D \
- __asm _emit 0x50 \
- __asm _emit 0x72 \
- __asm _emit 0x6F \
- __asm _emit 0x74 \
- __asm _emit 0x65 \
- __asm _emit 0x63 \
- __asm _emit 0x74 \
- __asm _emit 0x20 \
- __asm _emit 0x62 \
- __asm _emit 0x65 \
- __asm _emit 0x67 \
- __asm _emit 0x69 \
- __asm _emit 0x6E \
- __asm _emit 0x00\
- }
-
- #define VMPEND __asm\
- { \
- __asm _emit 0xEB \
- __asm _emit 0x0E \
- __asm _emit 0x56 \
- __asm _emit 0x4D \
- __asm _emit 0x50 \
- __asm _emit 0x72 \
- __asm _emit 0x6F \
- __asm _emit 0x74 \
- __asm _emit 0x65 \
- __asm _emit 0x63 \
- __asm _emit 0x74 \
- __asm _emit 0x20 \
- __asm _emit 0x65 \
- __asm _emit 0x6E \
- __asm _emit 0x64 \
- __asm _emit 0x00 \
- }
有了上面的define,在需要加密的地方只需要兩句話就行了,可以到處多插一點:
代碼:
[cpp] view plain copy
- VMPBEGIN
- //需要加密的代碼片斷
- VMPEND
VMProtect選項介紹
其中各項的解釋:(具體參見使用說明,這裡只做粗略的解釋)
(1)記憶體保護:檢測實體的完整性,如果運行時發現不完整,將停止運行
(2)輸入表保護:這個選項將把程式中使用的API隱藏起來。
(3)壓縮輸出檔案:如果只是用VMProtect進行保護,可以將這項勾選,如果還會使用ASProtect進行保護,可以將這項去掉。(注意:如果ASProtect和 VMProtect一同使用,先使用VMProtect在使用ASProtect保護)
(4)檢測調試器:這個選項將組織調試器對程式的監控,在進入保護段的程式時,如果檢測到調試器將顯示資訊並結束程式運行
(5)虛擬工具:當程式運行在虛擬環境總是,將顯示ixnxi並結束程式運行
(6)VM區段,是在用PE Explore查看資源時的顯示,將預設的“.vmp”更改為“.upx”是為了迷惑一下使用的保護工具。
(7)偵錯模式:在VMProtect執行保護程式的編譯時間,會檢查程式中保護段的添加是夠正確,如果存在問題,會給出提示。
(8)檢查虛擬機器對象:在程式運行時,將檢測虛擬區段表的完整性和VMProtect的插入點,的完整性,如果不完整也不會給出提示,但是會將程式引入到錯誤的地址,從而導致程式錯誤甚至崩潰。
(9)離開虛擬機器時加密寄存器:將把VMProtect的輸出結果進行加密。
(10)隱藏常量:將阻止通過地址去查詢變數或者通過地址去找到一個call方法的地址,但是此選項對於字串沒有作用。
(11)移除固定元素:像delphi這樣的編譯器,將會產生一個固定元素的列表,但是這些元素對於作業系統執行程式來說是不會用到的,VMProtect將根據這個列表進行處理,只把在保護過程中需要的列表儲存下來。
(12)挪動資源到檔案尾部:將資源檔放到尾部,例片資源。
轉儲——如果在VMProtect的使用中存在嵌套使用的情況,在這個面板中,可以通過尋找“Unpaire”來定位。
完成編譯——點擊編譯按鈕,完成編譯。之後會在*.exe旁邊產生*.vmp和*.vms檔案,(如果添加了指令碼才會產生*.vms檔案)
轉:用VMProtect和ASProtect 的SDK加密應用程式