.NET内网实战:通过线程池等待对象实现线程注入
原文链接: https://mp.weixin.qq.com/s?__biz=MzUyOTc3NTQ5MA==&mid=2247500073&idx=1&sn=70def9028da43f156cc586ca9b2f6fc3
.NET内网实战:通过线程池等待对象实现线程注入
专攻.NET安全的 dotNet安全矩阵 2025-07-13 03:10
01
阅读须知
此文所节选自小报童《.NET 内网实战攻防》专栏,主要
内容有.NET在各个内网渗透阶段与Windows系统交互的方式和技巧,对内网和后渗透感兴趣的朋友们可以订阅该电子报刊,解锁更多的报刊内容。
02
基本介绍
本文内容部分节选自小
报童《.NET 通过线程池等待对象实现线程注入
》,
完整的
文章内容请加入小报童后订阅查看。
现在限时
只需69元,永久
买断!
目前已有300+位朋友抢先预定,我们会长期更新,对.NET内网安全的朋友们请尽快订阅该报刊!
03
原理分析
在 Windows 操作系统中,线程池是一种高效的系统资源管理机制,被广泛用于执行异步任务、IO 完成回调、定时器事件等。微软 Windows 提供了一系列与线程池相关的原生 API,如 CreateThreadpoolWait、WaitForSingleObject 等,用于创建和管理基于事件触发的线程回调。
3.1 技术原理
线程池等待对象注入的核心思想是构造一个等待对象事件(Event),注册一个线程池等待回调,然后将 Shellcode 地址作为回调函数指针,再触发事件,系统线程池将执行 shellcode。
整个流程可分为以下几步:
1. 创建一个事件对象(Event Object)
2. 分配一块可执行内存并写入 Shellcode
3. 调用 CreateThreadpoolWait 设置 shellcode 为回调函数
4. 使用 SetThreadpoolWait 将线程池等待对象与事件绑定
5. 使用 WaitForSingleObject 或其他方法触发事件
线程池机制内部会调用 RtlpExecuteWaitCallback 来执行与该事件相关的回调函数,从而完成 shellcode 的执行。
3.2 CreateThreadpoolWait
CreateThreadpoolWait函数是Windows线程池API的组件之一,常用于创建一个等待对象,当特定的事件对象被设置为signaled状态或发生超时事件时,该等待对象将触发预设的回调函数。该函数在.NET平台下的签名如下所示。
[DllImport("kernel32.dll")]
publicstaticexternIntPtrCreateThreadpoolWait(IntPtr pfnwa,IntPtr pv,IntPtr pcb);
参数 pfnwa:指向回调函数的地址,这里我们传递 shellcode 的地址。参数 pv / pcb:通常设置为 0,可忽略。该函数返回一个 TP_WAIT 结构的指针,代表线程池等待对象。
3.3 CreateEvent
CreateEvent函数用于创建一个事件对象,一般情况下通过设置第三个参数的值为True,让事件在单个等待操作之后不会自动重置为未发信号(unsignaled)状态。该函数在.NET平台下的签名如下所示。
[DllImport("kernel32.dll")]
publicstaticexternIntPtrCreateEvent(IntPtr lpEventAttributes,bool bManualReset,bool bInitialState,string lpName);
参数 bManualReset:设置为 false,表示系统在一个等待线程被释放后自动重置信号,另外,参数 bInitialState:设置为 true,表示事件初始为 signaled 状态,确保回调能被立即触发。
3.4 实战代码解析
在红队实战中,这几个函数可能会被一起使用,作为加载和执行Shellcode等恶意代码的一种手段。下面是一个使用这些API函数加载Shellcode的示例,具体代码如下所示
string Event_lpname =null;
IntPtr Event_handle =CreateEvent(IntPtr.Zero,false,true, Event_lpname);
IntPtr Buf1_address =VirtualAlloc(IntPtr.Zero,(UInt32)buf1.Length,0x1000,0x40);
IntPtr TP_WAIT_pointer =CreateThreadpoolWait(Buf1_address, IntPtr.Zero, IntPtr.Zero);
SetThreadpoolWait(TP_WAIT_pointer, Event_handle, IntPtr.Zero);
在上述代码中,首先,通过CreateEvent函数创建一个已发信号(signaled)的事件对象,这要求将CreateEvent的第三个参数设置为TRUE,以便事件对象在单个等待操作之后保持已发信号的状态。如果未将事件对象设置true,那么任何依赖于该事件对象的线程池等待回调将不会触发,导致进程可能陷入无限等待状态。
综
上 ,
线程池等待对象注入技术是一种利用 Windows 系统线程池的低检测率内存注入方式。它不依赖显式线程创建,而是将 shellcode 注入到系统线程池所管理的线程中,通过事件对象触发其执行,达到隐藏行为、绕过检测的目的。
想要了解
完整或者更多的内网安全方向的文章,可以移步订阅小报童《.NET 内网实战攻防》电子报刊。
04
欢迎加入.NET 电子报刊
我们的小报童电子报刊【.NET内网安全攻防】也开始运营,引入小报童也是为了弥补知识星球对于轻量级阅读支持的不足,为用户读者提供更佳的阅读体验。
如果您对阅读体验的需求比较高,那么可以订阅这个专栏
。
本
次电子报刊《.NET 内网安全攻防》专栏,内容主要有.NET在各个内网渗透阶段与Windows系
统交互的方式和技巧,可细分为以下8个方向。
1) .NET 安全防御绕过
2) .NET 本地权限提升
3) .NET 内网信息收集
4) .NET 内网代理通道
5) .NET 内网横向移动
6) .NET 目标权限维持
7) .NET 数据传输外发
8) .NET 目标痕迹清理
原价899,现在限时
只需69元,永久买断
!
目前已有300+位朋友抢先预定,我们会长期更新,初步计划保持每周更新1-2篇新内容,对.NET内网安全的朋友们请尽快订阅该报刊!
每增加五十人涨价10元,抓紧订阅,超值!
订阅后请关注公众号:
dotNet安全矩阵,发送订单截图和您的微信号,邀请您加入专属交流群。
感兴趣的朋友,可以点击链接:https://xiaobot.net/p/dotNetAttack,或者
扫描下方海报微信二维码加入即可
,
订阅后小报童定时会将最新内容通过微信推送给您。