1. 程式人生 > >手動修改PE檔案:新增自定義程式碼

手動修改PE檔案:新增自定義程式碼

在PE檔案裡有很多位置可以新增自己的程式碼(其實就是感染PE),凡是用不到的地方都能加。想到的位置有(在檔案中不是在記憶體中):Dos頭和Nt頭之間、每個節末尾的Padding(間隙)、新增節分配在檔案末尾的空間;其它覆蓋資料的方法不安全容易引起錯誤還是算了。新增後還要在程式中設定跳轉以執行自己的程式碼,有用跳轉和改入口點的方法。總之方法很多,下面舉個例子:

1. 準備

在這裡我要加的程式碼功能為:彈出一個對話方塊,關掉對話方塊後就執行一個計算器。這個需要涉及到的問題是,彈出對話方塊和執行程式的函式未匯入,對話方塊顯示的字串和執行計算器的路徑放的位置。對於不設定匯入表和不設定資料段的方法,看了一下我測試用的程式,PE頭是夠寫這些的。不過現在要說到寫Shellcode就有點跑題了,以後再說,在這裡先記一下,雖然在這裡用那個會比較簡單(前面的內容都可以跳過了),不過相對簡單的東西另有自己的一個複雜度,還是換一篇來說比較好。現在用的是設定匯入表並把資料放到資料段的方法,這個方法需要設定重定位,有可能需要新建重定位表。那麼現在先開始寫程式碼。 測試程式的情況是這樣:



2. 設定匯入表和資料

編之前需要確定要呼叫的函式在哪和要使用的字串在哪,不然沒辦法編。所以先新增函式匯入。匯入表是一個IMAGE_IMPORT_DESCRIPTOR陣列,陣列包括兩個Thunk陣列的rva,陣列後直接跟了會用到的一些字串,所以想在匯入表中新增一項新的匯入,只能在相應的陣列後新增,但是這個結構儲存的十分緊湊,所以需要重建。 重建匯入表有三種思路:在原先位置重建、在新節重建、在空的位置重建。在原先位置重建難度很大,不過可以讓程式顯得好像沒有被改過一樣;在新節重建就比較簡單,不過多了一個節,文件大小也可能會增加(如果找程式中空的位置重建的話就不會增加,不過就相當於第三種方法了);在空的位置重建就是找節後的Padding,在那裡新增就行了,這樣就不會出現新的節。 後兩種方法都會修改到資料目錄的匯入表RVA,改動的東西比較明顯;第一種方法不用改RVA,但是如果添加了過多匯入函式的話,原先的節可能放不下,第二種就可以隨便放。折衷來看在現在的情況下還是第三種比較方便一些(= =其實直接用Shellcode的方法哪有那麼麻煩,如果已經準備好了程式碼就直接跳到後面就行了,我前面說的是不用那種的方法)。 新建節的話需要確定節有可寫屬性,載入的時候Thunk會被修改。新建節主要就是重建IMAGE_IMPORT_DESCRIPTOR陣列就行了,複製原先的陣列然後在末尾加上自己的匯入IMAGE_IMPORT_DESCRIPTOR結構,兩個Thunk和名字什麼的在自己的節中找個位置再設定好Rva就行。 需要匯入的兩個函式為User32.MessageBoxA、Kernel32.WinExec,所以我這樣設定:

這是修改後載入看到的樣子:
然後修改匯入表rva為新的位置就行了。 需要記住兩個地址,0x00006c8 - MessageBoxA、0x000006e8 - WinExec。 建立資料:
記下地址0x00000800 - 0x00000820 載入OD可以看到已經修改成功(程式的程式碼也截進來了):

3. 寫程式碼

為了避免重複寫內容,直接寫在PE頭裡吧。寫的程式碼需要儲存原先的現場,不然影響了其它東西程式會出錯。另外PE頭會比其它地方多出一個限制,就是我們從0x02開始寫,所以0x3A要跳過。程式碼需要放在一個可執行的節,一般方法是直接放程式碼段或者找空隙設定屬性或者新建節。我新建個節吧。
然後我偷懶用OD來寫一下程式碼吧,注意跳過0x3A就行。裡面的地址後面要轉一下。

程式碼比較短,沒過3A,白操心。如果是動態取函式的地址的可能會超過。可以看到裡面的重定位位置錯了,我之前寫完了一次,發現引數忘記壓了一個,後面改的,所以重定位還是原來的位置,根據這個原來的位置有人可以看出我原先少壓了哪個引數嗎?= = 需要記下地址0x00405002、0x00405006、0x0040500B、0x00405013、0x0040501A、0x00405020。把二進位制複製出來,修改相應地址的值,我這裡基址沒有被重定位,所以裡面的地址就不用改了,如果被重定位了就改成程式基址對應的值。改完寫回程式,我不用OD寫回,直接改二進位制檔案:

4. 重建/新增重定位表

需要重定位5個地址,因為是在新節,直接加重定位表就行了,如果在舊節,就要重建,因為陣列加元素後面的要往後移。5個地址因為對齊關係新加的重定位結構要佔20位元組,所以這樣:
改一下重定位表大小:
在CFF看到的樣子:

5. 修改跳轉

要麼改入口點,要麼在程式中跳轉。在程式中轉我覺得會跟後面說的東西重複,直接改入口點好了。
改完載入OD看看:
可以看到重定位位置正確,其它也正確,沒什麼可說的了。放到其它任何一個節裡都是可以的,設定好屬性就行了。 執行,關掉那個彈出框就執行計算器,不多截圖了: