溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

c++怎么實現(xiàn)線程注入

發(fā)布時間:2021-06-24 09:06:31 來源:億速云 閱讀:142 作者:chen 欄目:開發(fā)技術(shù)

這篇文章主要介紹“c++怎么實現(xiàn)線程注入”,在日常操作中,相信很多人在c++怎么實現(xiàn)線程注入問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”c++怎么實現(xiàn)線程注入”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

簡單編寫DLL文件:

#include <Windows.h>

extern "C" __declspec(dllexport) void MsgBox(LPCWSTR szMsg, LPCWSTR Title)
{
	MessageBox(NULL, szMsg, Title, MB_OK);
}

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		// 進程被加載后執(zhí)行
		break;
	case DLL_THREAD_ATTACH:
		// 線程被創(chuàng)建后加載
		break;
	case DLL_THREAD_DETACH:
		// 正常退出執(zhí)行的代碼
		break;
	case DLL_PROCESS_DETACH:
		// 進程卸載本Dll后執(zhí)行的代碼
		break;
	}
	return TRUE;
}
#include <Windows.h>
#include <iostream>

typedef VOID(*PFUNMSG)(LPCWSTR szMsg, LPCWSTR Title);

int main(int argc, char *argv[])
{

	HMODULE hModule = LoadLibrary("./hook.dll");

	if (hModule != NULL)
	{
		PFUNMSG pMsgBox = (PFUNMSG)GetProcAddress(hModule, "MsgBox");
		pMsgBox(L"hello lyshark", L"msgbox");
	}

	system("pause");
	return 0;
}

x86 實現(xiàn)遠(yuǎn)程線程注入:

注入原理是利用了Windows系統(tǒng)中提供的CreateRemoteThread()這個API函數(shù),該函數(shù)第四個參數(shù)是準(zhǔn)備運行的線程,我們將LoadLibrary()函數(shù)填入其中,這樣就可以執(zhí)行遠(yuǎn)程進程中的LoadLibrary()函數(shù),進而將我們自己準(zhǔn)備的DLL加載到遠(yuǎn)程進程空間中執(zhí)行,DLL在被裝載后則會自動執(zhí)行初始化部分,X86注入代碼如下.

#include <windows.h>
#include <stdio.h>

// 使用 CreateRemoteThread 實現(xiàn)遠(yuǎn)線程注入
BOOL CreateRemoteThreadInjectDll(DWORD Pid, char *DllName)
{
	HANDLE hProcess = NULL;
	SIZE_T dwSize = 0;
	LPVOID pDllAddr = NULL;
	FARPROC pFuncProcAddr = NULL;

	// 打開注入進程,獲取進程句柄
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
	if (NULL == hProcess)
	{
		return FALSE;
	}
	// 計算欲注入 DLL 文件完整路徑的長度
	dwSize = sizeof(char)+lstrlen(DllName);

	//  在目標(biāo)進程申請一塊長度為 nDllLen 大小的內(nèi)存空間
	pDllAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
	if (NULL == pDllAddr)
	{
		return FALSE;
	}
	//  將欲注入 DLL 文件的完整路徑寫入在目標(biāo)進程中申請的空間內(nèi)
	if (FALSE == WriteProcessMemory(hProcess, pDllAddr, DllName, dwSize, NULL))
	{
		return FALSE;
	}
	// 獲得 LoadLibraryA()函數(shù)的地址
	pFuncProcAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
	if (NULL == pFuncProcAddr)
	{
		return FALSE;
	}
	// 使用 CreateRemoteThread 創(chuàng)建遠(yuǎn)線程, 實現(xiàn) DLL 注入
	HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, NULL);
	if (NULL == hRemoteThread)
	{
		return FALSE;
	}
	// 關(guān)閉句柄
	CloseHandle(hProcess);
	return TRUE;
}

int main(int argc, char *argv[])
{
	CreateRemoteThreadInjectDll(4668, "./x86.dll");
	system("pause");
	return 0;
}

x64 實現(xiàn)遠(yuǎn)程線程注入:

如果想要注入X64程序,則需要在編譯時指定為64位編譯模式,并且使用LoadLibraryW()來加載動態(tài)鏈接庫,我們只需要在上面代碼的基礎(chǔ)上稍加改進就可以實現(xiàn)64位進程的注入了.

#include <windows.h>
#include <stdio.h>

// 使用 CreateRemoteThread 實現(xiàn)遠(yuǎn)線程注入
BOOL CreateRemoteThreadInjectDll(DWORD Pid, PCWSTR DllName)
{
	BOOL ret = FALSE;
	HANDLE hProcess, hThread = NULL;
	FARPROC pfnThreadRtn = NULL;
	PWSTR pwszPara = NULL;

	// 打開注入進程,獲取進程句柄
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
	if (NULL == hProcess)
	{
		return FALSE;
	}

	// 計算欲注入 DLL 文件完整路徑的長度
	size_t iProxyFileLen = wcslen(DllName) * sizeof(WCHAR);

	//  在目標(biāo)進程申請一塊長度為 nDllLen 大小的內(nèi)存空間
	pwszPara = (PWSTR)VirtualAllocEx(hProcess, NULL, iProxyFileLen, MEM_COMMIT, PAGE_READWRITE);
	if (NULL == pwszPara)
	{
		return FALSE;
	}

	//  將欲注入 DLL 文件的完整路徑寫入在目標(biāo)進程中申請的空間內(nèi)
	if (FALSE == WriteProcessMemory(hProcess, pwszPara, (PVOID)DllName, iProxyFileLen, NULL))
	{
		return FALSE;
	}

	// 獲得 LoadLibraryW()函數(shù)的地址
	pfnThreadRtn = GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
	if (NULL == pfnThreadRtn)
	{
		return FALSE;
	}

	// 使用 CreateRemoteThread 創(chuàng)建遠(yuǎn)線程, 實現(xiàn) DLL 注入
	hThread = CreateRemoteThread(hProcess, NULL, 1024, (LPTHREAD_START_ROUTINE)pfnThreadRtn, pwszPara, 0, NULL);
	WaitForSingleObject(hThread, INFINITE);
	if (NULL != hThread)
	{
		CloseHandle(hThread);
		CloseHandle(hProcess);
		VirtualFreeEx(hProcess, pwszPara, 0, MEM_RELEASE);
		return TRUE;
	}
	return FALSE;
}

int main(int argc, char *argv[])
{
	CreateRemoteThreadInjectDll(8224, L"./x64.dll");
	system("pause");
	return 0;
}

實現(xiàn)普通消息鉤子注入:

Windows提供的鉤子類型非常多,其中一種類型的鉤子非常實用,那就是WH_GETME SSAGE鉤子,它可以很方便地將DLL文件注入到所有的基于消息機制的目標(biāo)程序中,代碼非常簡單,這里直接給出DLL文件的代碼,具體如下:

#include <windows.h>

extern "C" __declspec(dllexport) VOID SetHookOn();
extern "C" __declspec(dllexport) VOID SetHookOff();

HHOOK g_HHook = NULL;
HINSTANCE g_hInst = NULL;

VOID DoSomeThing()
{
	MessageBoxA(0, "hello lyshark", 0, 0);
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
	switch (fdwReason)
	{
		case DLL_PROCESS_ATTACH:
		{
			g_hInst = hinstDLL;
			DoSomeThing();
			break;
		}
	}
	return TRUE;
}

LRESULT CALLBACK GetMsgProc(int code,WPARAM wParam,LPARAM lParam)
{
	return CallNextHookEx(g_HHook, code, wParam, lParam);
}

VOID SetHookOn()
{
	g_HHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInst, 0);
}

VOID SetHookOff()
{
	UnhookWindowsHookEx(g_HHook);
}

實現(xiàn)全局消息鉤子注入:

該注入的原理是利用系統(tǒng)中的SetWindowHookEx()這個API函數(shù),該函數(shù)可以攔截目標(biāo)進程的消息到指定DLL中的導(dǎo)出函數(shù)上,利用這個特性,我們可以將DLL注入到全局進程中,但是在使用SetWindowsHookEx()之前首先需要將HOOK的DLL加載到本身的進程中,以此得到DLL的模塊句柄,再使用GetProcAddress()得到DLL中公開的函數(shù)地址,最后遍歷出待注入進程的線程ID,這樣SetWindowHookEx()就可以利用這些參數(shù)進行HOOK了.

我們先來編寫DLL文件,創(chuàng)建Dll工程hook.cpp然后將SetHook()函數(shù)導(dǎo)出,由于該注入方式是全局注入,所以如果我們想要注入到指定進程中,則需要在DllMain()也就是動態(tài)鏈接庫開頭位置進行判斷,如果是我們需要Hook的進程,則加載Dll到指定進程中,如果不是則不執(zhí)行任何操作,這樣一來即可實現(xiàn)指定進程注入.

#include <windows.h>
HHOOK Global_Hook;

// 設(shè)置全局消息回調(diào)函數(shù)
LRESULT CALLBACK MyProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	return CallNextHookEx(Global_Hook, nCode, wParam, lParam);
}
// 安裝全局鉤子,此處的hook.dll可以是外部其他的dll
extern "C" __declspec(dllexport) void SetHook()
{
	Global_Hook = SetWindowsHookEx(WH_CBT, MyProc, GetModuleHandle(TEXT("hook.dll")), 0);
}
// 卸載全局鉤子
extern "C" __declspec(dllexport) void UnHook()
{
	if(Global_Hook)
		UnhookWindowsHookEx(Global_Hook);
}

bool APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
	HWND hwnd = FindWindowW(L"valve001",NULL);
	DWORD pid;
	GetWindowThreadProcessId(hwnd, &pid);
	if (GetCurrentProcessId() == pid)
	{
		MessageBox(hwnd, TEXT("hello lyshark"), 0, 0);
	}
	return true;
}

調(diào)用代碼:注意必須將上方編譯好的hook.dll與下方工程放到同一個目錄下,通過LoadLibrary()函數(shù)獲取到模塊句柄,然后通過GetProcAddress()獲取到導(dǎo)出函數(shù)地址,并通過函數(shù)指針調(diào)用,由于全局注入依賴于父進程,所以下面的代碼必須一直運行.

#include <windows.h>

int main(int argc, char *argv[])
{
	HMODULE hMod = LoadLibrary(TEXT("hook.dll"));

	typedef void(*pSetHook)(void);
	pSetHook SetHook = (pSetHook)GetProcAddress(hMod, "SetHook");
	SetHook();
	while (1)
	{
		Sleep(1000);
	}
	return 0;
}

APC應(yīng)用層異步注入:

APC 是異步過程調(diào)用,在Windows下每個線程在可被喚醒時在其APC鏈中的函數(shù)將有機會執(zhí)行被執(zhí)行,每一個線程都具有一個APC鏈,那么只要在可以在APC鏈中添加一個APC,就可以完成我們所需要的DLL注入的功能.

1.將需要加載的DLL的完整路徑寫入目標(biāo)進程空間.
2.獲得LoadLibraryA()函數(shù)的地址,當(dāng)然也可以是LoadLibraryW()函數(shù)的地址.
3.枚舉目標(biāo)進程中的所有線程,為每個線程添加一個APC函數(shù),這樣增加了注入成功的機會.

該注入的原理是利用當(dāng)線程被喚醒時APC中的注冊函數(shù)會被執(zhí)行的機制,并以此去執(zhí)行我們的DLL加載代碼,進而完成DLL注入的

目的,通過APC注入的流程步驟大致如下

1.當(dāng)EXE里某個線程執(zhí)行到SleepEx()或者WaitForSingleObjectEx()時,系統(tǒng)就會產(chǎn)生一個軟中斷.
2.當(dāng)線程再次被喚醒時,此線程會首先執(zhí)行APC隊列中的被注冊的函數(shù).
3.利用QueueUserAPC()這個API可以在軟中斷時向線程的APC隊列插入一個函數(shù)指針,如果我們插入的是Loadlibrary()執(zhí)行函數(shù)的話,就能達到注入DLL的目的,不論如何目標(biāo)程序必須有執(zhí)行SleepEx()或者WaitForSingleObjectEx()否則DLL不會加載.

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

// APC注入
BOOL ApcInjectDll(DWORD dwPid, char * szDllName)
{
	// 計算欲注入 DLL 文件完整路徑的長度
	int nDllLen = lstrlen(szDllName) + sizeof(char);

	// 打開目標(biāo)進程
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwPid);
	if (hProcess == NULL)
	{
		return FALSE;
	}
	// 在目標(biāo)進程申請一塊長度為 nDllLen 大小的內(nèi)存空間
	PVOID pDllAddr = VirtualAllocEx(hProcess,NULL, nDllLen,MEM_COMMIT,PAGE_READWRITE);
	if (pDllAddr == NULL)
	{
		CloseHandle(hProcess);
		return FALSE;
	}
	DWORD dwWriteNum = 0;
	// 將欲注入 DLL 文件的完整路徑寫入在目標(biāo)進程中申請的空間內(nèi)
	WriteProcessMemory(hProcess, pDllAddr, szDllName,nDllLen, &dwWriteNum);
	CloseHandle(hProcess);

	THREADENTRY32 te = { 0 };
	te.dwSize = sizeof(THREADENTRY32);
	//得到線程快照
	HANDLE handleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	if (INVALID_HANDLE_VALUE == handleSnap)
	{
		CloseHandle(hProcess);
		return FALSE;
	}
	// 獲得 LoadLibraryA()函數(shù)的地址
	FARPROC pFunAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
	DWORD dwRet = 0;
	//得到第一個線程
	if (Thread32First(handleSnap, &te))
	{
		do
		{
			//進行進程 ID 對比
			if (te.th42OwnerProcessID == dwPid)
			{
				//得到線程句柄
				HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,FALSE,te.th42ThreadID);
				if (hThread)
				{
					//向線程插入 APC
					dwRet = QueueUserAPC((PAPCFUNC)pFunAddr,hThread,(ULONG_PTR)pDllAddr);
					//關(guān)閉句柄
					CloseHandle(hThread);
				}
			}
			//循環(huán)下一個線程
		} while (Thread32Next(handleSnap, &te));
	}
	CloseHandle(handleSnap);
	return TRUE;
}

int main(int argc, char *argv[])
{
	ApcInjectDll(9608, "c:/x86.dll");
	system("pause");
	return 0;
}

ZwCreateThreadEx強力注入:

在前面的注入方式中,我們使用了CreateRemoteThread()這個函數(shù)來完成線程注入,此方式可以注入普通的進程,但卻無法注入到系統(tǒng)進程中,因為系統(tǒng)進程是處在SESSION0高權(quán)限級別的會話層.

由于CreateRemoteThread()底層會調(diào)用ZwCreateThreadEx()這個未公開的內(nèi)核函數(shù),所以我們必須手動調(diào)用ZwCreateThread()這一內(nèi)核函數(shù),將第七個參數(shù)設(shè)置為0即可,ZwCreateThreadEx函數(shù)在ntdll.dll中并未聲明,所以必須手動使用GetProcAddress函數(shù)將其地址導(dǎo)出.

#include <windows.h>
#include <stdio.h>

// 使用 ZwCreateThreadEx 實現(xiàn)遠(yuǎn)線程注入
BOOL ZwCreateThreadExInjectDll(DWORD dwProcessId, char * pDllName)
{
	HANDLE hProcess = NULL;
	SIZE_T dwSize = 0;
	LPVOID pDllAddr = NULL;
	FARPROC pFuncProcAddr = NULL;
	HANDLE hRemoteThread = NULL;
	DWORD dwStatus = 0;

	// 打開注入進程,獲取進程句柄
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
	if (NULL == hProcess)
	{
		return FALSE;
	}
	// 在注入進程中申請內(nèi)存
	dwSize = sizeof(char)+lstrlen(pDllName);
	pDllAddr = ::VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
	if (NULL == pDllAddr)
	{
		return FALSE;
	}
	// 向申請的內(nèi)存中寫入數(shù)據(jù)
	if (FALSE == ::WriteProcessMemory(hProcess, pDllAddr, pDllName, dwSize, NULL))
	{
		return FALSE;
	}
	// 加載 ntdll.dll
	HMODULE hNtdllDll = ::LoadLibrary("ntdll.dll");
	if (NULL == hNtdllDll)
	{
		return FALSE;
	}
	// 獲取LoadLibraryA函數(shù)地址
	pFuncProcAddr = ::GetProcAddress(::GetModuleHandle("Kernel32.dll"), "LoadLibraryA");
	if (NULL == pFuncProcAddr)
	{
		return FALSE;
	}
	// 獲取ZwCreateThread函數(shù)地址
#ifdef _WIN64
	typedef DWORD(WINAPI *typedef_ZwCreateThreadEx)(
		PHANDLE ThreadHandle,
		ACCESS_MASK DesiredAccess,
		LPVOID ObjectAttributes,
		HANDLE ProcessHandle,
		LPTHREAD_START_ROUTINE lpStartAddress,
		LPVOID lpParameter,
		ULONG CreateThreadFlags,
		SIZE_T ZeroBits,
		SIZE_T StackSize,
		SIZE_T MaximumStackSize,
		LPVOID pUnkown);
#else
	typedef DWORD(WINAPI *typedef_ZwCreateThreadEx)(
		PHANDLE ThreadHandle,
		ACCESS_MASK DesiredAccess,
		LPVOID ObjectAttributes,
		HANDLE ProcessHandle,
		LPTHREAD_START_ROUTINE lpStartAddress,
		LPVOID lpParameter,
		BOOL CreateSuspended,
		DWORD dwStackSize,
		DWORD dw1,
		DWORD dw2,
		LPVOID pUnkown);
#endif
	typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)::GetProcAddress(hNtdllDll, "ZwCreateThreadEx");
	if (NULL == ZwCreateThreadEx)
	{
		return FALSE;
	}
	// 使用 ZwCreateThreadEx 創(chuàng)建遠(yuǎn)線程, 實現(xiàn) DLL 注入
	dwStatus = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hProcess, 
		(LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, 0, 0, 0, NULL);
	if (NULL == hRemoteThread)
	{
		return FALSE;
	}
	// 關(guān)閉句柄
	::CloseHandle(hProcess);
	::FreeLibrary(hNtdllDll);
	return TRUE;
}

int main(int argc, char *argv[])
{
	BOOL bRet = ZwCreateThreadExInjectDll(2940, "hook.dll");

	system("pause");
	return 0;
}

強制卸載進程中的DLL:

#include <Windows.h>
#include <stdio.h>
#include <TlHelp32.h>

BOOL UnLoad_Module(DWORD dwPID, LPCTSTR szDllName)
{
	BOOL bMore = FALSE, bFound = FALSE;
	HANDLE hSnapshot, hProcess, hThread;
	HMODULE hModule = NULL;
	MODULEENTRY32 me = { sizeof(me) };
	LPTHREAD_START_ROUTINE pThreadProc;

	hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
	bMore = Module32First(hSnapshot, &me);
	for (; bMore; bMore = Module32Next(hSnapshot, &me))
	{
		if (!_tcsicmp((LPCTSTR)me.szModule, szDllName) || !_tcsicmp((LPCTSTR)me.szExePath, szDllName))
		{
			bFound = TRUE;
			break;
		}
	}
	if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
		return FALSE;

	hModule = GetModuleHandle(L"kernel32.dll");
	pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");
	hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL);
	WaitForSingleObject(hThread, INFINITE);
	if (hThread != 0)
	{
		CloseHandle(hThread);
		CloseHandle(hProcess);
		CloseHandle(hSnapshot);
		return TRUE;
	}
	return FALSE;
}

int main(int argc, char *argv[])
{
	UnLoad_Module(2012, "lyshark.dll");

	system("pause");
	return 0;
}

純匯編實現(xiàn)遠(yuǎn)程Dll注入:

.data
	szMyDll        db "\lyshark.dll",0h       ; 要注入的DLL
	szDllKernel    db "Kernel32.dll",0h
	szLoadLibrary  db "LoadLibraryA",0h
	lpFileName     db "Tutorial-i386",0h      ; 指定要注入進程
	lpDllName      dd ?
.data?
	szMyDllFull    db MAX_PATH dup (?)
	lpLoadLibrary  dd ?
	dwProcessID    dd ?     
	dwThreadID     dd ?
	hProcess       dd ?
.code
	main PROC
; 準(zhǔn)備工作:獲取dll的全路徑文件名、獲取LoadLibrary函數(shù)地址等
		invoke GetCurrentDirectory,MAX_PATH,addr szMyDllFull
		invoke lstrcat,addr szMyDllFull,addr szMyDll
		invoke GetModuleHandle,addr szDllKernel
		invoke GetProcAddress,eax,offset szLoadLibrary
		mov lpLoadLibrary,eax

; 查找文件管理器窗口并獲取進程ID,然后打開進程
		invoke FindWindow,NULL,addr lpFileName
		invoke GetWindowThreadProcessId,eax,offset dwProcessID
  		mov dwThreadID,eax
  		invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessID
		mov hProcess,eax

; 在進程中分配空間并將DLL文件名拷貝過去,然后創(chuàng)建一個LoadLibrary線程
		invoke VirtualAllocEx,hProcess,NULL,MAX_PATH,MEM_COMMIT,PAGE_READWRITE
		mov lpDllName,eax
		invoke WriteProcessMemory,hProcess,eax,offset szMyDllFull,MAX_PATH,NULL
		invoke CreateRemoteThread,hProcess,NULL,0,lpLoadLibrary,lpDllName,0,NULL
		ret
	main endp
end main

純匯編實現(xiàn)遠(yuǎn)程代碼注入:

1.首先使用匯編編寫一個代碼注入器,其命名為main.asm

.data
	lpLoadLibrary      dd ?
	lpGetProcAddress   dd ?
	lpGetModuleHandle  dd ?
	dwProcessID        dd ?
	dwThreadID         dd ?
	hProcess           dd ?
	lpRemoteCode       dd ?
.const
	ProcHandle        db "lyshark.exe",0h
	KernelBase        db "Kernel32.dll",0h
	szLoadLibrary     db "LoadLibraryA",0h
	szGetProcAddress  db "GetProcAddress",0h
	szGetModuleHandle db "GetModuleHandleA",0h
.code
include Macro.inc
include ShellCode.asm
	main proc
		invoke GetModuleHandle,addr KernelBase
		mov ebx,eax
		invoke GetProcAddress,ebx,offset szLoadLibrary
		mov lpLoadLibrary,eax
		invoke GetProcAddress,ebx,offset szGetProcAddress
		mov lpGetProcAddress,eax
		invoke GetProcAddress,ebx,offset szGetModuleHandle
		mov lpGetModuleHandle,eax

		invoke FindWindow,NULL,addr ProcHandle
		invoke GetWindowThreadProcessId,eax,offset dwProcessID
		mov dwThreadID,eax
		invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessID
		mov hProcess,eax

		invoke VirtualAllocEx,hProcess,NULL,2048,MEM_COMMIT,PAGE_EXECUTE_READWRITE
			.if eax
				mov lpRemoteCode,eax
				invoke WriteProcessMemory,hProcess,lpRemoteCode,offset REMOTE_CODE_START,1024,NULL
				invoke WriteProcessMemory,hProcess,lpRemoteCode,offset lpLoadLibrary,sizeof dword * 3,NULL
				mov eax,lpRemoteCode
				add eax,offset _RemoteThread - offset REMOTE_CODE_START
				invoke CreateRemoteThread,hProcess,NULL,0,eax,0,0,NULL
				invoke CloseHandle,eax
			.endif
			invoke CloseHandle,hProcess	
	invoke ExitProcess,NULL
	ret
	main endp
end main

為了后期編程方便,編寫一個反轉(zhuǎn)宏Macro.inc用來翻轉(zhuǎn)參數(shù),使用定義_invoke調(diào)用更方便

; --------------------------------------------
; 翻轉(zhuǎn)參數(shù)字節(jié)序
reverseArgs macro arglist:VARARG
	LOCAL txt,count
	txt TEXTEQU <>
	count=0
	for i,<arglist>
		count = count+1
		txt TEXTEQU @CatStr(i,<!,>,<%txt>)
	endm
	if count GT 0
		txt SUBSTR txt,1,@SizeStr(%txt)-1
	endif
	exitm txt
endm
; --------------------------------------------
; 創(chuàng)建類似于INVOKE的宏代碼
_invoke macro _Proc,args:VARARG
	LOCAL count
	count = 0
%	for i,< reverseArgs( args ) >
		count = count+1
		push i
	endm
	call dword ptr _Proc    
endm

最后編寫注入代碼,此處命名為shellcode.asm該代碼包括了子定位功能.

REMOTE_CODE_START equ this byte
_lpLoadLibrary      dd ?
_lpGetProcAddress   dd ?
_lpGetModuleHandle  dd ?

; --------------------------------------------
; 存放靜態(tài)資源,比如常量,字符串等.
_hInstance          dd ?
_szShowTitle        db "hello lyshark",0h

; --------------------------------------------
; 存放獲取到的指針
_lpDllUser          dd ?
_lpMessageBox       dd ?
; --------------------------------------------
; 放入導(dǎo)入函數(shù)的字符串
_szDllUser		db	"user32.dll",0h
_szMessageBox           db      "MessageBoxA",0h,0
; --------------------------------------------
_RemoteThread proc uses ebx esi edi
		LOCAL @hModule
; --------------------------------------------
; 計算指令的偏移地址,用ebx作為基址指針
		call @F
		@@:
		pop ebx
		sub ebx,offset @B
; --------------------------------------------
		_invoke [ebx + _lpGetModuleHandle],NULL         ; 取當(dāng)前模塊句柄
		mov [ebx + _hInstance],eax
		lea eax,[ebx + offset _szDllUser]           
		_invoke [ebx + _lpGetModuleHandle],eax          ; 取user32.dll模塊句柄
		mov @hModule,eax
; --------------------------------------------
; 循環(huán)獲取每個導(dǎo)入函數(shù)的地址,并放入指針變量保存
		lea esi,[ebx + offset _szMessageBox]            ; 循環(huán)獲取,從該函數(shù)起始地址處
		lea edi,[ebx + offset _lpMessageBox]
		.while TRUE
			_invoke	[ebx + _lpGetProcAddress],@hModule,esi
			mov [edi],eax       ; 獲取到函數(shù)地址后,放入導(dǎo)入函數(shù)字符串中
			add edi,4           ; 每次遞增4字節(jié),指向下一個函數(shù),遇到0則停止
			@@:
			lodsb
			or al,al
			jnz @B
			.break .if !byte ptr [esi]
		.endw
; --------------------------------------------
		;lea esi,[ebx+ offset _szMessageBox]            ; 取msgbox模塊地址
		;_invoke [ebx+_lpGetProcAddress],@hModule,esi   ; 獲取地址
		;mov [ebx+_lpMessageBox],eax                    ; 存入變量中
		lea esi,[ebx + offset _szShowTitle]             ; 獲取彈窗資源
		_invoke [ebx + _lpMessageBox],0,esi,eax,0       ; 調(diào)用信息框
		ret
_RemoteThread endp

到此,關(guān)于“c++怎么實現(xiàn)線程注入”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI