2-创建远程线程注入(CreateRemoteThread Injection)

一、前言

创建远程线程注入 又是另一个经典且使用最多的一种shellcode和dll注入方式

创建远程线程注入 是指一个进程在另一个进程中创建线程的技术,通常用于注入dll或shellcode,两者执行方式会有一些简单的差异但是原理相同,这是一种简单且稳定的经典注入方式,被很多病毒木马所青睐,此外也存在更新式的注入方式。

二、流程

  1. 使用 VirtualAllocEx 在远程进程中申请空间。官方文档:VirtualAllocEx 函数 (memoryapi.h) - Win32 apps | Microsoft Learnarrow-up-right

  2. 使用 WriteProcessMemory 将数据写入到指定进程中的内存区域。 要写入的整个区域必须可访问,否则操作将失败。官方文档:WriteProcessMemory 函数 (memoryapi.h) - Win32 apps | Microsoft Learnarrow-up-right

  3. 使用 CreateRemoteThread 创建在另一个进程的虚拟地址空间中运行的线程。官方文档:CreateRemoteThread 函数 (processthreadsapi.h) - Win32 apps | Microsoft Learnarrow-up-right

  4. 使用 WaitForSingleObject 等待远程线程结束。官方文档:WaitForSingleObject 函数 (synchapi.h) - Win32 apps | Microsoft Learnarrow-up-right

偷来的图,将就看一下吧😀

三、代码实现

3.1 注入shellcode

(一)完整代码

输入被注入进程的PID,比如下图的notepad.exe的PID是27840

(二)调式

虽然VS可以查看内存情况,但是只能查看本进程,即正在调式运行的进程的内存布局,想要看其他进程的内存空间就需要借助其他工具。反是涉及到注入到远程进程的,我都建议使用x32/64dbg和VS联动,这样能看到目标进程的的内存情况,有助于帮助我们判断是否注入成功。

  1. x64dbg附加进程

可以通过菜单"文件"->"附加"(或者按下快捷键Alt+A)会弹出如下图所示的附加对话框,读者只需要选中一个正在运行的程序即可附加到特定进程内

  1. VS调式运行

VirtualAllocEx 这里下一个断点,然后运行即可

  1. 复制想要查看的地址值

在本例中是 lpAddress 的值是0x0000021483150000(每次运行都不一样)

  1. 在x64dbg中查看相应地址的内存情况

快捷键:ctrl+G,输入目标地址值,即可查看相应地址的内存情况

演示

3.2 注入DLL

(一)完整代码

DLL(Dynamic Link Library)是动态链接库,其中包含可由另一个模块 (应用程序或 DLL) 使用的函数和数据,在免杀和C2中是很常用的一种PE文件。在实际的免杀中,单exe免杀的效果往往很差,更多是配合 白加黑 等手段达到一个很好免杀效果。更多DLL的玩法,我会在后面详细介绍,这里我只是简单的提一下恶意DLL的制作。

  1. 添加一个DLL项目

项目结构如下,我们只需修改dllmain.cpp即可

解释一下代码,DllMain,这是 DLL 的入口点,暂时用不到dll编写导出函数,我们只需要DllMain函数就可以了。当 ur_reason_for_call 满足下列几种情况时会执行相应的代码(需要自己添加)

  • DLL_PROCESS_ATTACH

  • DLL_THREAD_ATTACH

  • DLL_THREAD_DETACH

  • DLL_PROCESS_DETACH

  1. 构造恶意的黑DLL,并在其中运行shellcode。

点击生成,得到恶意dll

注意

  • 在DLL中执行shellcode是不能用 WaitForSingleObject,因为可以能导致DLL死锁风险,虽然有解决方法,但是还是不推荐使用。

  • 32位程序只能注入32位程序,64位程序只能注入64位程序。跨位数注入好像msf里有提及,感兴趣的可以去找一下源码。

  1. 加载器代码

注意

  1. 在 Windows 操作系统中,进程的虚拟地址空间是相互隔离的,这意味着每个进程都有自己的虚拟地址空间,不能直接访问其他进程的内存。

  2. 为什么远程进程能使用LoadLibraryA的地址呢?因为kernel32ntdll.dll 等DLL是一个共享的系统库,所有进程都可以访问,所有Windows 进程在加载该库时会使用相同的VA。这一点请理清楚,后面会很多知识点都会涉及这一个内容。

(二)调式

与注入shellcode同理,我们要用x32/64dbg来验证我们的DLL路径是否写入到了目标进程的内存中

演示

Last updated