旁路保護(I):Reversing和重構受保護的dll

專欄地址一葉知安 - 知乎專欄

0x00 前言

本文將講述如何繞過在實施中有一些缺陷的保護。

在這個例子中,我們會看到一個使用asprotect保護的dll,並使用一個簡單的方法來重新創建它。

由於這個受保護的dll只執行許可證檢查程序,我們很容易在Delphi重建dll,繞過所有保護。

有些應用程序的作者喜歡將所有的許可證管理代碼放入單個dll中,應用程序的所有模塊都引用它來確定它是否被註冊。

由於這將處理所有許可證管理,所有這便會是程序中的弱點。

我們將逆向這個小dll,並重新構造delphi中的所有函數和過程,以便他們總是返回正確的值。

出於保護原因我不會在過程中提到該程序的名字,但是足以熟悉這個「套路」

0x01 正文

下載應用程序。運行時,彈出此窗口。用protectedID檢測目錄,就會發現,名為ba8pro的dll被ASProtect保護。讓我們在PETools中查看ba8pro的導出表,看看它包含了什麼函數和執行過程。

我們可以看到,這包含了4個過程。如果我們檢查主可執行文件,我們看到沒有對這個DLL的導入引用,並且在啟動時,這個DLL不在內存中。

這意味著它可能使用LoadLibrary函數載入此DLL,並使用GetProcAddress獲取過程VA。

這種情況,我們可以通過簡單地搜索函數名的字元串引用來找到這些過程的名稱。

當我們在OllyDbg中載入主可執行文件時,我們可以看到主程序中引用的ba8pro dll。

下面我們可以看到CheckVersion和CheckDays的引用。

在標記為Call To CheckVersion的點之後,我們注意到在調用此函數之前沒有任何東西被推入堆棧。

因此,我們可以得出結論,CheckVersion函數不接受參數。

然後,我們將$ FFFFFFFF的值返回到EAX並將其存儲在5D9B04。

由於我們將完整的EAX寄存器移動到這個值,我們可以得出結論CheckVersion返回一個整數。

嘗試之後,我發現如果我們從CheckVersion返回0,它將作為註冊運行。

因此,我們可以在Delphi中重新創建這個dll函數,如下所示:

Function CheckVersion(): Integer; stdcall;nBeginnResult:=0; //pronEnd;n nThe next function CheckDays works the same way. It does not take parameters and returns the number of days as an integer. We can declare it like this:n nFunction CheckDays():Integer; stdcall;nBeginn Result:=255; //Any value greater than 0 and <= $7FFFFFFF will work nEnd;n

讓我們在這裡切換斷點,運行應用程序,轉到幫助,然後單擊關於按鈕。

這會導致ollydbg在這裡被打斷。

一旦我們下到調用,我們意識到一個值在進入這個調用之前被推入堆棧。

記下該值。讓我們進入這個常式,來了解這個過程到底發生了什麼。

在步驟結束之後,我們發現推送到堆棧的值是一個指向一個Unicode字元串值的指針,該字元串值將填充將出現在about表單上的註冊信息字元串。

此常式不向EAX返回值,因此我們可以得出結論,這是一個程序。

使用這個程序,我發現如果註冊它將返回以下字元串:

Procedure GetModeVersion(s:pWideString); stdcall;nBeginns^:=Registered Version+#13+Single User License+#13+Lifetime Free Upgrades; //Write to the String.nEnd;n

最後,我們將看看最終的函數RegisterApplication。

由於我們默認使這個註冊,這個功能我們不使用,但我們將添加這反正來完成DLL。

讓我們重新啟動應用程序。

在快速字元串搜索之後,我們可以找到對RegisterApplication的調用。

讓我們運行應用程序並輸入一些隨機註冊詳細信息。

我們可以看到,這是傳遞兩個字元串到函數。

當我們從這個常式返回時,我們看到a1被填充0.由於下一個函數測試a1是否等於0,我們可以確定a1是一個布爾值,其中0 =假和1 =真。

這意味著RegisterApplication函數接受兩個常量(不變)字元串作為參數,並返回一個布爾值。

我們可以這樣重建這個函數:

Function RegisterApplication(CONST s,s2:string):Boolean; stdcall;nBeginnResult:=true;nEnd;n

現在我們已經重構了這些代碼,執行效果如下

剩下要做的是將目錄中的dll替換為我們創建的dll,修補模塊中的完整性檢查,並在註冊表中添加假key即可。

譯自Bypassing Protections: Reversing and Recreating a Protected DLL


推薦閱讀:

巧破「加密狗」
安卓逆向入門(二)
開發常用軟體「激活碼」分享
為什麼幾乎所有的破解程序都會播放一些很奇葩的8BIT音樂?這些音樂是程序員自己創作的嗎?

TAG:软件逆向工程 | 信息安全 | 软件破解 |