日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实战DLL注入

發布時間:2023/12/31 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实战DLL注入 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方關注 “終端研發部

設為“星標”,和你一起掌握更多數據庫知識

來源:https://bbs.pediy.com/user-home-919002.htm

一摘要


使用vs2019編寫注入器程序, 在生成的注入器可用前, 踩了不少坑, 因此記錄一下。


本文涉及三種惡意代碼注入方法: 直接dll注入, 反射式dll注入, 鏤空注入。之所以選這三種注入方法, 是因最近在做一個檢測進程內存空間以期發現代碼注入的程序, 而實驗發現這三種方法對目標進程的改變各有特點:


直接dll注入: 還有APC注入, 本質都是在目標進程中執行LoadLibrary函數, 因而在枚舉目標進程的模塊列表時可看到注入的dll。


反射式dll注入: 這種方法也會在目標進程中開辟新的內存空間并寫入代碼。但因為沒有調用LoadLibrary, 所以枚舉目標進程的模塊列表并不能看到注入的dll。(意味著目標進程的PEB沒有變化)。


鏤空注入: 直接改進程中某一模塊的內存空間, 或者先注入一個合法模塊, 再鏤空該模塊。因為該方法沒有注入惡意dll, 所以直接枚舉目標進程的模塊列表也無法發現惡意代碼, 需掃描進程的內存空間。


標了注:的地方基本都是踩的坑。


二直接注入


示例: LibSpy項目的OnMouseMove和InjectDll


流程:


1、OpenProcess打開目標進程(一參為PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE| PROCESS_VM_READ, 后面CreateRemoteThread才能執行)。

需要給進程提權, 得到SeDebug權限。

(1)注:?準確地說不是提權, 而是將訪問令牌中禁用的權限啟用。成功調用下面幾個函數的前提是進程具備該權限, 只是訪問令牌中沒有啟用該權限。而如果進程沒有該權限, 則使用下面的函數后再調用GetLastError會返回ERROR_NOT_ALL_ASSIGN。


(2)先用LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid)得到用戶的debug權限。


(3)然后用OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES,&hToken)獲取進程的令牌句柄。


(4)最后用AdjustTokenPrivileges啟用特權。

若要打開關鍵進程(csrss.exe等), 需在驅動中打開, 去掉關鍵進程的EPROCESS中的PsIsProtectProcess標志位, 并關閉dll簽名策略。(參考開源項目blackbone)


2、獲取待注入的dll路徑, 在目標進程內分配一塊內存(VirtualAllocateEx), 將路徑拷貝到該內存中(WriteProcessMemory)。


3、獲取kernel32中的LoadLibraryA地址(如果dll路徑是寬字符串, 則用LoadLibraryW)。


4、調用CreateRemoteThread, 在目標進程中執行LoadLibrary, 進而執行DllMain函數中的目標代碼。


注意, 因為VirtualAllocEx返回的是虛擬地址, 默認情況下CreateRemoteThread函數的lpStartAddress參數使用該地址是沒問題的。但是若注入器是32位而被注入程序是64位, 則可能導致CreateRemoteThread失敗而返回NULL。參考: createremotethread-returns-null-while-trying-to-use-it-to-inject-dll(https://stackoverflow.com/questions/60687458/createremotethread-returns-null-while-trying-to-use-it-to-inject-dll)


三反射式注入(reflective injection)


概要


沒有使用LoadLibrary函數注入dll。


需由注入器自行解析PE文件:

將dll頭部(包括DOS頭, PE頭, 區塊表)逐字節寫入新開辟的內存。

按重定位表的信息手動重定位。

修復導入函數表: 使用LdrLoadDll得到shellcode需要的庫的內存地址, 用LdrGetProcedureAddress得到要導入的函數的內存地址, 然后將這些地址填入導入表。

流程


1、將自己實現的LoadLibrary功能函數保存為shellcode。


注: 在shellcode中使用的系統api都要事先通過GetProcAddress獲取(使用GetModuleHandleA獲取模塊句柄, 傳入的模塊名不用后綴), 并作為參數傳給shellcode。


注: 需要審查注入器保存的shellcode是否是真實的函數體。調試發現在vs2019中, 按默認選項編譯得到的函數地址處是一條跳轉到實際函數體的jmp指令。因此需要使用jmp指令的操作數計算實際函數地址。如下為獲取一個shellcode函數的代碼:

// shellcode函數 void shellcodeFunc(PMY_PARAMS pParams) {// pParams保存LdrLoadDll等系統api的內存地址// 用NtAllocateVirtualMemory在目標進程中開辟一塊內存(需指定PAGE_EXECUTE_READWRITE權限)// 將dll的文件內容寫入開辟的內存// 修復導入表; 重定位// 執行dll的入口函數DLLMain }DWORD size = 0, ssss=0;// 獲取jmp指令后的雙字操作數(即jmp的目的地址偏移) DWORD* jmpAddr = (DWORD*) ((BYTE*) shellcodeFunc + 1);// 加5得到jmp指令的下一條指令地址, 然后加上jmp的目的地址偏移, 得到函數體的實際起始地址 WORD* Memx0 = (WORD*) ((BYTE*) shellcodeFunc + 5 + *jmpAddr); LONG_PTR* Memx = (LONG_PTR*) Memx0;// 用0xCCCCCCCCCCCCCCCC作為函數體結束識別標識. while (*Memx != 0xCCCCCCCCCCCCCCCC) {Memx++;size += 8; }// 將shellcode寫入文件 HANDLE hFile = CreateFile(LOADECODE, GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, NULL, NULL); if (hFile) {WriteFile(hFile, Memx0, size, &ssss, NULL);CloseHandle(hFile); }


注: 用windbg調試遠程線程, 發現遠程線程中出現地址訪問沖突:

原因1: 出問題的地方試圖讀取__security_cookie。


解決: 編譯時關閉/GS選項, 禁用棧保護。


原因2: 遠程線程中試圖調用一些不可用的函數, 包括__CheckForDebuggerJustMyCode, _RTC_CheckStackVars。


解決: 禁用/JMC選項, /RTC選項, 其他的如果是必要使用的動態庫函數, 則需要用LoadLibrary和GetProcAddress獲取, 且要確保目標進程已載入相應dll。

注: shellcode函數中不要用字符串常量, 因為在vs2019中調試發現這些字符串總是存在注入器進程的數據區而非棧上, 這樣一來shellcode在運行時無法獲取字符串(畢竟注入并運行的shellcode在目標進程而非注入器進程)。在shellcode中最好還是通過傳參的方式獲取需要用到的字符串常量。

2、在目標進程中開辟新內存, 依次寫入:

(1)要注入的dll的文件內容。


(2)shellcode。


(3)傳給shellcode的參數, 主要是shellcode需要的如下系統api的函數地址:

LdrLoadDll: 獲取注入的dll依賴的dll的內存地址。

LdrGetProcedureAddress: 獲取注入的dll需導入的函數的內存地址。

RtlInitAnsiString RtlAnsiStringToUnicodeString RtlFreeUnicodeString: 用以配合上述兩個函數, 得到導入函數的內存地址。

NtAllocateVirtualMemory: 分配內存空間, 以寫入要注入的dll的文件內容。


3、創建遠程線程, 執行shellcode, 由shellcode載入dll。


優點

僅枚舉進程模塊列表并不能發現注入的dll。

四鏤空(hollowing):


概要:


兩種方式:

(1)鏤空已有進程模塊: 直接修改進程中已有模塊的代碼節, 注入惡意代碼.


(2)先注入后鏤空: 注入一個合法dll(擁有合法簽名), 然后修改dll入口點處代碼為自己想執行的代碼。

下面只講先注入dll后鏤空的方法。


流程


1、首先, 如普通的dll注入, CreateRemoteThread創建遠程線程, 執行LoadLibrary注入一個dll, 不同的是注入到進程的是一個合法dll(比如system32目錄下的dll)。


2、EnumProcessModules枚舉進程模塊, GetModuleBaseNameA得到每個模塊的名稱, 從而找到注入的dll。


3、注入器進程中分配0x1000的內存空間(可用malloc或HeapAlloc), 然后將找到的dll的PE頭部內容讀進來。


4、由PE頭中的optional頭得到目標dll的入口地址, 加上枚舉模塊時得到的dll的基址, 得到實際dll入口地址, 并用WriteProcessMemory向該地址寫入shellcode。


注: 通過windbg調試發現, 注入入口地址不一定能成功執行shellcode, 因為DllMain函數可能多次執行。如果只想執行一次shellcode, 可把shellcode及其寫在dll的末尾對齊空間。


如同反射式dll注入, 生成shellcode的方法也是在注入器中定義shellcode函數并獲取其機器碼。

5、創建遠程線程, 并以寫入shellcode的地址為線程執行地址。


優點


無需將惡意dll保存在磁盤中, 可躲避靜態查殺。

回復?【idea激活】即可獲得idea的激活方式 回復?【Java】獲取java相關的視頻教程和資料 回復?【SpringCloud】獲取SpringCloud相關多的學習資料 回復?【python】獲取全套0基礎Python知識手冊 回復?【2020】獲取2020java相關面試題教程 回復?【加群】即可加入終端研發部相關的技術交流群用 Spring 的 BeanUtils 前,建議你先了解這幾個坑!lazy-mock ,一個生成后端模擬數據的懶人工具在華為鴻蒙 OS 上嘗鮮,我的第一個“hello world”,起飛!字節跳動一面:i++ 是線程安全的嗎?一條 SQL 引發的事故,同事直接被開除!!太扎心!排查阿里云 ECS 的 CPU 居然達100%一款vue編寫的功能強大的swagger-ui,有點秀(附開源地址)相信自己,沒有做不到的,只有想不到的在這里獲得的不僅僅是技術!喜歡就給個“在看”

總結

以上是生活随笔為你收集整理的实战DLL注入的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。