随笔- 20  文章- 0  评论- 0  阅读- 5910 

远程线程注入
        远程线程注入是一种常见的注入手段,是一种跨进程创建线程的注入手法。
        其实现思路是将待注入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   Hanpto  阅读(432)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示