远程线程注入
远程线程注入是一种常见的注入手段,是一种跨进程创建线程的注入手法。
其实现思路是将待注入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进行测试,测试结果如下:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通