iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Security

我逆向你逆向我的逆向工程膩系列 第 20

Dx20 - 遠程 DLL 注入工具解析

  • 分享至 

  • xImage
  •  

在上一篇中我們使用了一份 反射式 DLL 注入工具來對記事本進行注入攻擊,那來分析看看是工具是如何做到的。並且再試著跟著做一份,從中學習到程式的細節

分析

來簡略分析一下這個注入程式是甚麼運作的。

請搭配使用 :
https://github.com/UserExistsError/InjectDll/blob/master/InjectDll/InjectDll.cpp

  1. 首先,main 開始的地方檢查輸入是否合規,讀入整份 DLL檔案,並把 PID 轉為 DWORD

https://ithelp.ithome.com.tw/upload/images/20221004/20135675UX6vX2jYAZ.png

  1. 利用 OpenProcess() 來得到 具有全部權限 ( RWX )handle

https://ithelp.ithome.com.tw/upload/images/20221004/20135675HBzEzVjJgn.png

  1. 檢查位元為 x32 還是 x64

https://ithelp.ithome.com.tw/upload/images/20221004/20135675HNgXPJCG5s.png

  1. 利用 NT_header 來確認 DLL 格式是否正常,還有 DLL 跟目標 process 是否都是 32/64 位元。

https://ithelp.ithome.com.tw/upload/images/20221004/201356754NvTt97zss.png

  1. 選擇要載入的模式,並且載入相應 shell code 以加載 DLL。這個 shellcode 是用來替代 LoadLibary()reflective loader。公開於研究員 stephenfewer 提出的技術開源,並被 UserExistsError 轉化成 ShellCode。在這個篇章中先不討論這份技術的細節。
    https://github.com/stephenfewer/ReflectiveDLLInjection

https://ithelp.ithome.com.tw/upload/images/20221004/201356754DPwJRYzKF.png

  1. 透過 VirtualAllocEx() 來宣告被注入 process 的記憶體要花多少空間來放 ShellCode 與 DLL 檔案

https://ithelp.ithome.com.tw/upload/images/20221004/20135675zrgOMoFral.png

寫入 ShellCode 與 DLL 檔案

https://ithelp.ithome.com.tw/upload/images/20221004/20135675AsJbyyAJC3.png

  1. 取得 ntdllRtlCreateUserThread() 來用以建立 Thread,之後在上面申請與寫入的空間為目的。使用 RtlCreateUserThread() 來執行 Shellcode。得到的 Thread 就是我們在 DLL 上寫的程式,執行後進入主函式 DllMain()

https://ithelp.ithome.com.tw/upload/images/20221004/201356757A7Rzjncdy.png

臨摹

看完上面的程式碼後,也來依樣畫葫蘆的試著擷取重點功能,來仿照一份專屬於 x64 的注射器。

以下是我把關鍵功能集成下來並作了小修改的精簡版

請搭配使用 :
https://github.com/Dinlon5566/IT_Reverse_Engineering/blob/main/Dx20/InjectDll_R01.cpp

首先關於 ReadFileData() 這個 Function 這邊使用原版的程式

BOOL ReadFileData(WCHAR* filename, BYTE** buff, DWORD* size)

  • filename : DLL 檔案路徑
  • buff : 儲存位置
  • size : 儲存文件大小

那開始主函式 wmain() 的解說吧

  1. 確認參數與透過路徑呼叫 ReadFileData() 讀入 DLL 檔案及大小。

https://ithelp.ithome.com.tw/upload/images/20221004/20135675GtBqRSeN7F.png

  1. 將 PID 由 WCHAR* 轉為 DWORD,這邊直接使用 wcstoul 來轉化為數字。

https://ithelp.ithome.com.tw/upload/images/20221004/20135675owFnPlNvMY.png

  1. 取得 Process[PID] 具有全部權限的 HANDLE

https://ithelp.ithome.com.tw/upload/images/20221004/20135675LQRaXjjLo2.png

  1. 取得 loader ,shellcode 放置於 loader.h 中。之後就是把這個注入 process 中

https://ithelp.ithome.com.tw/upload/images/20221004/20135675X2vLsCdjQh.png

  1. 計算要宣告分配多大的空間 ( loader shell code + DLL file )放入指定 process 中。使用 VirtualAllocEx() 在步驟3時宣告的 Handle,並使該空間有 執行/讀/寫 權限。

https://ithelp.ithome.com.tw/upload/images/20221004/20135675uNe2KDmjPh.png

關於 VirtualAllocEx() 官方文件
https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex

  1. 利用 WriteProcessMenory()loaderdll file 寫入上個步驟宣告的空間。

https://ithelp.ithome.com.tw/upload/images/20221004/20135675uBxlCMwOqe.png

由於上面的指令不太直觀,我畫了一張圖來說明這邊的分配情況:
https://ithelp.ithome.com.tw/upload/images/20221004/20135675jjSWRXL3wS.png

主要先把 loader 寫入空間後再把 DLL 的資料放進去。

關於 WriteProcessMenory() 官方文件
https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory

  1. 在一開始宣告的時候有 typedef 了這個定義,他可以把位置轉化為 NTAPI*,並透過引數來直接執行。
    這邊透過 GetProcAddress() 來得到 ntdll 中的 RtlCreateUserThread() 位置,轉為 RTLCREATEUSERTHREAD 使他可以用 typedef 定義的方法來執行他。
typedef LONG(NTAPI* RTLCREATEUSERTHREAD)(HANDLE, PSECURITY_DESCRIPTOR, BOOLEAN, ULONG, SIZE_T, SIZE_T, PTHREAD_START_ROUTINE, PVOID, PHANDLE, LPVOID);

https://ithelp.ithome.com.tw/upload/images/20221004/20135675M6Tn9Nc3Wo.png

  1. 執行取得到的 RtlCreateUserThread() 位置,指定好引數後就可以產出 Thread 了,這個 Thread 會先執行 loadLibary shellcode,之後透過類似於 loadLibary() 的函式來執行 DLL。

https://ithelp.ithome.com.tw/upload/images/20221004/20135675JSQdvSQ19Y.png

那這個注入程式就到這邊完成。


後記

寫這一篇我花了好久調試…其中好多函數( 尤其是 WINAPI )是以前都沒碰過的東西很怕寫錯,不過之後感覺會很常碰到。大家加油 OwO/


上一篇
Dx19 - DLL遠程注入攻擊 !
下一篇
Dx21 - 修改PE強制加載DLL
系列文
我逆向你逆向我的逆向工程膩31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言