用C++實現的殼(基礎版)
阿新 • • 發佈:2019-01-19
最近一直在15PB學習,現階段學的主要是關於殼的知識,正好現在也在做殼這個階段專案,用了2天的時間實現了一個基礎版的C++寫的殼,拿出來跟大家分享一下,程式碼量不多,但知識點不少,適合新手學習提高~
殼的流程看上去並不複雜,但需要的是你對PE檔案有一定的瞭解,在瞭解了一些關於匯入表、匯出表、重定位表、IAT等基礎知識以後方可寫出一個具有基本功能的殼。但如果想要寫一個加密、壓縮或者相容性很強的殼的話,絕對不是一件容易的事,此貼只是簡單實現了殼的基本載入流程,展現的殼都做了哪些基礎操作,關於更高技術的加密、反除錯、壓縮等技術暫不討論,可能過後我會發一個講述如何在此版本上進行一些拓展,實現如IAT加密、IAT-Hook、花指令、反除錯等功能的殼。
此專案的參考書目:《黑客免殺攻防》(任曉琿)、《加密與解密 第三版》(段鋼)
基礎版殼所實現的功能:
1.在原程式中新增一塊區段,將殼部分的程式碼移植進去。
2.在程式啟動前優先獲得控制權,執行完自己的程式碼以後再將控制權交還給原程式。
3.對程式碼段進行簡單的亦或加密。
4.對原程式的匯入表(IAT)進行修復。
5.如果原程式開啟了隨機基址,則對源程式進行重定位修復。
專案分為兩部分,第一部分為加殼程式(Pack),第二部分為外殼程式(Shell.dll)。
其中涉及到的重點是修復匯入表和重定位表,這是加殼後的程式能夠正常執行的基礎,下面我就針對每個部分單獨展開來說。
為縮減篇幅,詳細的程式碼就不在此貼出,只貼一些比較重要的程式碼,具體每個功能所用到的程式碼我會標註出在原始碼的哪個檔案。
第一部分:加殼部分的編寫
先說一下檔案加殼前後的變化:
上圖簡單的示意了加殼前後的PE檔案變化,首先是多出了一個區段,用於存放Shell部分的程式碼,再就是入口點變為了Shell部分的入口點,這樣保證能夠先執行我們殼部分的程式碼,執行我們想要的操作,最後就是跳回到原始程式的OEP,開始執行原始程式。
流程看著簡單,但如果能夠讓一般的PE檔案正常執行,需要注意的細節還是很多的,下面我就來詳細道來。
框架:在一個普通的MFC新建工程基礎上,自己添加了兩個類,一個為Pack類,另一個為PE類。 MFC自帶工程僅僅負責介面,加殼的主要流程是在Pack類裡,在加殼過程中需要對PE檔案操作是,就呼叫PE類中的函式來實現。
加殼部分的流程(此流程在Pack類中的Pack()函式中實現):
1.讀取檔案PE檔案資訊並儲存
2.加密程式碼段操作
3.將必要的資訊儲存到Shell (Pack部分和Shell部分的資料交換)
4.將Shell部分附加到PE檔案
5.儲存檔案,完成加殼
6.釋放資源
具體實現:
1.讀取檔案PE檔案資訊並儲存
要為一個PE檔案加殼,首先就是要了解這個PE檔案。那麼就需要把這個檔案讀到記憶體中,載入到記憶體中的方式有兩種,一種是以檔案對齊的方式讀到記憶體,也就是直接讀取檔案的二進位制資料,另一種方式是以記憶體對齊的方式讀到記憶體,或者其實就在模擬程式執行時的記憶體分部,我選擇的是第二種,以記憶體對齊的方式讀到記憶體,這樣的好處就是在對PE檔案進行操作的時候,不需要將相對虛擬地址(RVA)轉換為檔案偏移(ROffset),操作起來也更直觀,直接就是記憶體中的偏移地址。讀取檔案的程式碼詳見原始碼PE類中的InitPE(CString strFilePath)函式,或者參考《加密與解密 第三版》第443頁內容。
將檔案讀取到記憶體以後,下一步就是獲取我們關注的資訊並儲存了,資訊儲存在PE類中的成員變數中,這樣在Pack類中只需要定義一個PE類的物件,即可呼叫這些資訊。
我儲存的關鍵資訊有:儲存PE檔案的緩衝區的指標,PE檔案的NT頭指標、映象大小、映象基址、OEP地址、區段數量以及重定位表、匯入表指標資訊。這裡儲存的資訊其實越詳細越好,方便以後拓展功能的時候能夠用到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |