【安全技術(shù)】關(guān)于幾種dll注入方式的學(xué)習(xí)

何為dll注入

DLL注入技術(shù),一般來講是向一個(gè)正在運(yùn)行的進(jìn)程插入/注入代碼的過程。我們注入的代碼以動(dòng)態(tài)鏈接庫(DLL)的形式存在。DLL文件在運(yùn)行時(shí)將按需加載(類似于UNIX系統(tǒng)中的共享庫(share object,擴(kuò)展名為.so))。然而實(shí)際上,我們可以以其他的多種形式注入代碼(正如惡意軟件中所常見的,任意PE文件,shellcode代碼/程序集等)。

全局鉤子注入

在Windows大部分應(yīng)用都是基于消息機(jī)制,他們都擁有一個(gè)消息過程函數(shù),根據(jù)不同消息完成不同功能,windows通過鉤子機(jī)制來截獲和監(jiān)視系統(tǒng)中的這些消息。一般鉤子分局部鉤子與全局鉤子,局部鉤子一般用于某個(gè)線程,而全局鉤子一般通過dll文件實(shí)現(xiàn)相應(yīng)的鉤子函數(shù)。

核心函數(shù)

SetWindowsHookEx

通過設(shè)定鉤子類型與回調(diào)函數(shù)的地址,將定義的鉤子函數(shù)安裝到掛鉤鏈中。如果函數(shù)成功返回鉤子的句柄,如果函數(shù)失敗,則返回NULL

實(shí)現(xiàn)原理

由上述介紹可以知道如果創(chuàng)建的是全局鉤子,那么鉤子函數(shù)必須在一個(gè)DLL中。這是因?yàn)檫M(jìn)程的地址空間是獨(dú)立的,發(fā)生對(duì)應(yīng)事件的進(jìn)程不能調(diào)用其他進(jìn)程地址空間的鉤子函數(shù)。如果鉤子函數(shù)的實(shí)現(xiàn)代碼在DLL中,則在對(duì)應(yīng)事件發(fā)生時(shí),系統(tǒng)會(huì)把這個(gè)DLL加較到發(fā)生事體的進(jìn)程地址空間中,使它能夠調(diào)用鉤子函數(shù)進(jìn)行處理。

在操作系統(tǒng)中安裝全局鉤子后,只要進(jìn)程接收到可以發(fā)出鉤子的消息,全局鉤子的DLL文件就會(huì)由操作系統(tǒng)自動(dòng)或強(qiáng)行地加載到該進(jìn)程中。因此,設(shè)置全局鉤子可以達(dá)到DLL注入的目的。創(chuàng)建一個(gè)全局鉤子后,在對(duì)應(yīng)事件發(fā)生的時(shí)候,系統(tǒng)就會(huì)把 DLL加載到發(fā)生事件的進(jìn)程中,這樣,便實(shí)現(xiàn)了DLL注入。

為了能夠讓DLL注入到所有的進(jìn)程中,程序設(shè)置WH_GETMESSAGE消息的全局鉤子。因?yàn)閃H_GETMESSAGE類型的鉤子會(huì)監(jiān)視消息隊(duì)列,并且 Windows系統(tǒng)是基于消息驅(qū)動(dòng)的,所以所有進(jìn)程都會(huì)有自己的一個(gè)消息隊(duì)列,都會(huì)加載?WH_GETMESSAGE類型的全局鉤子DLL。

那么設(shè)置WH_GETMESSAGE就可以通過以下代碼實(shí)現(xiàn),記得加上判斷是否設(shè)置成功


這里第二個(gè)參數(shù)是回調(diào)函數(shù),那么我們還需要寫一個(gè)回調(diào)函數(shù)的實(shí)現(xiàn),這里就需要用到CallNextHookEx這個(gè)api,主要是第一個(gè)參數(shù),這里傳入鉤子的句柄的話,就會(huì)把當(dāng)前鉤子傳遞給下一個(gè)鉤子,若參數(shù)傳入0則對(duì)鉤子進(jìn)行攔截


既然我們寫入了鉤子,如果不使用的情況下就需要將鉤子卸載掉,那么這里使用到UnhookWindowsHookEx這個(gè)api來卸載鉤子


既然我們使用到了SetWindowsHookEx這個(gè)api,就需要進(jìn)行進(jìn)程間的通信,進(jìn)程通信的方法有很多,比如自定義消息、管道、dll共享節(jié)、共享內(nèi)存等等,這里就用共享內(nèi)存來實(shí)現(xiàn)進(jìn)程通信



實(shí)現(xiàn)過程

首先新建一個(gè)dll

在pch.h頭文件里面聲明這幾個(gè)我們定義的函數(shù)都是裸函數(shù),由我們自己平衡堆棧


然后在pch.cpp里面寫入三個(gè)函數(shù)并創(chuàng)建共享內(nèi)存


然后再在dllmain.cpp設(shè)置DLL_PROCESS_ATTACH,然后編譯生成Golbal.dll


再創(chuàng)建一個(gè)控制臺(tái)項(xiàng)目

使用LoadLibrabryW加載dll,生成GolbalInjectDll.cpp文件



執(zhí)行即可注入GolbalDll.dll

遠(yuǎn)程線程注入

遠(yuǎn)程線程函數(shù)顧名思義,指一個(gè)進(jìn)程在另一個(gè)進(jìn)程中創(chuàng)建線程。

核心函數(shù)

CreateRemoteThread

lpStartAddress:A pointer to the application-defined function of type?LPTHREAD_START_ROUTINE?to be executed by the thread and represents the starting address of the thread in the remote process. The function must exist in the remote process. For more information, see?ThreadProc).

lpParameter:A pointer to a variable to be passed to the thread function.

lpStartAddress即線程函數(shù),使用LoadLibrary的地址作為線程函數(shù)地址;lpParameter為線程函數(shù)參數(shù),使用dll路徑作為參數(shù)

VirtualAllocEx

是在指定進(jìn)程的虛擬空間保留或提交內(nèi)存區(qū)域,除非指定MEM_RESET參數(shù),否則將該內(nèi)存區(qū)域置0。



hProcess:申請(qǐng)內(nèi)存所在的進(jìn)程句柄

lpAddress:保留頁面的內(nèi)存地址;一般用NULL自動(dòng)分配 。

dwSize:欲分配的內(nèi)存大小,字節(jié)單位;注意實(shí)際分 配的內(nèi)存大小是頁內(nèi)存大小的整數(shù)倍。

flAllocationType

可取下列值:

MEM_COMMIT:為特定的頁面區(qū)域分配內(nèi)存中或磁盤的頁面文件中的物理存儲(chǔ)

MEM_PHYSICAL :分配物理內(nèi)存(僅用于地址窗口擴(kuò)展內(nèi)存)

MEM_RESERVE:保留進(jìn)程的虛擬地址空間,而不分配任何物理存儲(chǔ)。保留頁面可通過繼續(xù)調(diào)用VirtualAlloc()而被占用

MEM_RESET :指明在內(nèi)存中由參數(shù)lpAddress和dwSize指定的數(shù)據(jù)無效

MEM_TOP_DOWN:在盡可能高的地址上分配內(nèi)存(Windows 98忽略此標(biāo)志)

MEM_WRITE_WATCH:必須與MEM_RESERVE一起指定,使系統(tǒng)跟蹤那些被寫入分配區(qū)域的頁面(僅針對(duì)Windows 98)

flProtect

可取下列值:

PAGE_READONLY: 該區(qū)域?yàn)橹蛔x。如果應(yīng)用程序試圖訪問區(qū)域中的頁的時(shí)候,將會(huì)被拒絕訪

PAGE_READWRITE 區(qū)域可被應(yīng)用程序讀寫

PAGE_EXECUTE: 區(qū)域包含可被系統(tǒng)執(zhí)行的代碼。試圖讀寫該區(qū)域的操作將被拒絕。

PAGE_EXECUTE_READ :區(qū)域包含可執(zhí)行代碼,應(yīng)用程序可以讀該區(qū)域。

PAGE_EXECUTE_READWRITE: 區(qū)域包含可執(zhí)行代碼,應(yīng)用程序可以讀寫該區(qū)域。

PAGE_GUARD: 區(qū)域第一次被訪問時(shí)進(jìn)入一個(gè)STATUS_GUARD_PAGE異常,這個(gè)標(biāo)志要和其他保護(hù)標(biāo)志合并使用,表明區(qū)域被第一次訪問的權(quán)限

PAGE_NOACCESS: 任何訪問該區(qū)域的操作將被拒絕

PAGE_NOCACHE: RAM中的頁映射到該區(qū)域時(shí)將不會(huì)被微處理器緩存(cached)

注:PAGE_GUARD和PAGE_NOCHACHE標(biāo)志可以和其他標(biāo)志合并使用以進(jìn)一步指定頁的特征。PAGE_GUARD標(biāo)志指定了一個(gè)防護(hù)頁(guard page),即當(dāng)一個(gè)頁被提交時(shí)會(huì)因第一次被訪問而產(chǎn)生一個(gè)one-shot異常,接著取得指定的訪問權(quán)限。PAGE_NOCACHE防止當(dāng)它映射到虛擬頁的時(shí)候被微處理器緩存。這個(gè)標(biāo)志方便設(shè)備驅(qū)動(dòng)使用直接內(nèi)存訪問方式(DMA)來共享內(nèi)存塊。

WriteProcessMemory

此函數(shù)能寫入某一進(jìn)程的內(nèi)存區(qū)域(直接寫入會(huì)出Access Violation錯(cuò)誤),故需此函數(shù)入口區(qū)必須可以訪問,否則操作將失敗。



實(shí)現(xiàn)原理

使用CreateRemoteThread這個(gè)API,首先使用CreateToolhelp32Snapshot拍攝快照獲取pid,然后使用Openprocess打開進(jìn)程,使用VirtualAllocEx

遠(yuǎn)程申請(qǐng)空間,使用WriteProcessMemory寫入數(shù)據(jù),再用GetProcAddress獲取LoadLibraryW的地址(由于Windows引入了基址隨機(jī)化ASLR安全機(jī)制,所以導(dǎo)致每次開機(jī)啟動(dòng)時(shí)系統(tǒng)DLL加載基址都不一樣,有些系統(tǒng)dll(kernel,ntdll)的加載地址,允許每次啟動(dòng)基址可以改變,但是啟動(dòng)之后必須固定,也就是說兩個(gè)不同進(jìn)程在相互的虛擬內(nèi)存中,這樣的系統(tǒng)dll地址總是一樣的),在注入進(jìn)程中創(chuàng)建線程(CreateRemoteThread)

實(shí)現(xiàn)過程

首先生成一個(gè)dll文件,實(shí)現(xiàn)簡單的彈窗即可


我們要想進(jìn)行遠(yuǎn)程線程注入,那么就需要得到進(jìn)程的pid,這里使用到的是CreateToolhelp32Snapshot這個(gè)api拍攝快照來進(jìn)行獲取,注意我這里定義了#include "tchar.h",所有函數(shù)都是使用的寬字符


首先使用OpenProcess打開進(jìn)程


然后使用VirtualAllocEx遠(yuǎn)程申請(qǐng)空間


然后寫入內(nèi)存,使用WriteProcessMemory


然后創(chuàng)建線程并等待線程函數(shù)結(jié)束,這里WaitForSingleObject的第二個(gè)參數(shù)要設(shè)置為-1才能夠一直等待


綜上完整代碼如下





然后這里生成一個(gè)test.exe來做測(cè)試

編譯并運(yùn)行,實(shí)現(xiàn)效果如下

突破session 0的遠(yuǎn)程線程注入

首先提一提session0的概念:

Intel的CPU將特權(quán)級(jí)別分為4個(gè)級(jí)別:RING0,RING1,RING2,RING3。Windows只使用其中的兩個(gè)級(jí)別RING0和RING3,RING0只給操作系統(tǒng)用,RING3誰都能用。如果普通應(yīng)用程序企圖執(zhí)行RING0指令,則Windows會(huì)顯示“非法指令”錯(cuò)誤信息。

ring0是指CPU的運(yùn)行級(jí)別,ring0是最高級(jí)別,ring1次之,ring2更次之…… 拿Linux+x86來說, 操作系統(tǒng)(內(nèi)核)的代碼運(yùn)行在最高運(yùn)行級(jí)別ring0上,可以使用特權(quán)指令,控制中斷、修改頁表、訪問設(shè)備等等。 應(yīng)用程序的代碼運(yùn)行在最低運(yùn)行級(jí)別上ring3上,不能做受控操作。如果要做,比如要訪問磁盤,寫文件,那就要通過執(zhí)行系統(tǒng)調(diào)用(函數(shù)),執(zhí)行系統(tǒng)調(diào)用的時(shí)候,CPU的運(yùn)行級(jí)別會(huì)發(fā)生從ring3到ring0的切換,并跳轉(zhuǎn)到系統(tǒng)調(diào)用對(duì)應(yīng)的內(nèi)核代碼位置執(zhí)行,這樣內(nèi)核就為你完成了設(shè)備訪問,完成之后再從ring0返回ring3。這個(gè)過程也稱作用戶態(tài)和內(nèi)核態(tài)的切換。

RING設(shè)計(jì)的初衷是將系統(tǒng)權(quán)限與程序分離出來,使之能夠讓OS更好的管理當(dāng)前系統(tǒng)資源,也使得系統(tǒng)更加穩(wěn)定。舉個(gè)RING權(quán)限的最簡單的例子:一個(gè)停止響應(yīng)的應(yīng)用程式,它運(yùn)行在比RING0更低的指令環(huán)上,你不必大費(fèi)周章的想著如何使系統(tǒng)回復(fù)運(yùn)作,這期間,只需要啟動(dòng)任務(wù)管理器便能輕松終止它,因?yàn)樗\(yùn)行在比程式更低的RING0指令環(huán)中,擁有更高的權(quán)限,可以直接影響到RING0以上運(yùn)行的程序,當(dāng)然有利就有弊,RING保證了系統(tǒng)穩(wěn)定運(yùn)行的同時(shí),也產(chǎn)生了一些十分麻煩的問題。比如一些OS虛擬化技術(shù),在處理RING指令環(huán)時(shí)便遇到了麻煩,系統(tǒng)是運(yùn)行在RING0指令環(huán)上的,但是虛擬的OS畢竟也是一個(gè)系統(tǒng),也需要與系統(tǒng)相匹配的權(quán)限。而RING0不允許出現(xiàn)多個(gè)OS同時(shí)運(yùn)行在上面,最早的解決辦法便是使用虛擬機(jī),把OS當(dāng)成一個(gè)程序來運(yùn)行。

核心函數(shù)

ZwCreateThreadEx

注意一下這個(gè)地方ZwCreateThreadEx這個(gè)函數(shù)在32位和64位中的定義不同

在32位的情況下


在64位的情況下


這里因?yàn)槲覀円M(jìn)到session 0那么就勢(shì)必要到system權(quán)限,所以這里還有幾個(gè)提權(quán)需要用到的函數(shù)

OpenProcessToken

LookupPrivilegeValueA

AdjustTokenPrivileges


實(shí)現(xiàn)原理

ZwCreateThreadEx比?CreateRemoteThread函數(shù)更為底層,CreateRemoteThread函數(shù)最終是通過調(diào)用ZwCreateThreadEx函數(shù)實(shí)現(xiàn)遠(yuǎn)線程創(chuàng)建的。

通過調(diào)用CreateRemoteThread函數(shù)創(chuàng)建遠(yuǎn)線程的方式在內(nèi)核6.0(Windows VISTA、7、8等)以前是完全沒有問題的,但是在內(nèi)核6.0 以后引入了會(huì)話隔離機(jī)制。它在創(chuàng)建一個(gè)進(jìn)程之后并不立即運(yùn)行,而是先掛起進(jìn)程,在查看要運(yùn)行的進(jìn)程所在的會(huì)話層之后再?zèng)Q定是否恢復(fù)進(jìn)程運(yùn)行。

在Windows XP、Windows Server 2003,以及更老版本的Windows操作系統(tǒng)中,服務(wù)和應(yīng)用程序使用相同的會(huì)話(Session)運(yùn)行,而這個(gè)會(huì)話是由第一個(gè)登錄到控制臺(tái)的用戶啟動(dòng)的。該會(huì)話就叫做Session 0,如下圖所示,在Windows Vista之前,Session 0不僅包含服務(wù),也包含標(biāo)準(zhǔn)用戶應(yīng)用程序。

將服務(wù)和用戶應(yīng)用程序一起在Session 0中運(yùn)行會(huì)導(dǎo)致安全風(fēng)險(xiǎn),因?yàn)榉?wù)會(huì)使用提升后的權(quán)限運(yùn)行,而用戶應(yīng)用程序使用用戶特權(quán)(大部分都是非管理員用戶)運(yùn)行,這會(huì)使得惡意軟件以某個(gè)服務(wù)為攻擊目標(biāo),通過“劫持”該服務(wù),達(dá)到提升自己權(quán)限級(jí)別的目的。

從Windows Vista開始,只有服務(wù)可以托管到Session 0中,用戶應(yīng)用程序和服務(wù)之間會(huì)被隔離,并需要運(yùn)行在用戶登錄到系統(tǒng)時(shí)創(chuàng)建的后續(xù)會(huì)話中。例如第一個(gè)登錄的用戶創(chuàng)建 Session 1,第二個(gè)登錄的用戶創(chuàng)建Session 2,以此類推,如下圖所示。

使用CreateRemoteThread注入失敗DLL失敗的關(guān)鍵在第七個(gè)參數(shù)CreateThreadFlags, 他會(huì)導(dǎo)致線程創(chuàng)建完成后一直掛起無法恢復(fù)進(jìn)程運(yùn)行,導(dǎo)致注入失敗。而想要注冊(cè)成功,把該參數(shù)的值改為0即可。

實(shí)現(xiàn)過程

在win10系統(tǒng)下如果我們要注入系統(tǒng)權(quán)限的exe,就需要使用到debug調(diào)試權(quán)限,所以先寫一個(gè)提權(quán)函數(shù)。


在進(jìn)程注入dll的過程中,是不能夠使用MessageBox的,系統(tǒng)程序不能夠顯示程序的窗體,所以這里編寫一個(gè)ShowError函數(shù)來獲取錯(cuò)誤碼


首先打開進(jìn)程獲取句柄,使用到OpenProcess


然后是在注入的進(jìn)程申請(qǐng)內(nèi)存地址,使用到VirtualAllocEx


再使用WriteProcessMemory寫入內(nèi)存

? ??

加載ntdll,獲取LoadLibraryA函數(shù)地址


獲取ZwCreateThreadEx函數(shù)地址


使用?ZwCreateThreadEx創(chuàng)建遠(yuǎn)線程, 實(shí)現(xiàn) DLL 注入


這里還有一點(diǎn)需要注意的是ZwCreateThreadEx在?ntdll.dll?中并沒有聲明,所以我們需要使用?GetProcAddress從?ntdll.dll中獲取該函數(shù)的導(dǎo)出地址

這里加上ZwCreateThreadEx的定義,因?yàn)?4位、32位結(jié)構(gòu)不同,所以都需要進(jìn)行定義


完整代碼如下





因?yàn)樵赿ll注入的過程中是看不到messagebox的,所以這里我選擇cs注入進(jìn)行測(cè)試,若注入成功即可上線

首先生成一個(gè)32位的dll文件,這里跟位數(shù)有關(guān),我選擇注入的是32位的進(jìn)程,所以這里我選擇生成32位的dll

得到路徑

這里我選擇的是有道云筆記進(jìn)行注入,查看一下pid

然后把我們函數(shù)的pid改為有道云的pid

實(shí)現(xiàn)效果如下所示


APC注入

APC,全稱為Asynchronous Procedure Call,即異步過程調(diào)用,是指函數(shù)在特定線程中被異步執(zhí)行,在操作系統(tǒng)中,APC是一種并發(fā)機(jī)制。

這里去看一下msdn中異步過程調(diào)用的解釋如下

首先第一個(gè)函數(shù)

QueueUserApc: 函數(shù)作用,添加制定的異步函數(shù)調(diào)用(回調(diào)函數(shù))到執(zhí)行的線程的APC隊(duì)列中

APCproc:   函數(shù)作用: 回調(diào)函數(shù)的寫法.

往線程APC隊(duì)列添加APC,系統(tǒng)會(huì)產(chǎn)生一個(gè)軟中斷。在線程下一次被調(diào)度的時(shí)候,就會(huì)執(zhí)行APC函數(shù),APC有兩種形式,由系統(tǒng)產(chǎn)生的APC稱為內(nèi)核模式APC,由應(yīng)用程序產(chǎn)生的APC被稱為用戶模式APC。這里介紹一下應(yīng)用程序的APC,APC是往線程中插入一個(gè)回調(diào)函數(shù),但是用的APC調(diào)用這個(gè)回調(diào)函數(shù)是有條件的,如msdn所示


核心函數(shù)

QueueUserAPC

QueueUserAPC 函數(shù)的第一個(gè)參數(shù)表示執(zhí)行函數(shù)的地址,當(dāng)開始執(zhí)行該APC的時(shí)候,程序會(huì)跳轉(zhuǎn)到該函數(shù)地址處來執(zhí)行。第二個(gè)參數(shù)表示插入APC的線程句柄,要求線程句柄必須包含THREAD_SET_CONTEXT 訪問權(quán)限。第三個(gè)參數(shù)表示傳遞給執(zhí)行函數(shù)的參數(shù),與遠(yuǎn)線程注入類似,如果QueueUserAPC 的第一個(gè)參數(shù)為LoadLibraryA,第三個(gè)參數(shù)設(shè)置的是dll路徑即可完成dll注入。

實(shí)現(xiàn)原理

在 Windows系統(tǒng)中,每個(gè)線程都會(huì)維護(hù)一個(gè)線程 APC隊(duì)列,通過QucueUserAPC把一個(gè)APC 函數(shù)添加到指定線程的APC隊(duì)列中。每個(gè)線程都有自己的APC隊(duì)列,這個(gè) APC隊(duì)列記錄了要求線程執(zhí)行的一些APC函數(shù)。Windows系統(tǒng)會(huì)發(fā)出一個(gè)軟中斷去執(zhí)行這些APC 函數(shù),對(duì)于用戶模式下的APC 隊(duì)列,當(dāng)線程處在可警告狀態(tài)時(shí)才會(huì)執(zhí)行這些APC 函數(shù)。一個(gè)線程在內(nèi)部使用SignalObjectAndWait 、 SleepEx、WaitForSingleObjectEx、WaitForMultipleObjectsEx等函數(shù)把自己掛起時(shí)就是進(jìn)入可警告狀態(tài),此時(shí)便會(huì)執(zhí)行APC隊(duì)列函數(shù)。

通俗點(diǎn)來概括過程可分為以下幾步:

1)當(dāng)EXE里某個(gè)線程執(zhí)行到SleepEx()或者WaitForSingleObjectEx()時(shí),系統(tǒng)就會(huì)產(chǎn)生一個(gè)軟中斷(或者是Messagebox彈窗的時(shí)候不點(diǎn)OK的時(shí)候也能注入)。

2)當(dāng)線程再次被喚醒時(shí),此線程會(huì)首先執(zhí)行APC隊(duì)列中的被注冊(cè)的函數(shù)。

3)利用QueueUserAPC()這個(gè)API可以在軟中斷時(shí)向線程的APC隊(duì)列插入一個(gè)函數(shù)指針,如果我們插入的是Loadlibrary()執(zhí)行函數(shù)的話,就能達(dá)到注入DLL的目的。

但是想要使用apc注入也有以下兩點(diǎn)條件:

1.必須是多線程環(huán)境下

2.注入的程序必須會(huì)調(diào)用那些同步對(duì)象

每一個(gè)進(jìn)程的每一個(gè)線程都有自己的APC隊(duì)列,我們可以使用QueueUserAPC函數(shù)把一個(gè)APC函數(shù)壓入APC隊(duì)列中。當(dāng)處于用戶模式的APC被壓入到線程APC隊(duì)列后,線程并不會(huì)立刻執(zhí)行壓入的APC函數(shù),而是要等到線程處于可通知狀態(tài)(alertable)才會(huì)執(zhí)行,即只有當(dāng)一個(gè)線程內(nèi)部調(diào)用SleepEx等上面說到的幾個(gè)特定函數(shù)將自己處于掛起狀態(tài)時(shí),才會(huì)執(zhí)行APC隊(duì)列函數(shù),執(zhí)行順序與普通隊(duì)列相同,先進(jìn)先出(FIFO),在整個(gè)執(zhí)行過程中,線程并無任何異常舉動(dòng),不容易被察覺,但缺點(diǎn)是對(duì)于單線程程序一般不存在掛起狀態(tài),所以APC注入對(duì)于這類程序沒有明顯效果。

實(shí)現(xiàn)過程

這里的常規(guī)思路是編寫一個(gè)根據(jù)進(jìn)程名獲取pid的函數(shù),然后根據(jù)PID獲取所有的線程ID,這里我就將兩個(gè)函數(shù)集合在一起,通過自己輸入PID來獲取指定進(jìn)程的線程并寫入數(shù)組



然后是apc注入的主函數(shù),首先使用VirtualAllocEx遠(yuǎn)程申請(qǐng)內(nèi)存


然后使用WriteProcessMemory把dll路徑寫入內(nèi)存


再獲取LoadLibraryA的地址


便利線程并插入APC,這里定義一個(gè)fail并進(jìn)行判斷,如果QueueUserAPC返回的值為NULL則線程遍歷失敗,fail的值就+1


然后在到主函數(shù),定義dll地址


使用OpenProcess打開句柄


調(diào)用之前寫好的APCInject函數(shù)實(shí)現(xiàn)APC注入



完整代碼如下







之前說過我沒有使用進(jìn)程名 -> pid的方式,而是直接采用手動(dòng)輸入的方式,通過cin >> ulProcessID將接收到的參數(shù)賦給ulProcessID

這里可以選擇寫一個(gè)MessageBox的dll,這里我直接用的是cs的dll,演示效果如下所示

最后

關(guān)注私我獲取【網(wǎng)絡(luò)安全學(xué)習(xí)資料·攻略

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容