FineArt News

如何使用 APC 進行 DLL 遠端注入

要說明什麼是DLL注入之前,首先我們必須要先瞭解兩個名詞,一個是行程(Process),另一個是執行緒(Thread)。

我們一般在電腦上看到的程式,就是所謂的行程(Process),例如:WINWORD.EXE,EXCEL.EXE等,我們可以將行程看成一個多種資源的集合,包含程式碼、資料、記憶體、周邊、作業系統提供的資源等。如果擬人化的話,可以將行程看成一個家庭的組合,一個家庭中可能有電視、冰箱、床具、成員…等各種家具資源,這些資源都是屬於在這個家庭之中。

對應到程式設計者的角度,執行緒(Thread)才是真正的程式碼執行角色,我們可以將之比喻成家庭中的成員,是真正活動的基礎。可以粗略的類推家庭活動是一些成員利用資源的集合。成員各自活動行程之下,擁有多個執行緒(Thread)共同利用資源完成活動,這些執行緒才是程式活動真正的執行者。

我們一般瞭解的程式,例如:WINWORD.EXEEXCEL.EXE等,大多是一個行程(Process),其下包含了多個執行緒(Thread)。下面的例子說明 WINWORD.EXE 中包含了3個執行緒(Thread),每個執行緒都擁有自己的資源空間。

 

DLL 注入

DLL 注入是透過強制一個行程載入DLL,在另一個行程的位址空間內執行程式碼。DLL 注入通常由外部程式發動,在沒有預料到或無意識的方式影響另一個行程的執行。Windows作業系統使用虛擬記憶體技術,一般行程(Process)看到的記憶體位置都是虛擬的相對位址;執行行程(Process)時,由作業系統透過一些演算法對應到真實的記憶體位址。

這樣設計的主要目標,是讓執行中的各個行程(Process),都擁有自己的位址空間,讓各行程間不會互相干擾。所以我們可以發現即使WINWORD.EXE當掉,也不會影響到其他程式。Windows的設計讓各行程間完全隔離,使得DLL注入困難。例如:我們希望使用My.EXE將一個My.DLL注入到WINWORD.EXE的行程中,並且引發一個Thread4在WINWORD.EXE中執行。這樣的過程實作時會有很多挑戰。像是跨Windows行程(Process)間的壁壘,將My.DLL安插到WINWORD.EXE的行程之下,以及如何產生執行緒去執行My.DLL等

 

APC ( Asynchronous Procedure Call ) 異步過程調用

程式設計師應會瞭解一些常用的同步函數,例如:Mutex、Event…等,這些同步函數可以協助不同的執行緒(Thread)之間共用相同的資源。例如:下圖中Thread1、Thread2都想存取共用的Data,就需要使用同步函數,讓同一時間只能有一個Thread可存取Data。

如果使用APC那是使用不同的概念來建立同步,基本上每一個執行緒(Thread)都有一個APC鏈,APC鏈上可以掛載一堆待執行的程式,這些待執行的程式,必須等到對應的執行緒啟動時,才會一一執行APC鏈上的程式,到同上面的例子:當Thread1休眠後,Windows輪到Thread2時,會檢查Thread2中的APC鏈,並一一執行Thread2 APC鏈中的程式。

 

使用 APC 注入 DLL 的4個步驟
  • STEP_1:取得跨行程(Process)間壁壘的門票
    為了化簡這個問題,首先必須假設我們有足夠的權限,可以執行高權限的API。
    要跨過行程(Process)間壁壘,My.EXE可以使用OpenProcess(…”WINWORD.EXE 的PID”…)開啟一個行程(Process)的參考副本,如果我們有足夠的權限,My.EXE就可以透過OpenProcess的傳回值,取得另一個行程WINWORD.EXE的進入門票。
  • STEP_2:跨行程(Process)分配記憶體
    透過OpenProcess取得到門票,就可以控制WINWORD.EXE行程中的一些功能。其中一個就是My.EXE使用門票+VirtualAllocEx,要求取得遠端(WINWORD.EXE)的記憶體。在本文中,此記憶體的內容將在下一步時,放入My.DLL的檔案路徑。
  • STEP_3:將資料寫入跨行程(Process)記憶體
    在My.EXE中透過STEP_1取得WINWORD.EXE的進入門票,再由STEP_2在WINWORD.EXE中分配了記憶體,而在STEP_3,My.EXE會透過遠端寫入API WriteProcessMemory的功能,將之前分配的記憶體寫入資料,在本文中,這些資料就是My.DLL的檔案路徑。
  • STEP_4:使用 APC 啟動Thread
    每一個執行緒(Thread)都具有一個APC鏈,Windows在每個執行緒被喚醒時,會一一執行執行緒在APC鏈中的函式,所以我們只要在APC鏈中新增一個APC函式,就可以完成我們所需要的DLL注入的功能。

一般來說,我們必須先使用CreateToolhelpmnapshot取回執行緒(Thread)的快照,找出要注入的執行緒,再使用QueueUserAPC插入一個新的APC到這個Thread中,一但等到這個要注入的執行緒啟動後,就會自動執行這個新的APC中對應的程式。

 

綜合流程圖

 

本文簡單的分析了用APC注入DLL的基本原理,以第三者的角度觀察WINWORD.EXE,會以為WINWORD.EXE自發性的載入並執行My.DLL,實際上這是第三方的My.EXE的注入流程。