远程线程注入
        远程线程注入是一种常见的注入手段,是一种跨进程创建线程的注入手法。
        其实现思路是将待注入DLL的路径写入目标进程内存空间,并利用CreateRemoteThread和LoadLibrary函数使目标进程创建一个线程,将其入口地址设为LoadLibrary,进而加载待注入的DLL。

DLL_THREAD_ATTACH通知
通过查阅《Windows核心编程》和微软说明文档得知:
        当进程创建一个线程的时候,系统会检查当前映射到该进程的地址空间中的所有DLL文件映像,并用DLL_THREAD_ATTACH来调用每个DLL的DllMain函数,调用是在新线程的上下文中进行的。新创建的线程负责执行所有DLL的DllMain函数中的代码,只有当所有DLL都完成了对该通知的处理之后,系统才会让新线程开始执行它的线程函数

远程线程注入检测
       我们可以利用DLL_THREAD_ATTACH通知这一机制来检测远程线程注入。方法如下:
       创建一个DLL,在DllMain的DLL_THREAD_ATTACH这一switch分支下拦截每一个新创建的线程,获取其如入口地址,将入口地址与LoadLibrary函数地址作比较,若相同,则说明是远线程注入创建的线程。

DllMain代码如下:

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

typedef enum _THREADINFOCLASS {
    ThreadQuerySetWin32StartAddress=9
}THREADINFOCLASS;


typedef LONG(WINAPI* LPFN_ZWQUERYINFORMATIONTHREAD)(
    IN HANDLE ThreadHandle,
    IN THREADINFOCLASS ThreadInformationClass,
    OUT PVOID ThreadInformation,
    IN ULONG ThreadInformationLength,
    OUT PULONG ReturnLength OPTIONAL);


void Check_RemoteThreadInject(DWORD dwStartAddr)
{
	DWORD dwAddr_LoadLibraryA = (DWORD)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "LoadLibraryA");
	DWORD dwAddr_LoadLibraryW = (DWORD)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "LoadLibraryW");
	DWORD dwAddr_LoadLibraryExA= (DWORD)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "LoadLibraryExA");
	DWORD dwAddr_LoadLibraryExW = (DWORD)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "LoadLibraryExW");

	if (dwStartAddr == dwAddr_LoadLibraryA || dwStartAddr == dwAddr_LoadLibraryW||
		dwStartAddr == dwAddr_LoadLibraryExA || dwStartAddr== dwAddr_LoadLibraryExW)
	{
		if (MessageBoxA(0, "find remote thread inject\nkill or not?", "tips", MB_OKCANCEL) == IDOK)
		{
			ExitThread(0);
		}
	}
}

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
)
{
	switch (ul_reason_for_call)
	{
	case DLL_THREAD_ATTACH:
		DWORD dwStartAddr, dwReturnLen;
		HINSTANCE hNTDLL = GetModuleHandleA("ntdll.dll");
		LPFN_ZWQUERYINFORMATIONTHREAD ZwQueryInformationThread = (LPFN_ZWQUERYINFORMATIONTHREAD)GetProcAddress(hNTDLL, "ZwQueryInformationThread");
		
		ZwQueryInformationThread(GetCurrentThread(),            //查询线程起始地址
			ThreadQuerySetWin32StartAddress,
			&dwStartAddr,
			4,
			&dwReturnLen);
	
		Check_RemoteThreadInject(dwStartAddr);				   //判断是否是远程线程注入的线程	
		break;
	}
	return TRUE;
}

结果测试
在主进程中加载该DLL并用注入器向主进程注入DLL进行测试,测试结果如下:
image

 posted on 2023-03-27 16:17  Hanpto  阅读(390)  评论(0编辑  收藏  举报