acl在内核里的位置_Windows 注入篇 之 内核 APC 注入

本文详细介绍了Windows下进程创建过程,特别是内核APC注入的原理。从进程创建到主线程初始化,再到系统回调和APC的调度执行,讨论了XP到Win10的不同系统版本中APC注入的实现方案,包括XP的安全软件做法和Win7以后的简化方法。重点关注了线程初始化阶段的权限和回调机制,以及如何利用这些机制进行APC注入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Windows 下进程创建过程概述:

1. 应用层通过CreateProcess发起进程创建,然后进入系统调用。

2. 系统调用中通过 NtCreateProcess,创建进程的各种资源(内存空间,句柄表,Peb,设备描述表等),此时,进程还只是一个空壳,所以必须为自己创建一个线程(即我们通常说的主线程)。

3. 主线程由KeInitThread函数进行初始化。并有内核调度,启动点是PspUserThreadStartup。

4. PspUserThreadStartup为主线程的Ring3初始化环境,加载进程的动态链接库,这个函数是家喻户晓的ntdll!LdrInitializeThunk,在内核线程受到调度回到Ring3层时,Apc被调度执行。

5. 一般的线程的Ring3层入口,是ntdll!RtlUserThreadStart,由于每次内核返回Ring3的过程时都会尝试调用Apc

二、系统回调

Apc注入离不开系统回调,而Apc是线程相关的,那么就肯定要在回调中由线程Id去查找线程体(ETHREAD),我们看进程回调与线程回调的调用位置,两者都是在PspCreateThread中得到执行:

60bda6f5f48d9acc54518a717bbba3de.png

初始化线程的时候才会将EProcess.UniqueProcessId置为其句柄表的索引,后续线程创建时将不再通知进程回调。而这个时候PspCreateThread还未将当前线程体初始化完毕,特别的是EThread.GrantedAccess没被初始化,那么在进/线程中 不管是Ring3的OpenThread或者是Ring0的PsLookupThreadByThreadId都将Fail,这个算是微软的一个小bug,但是到Vista之后,也就是Win7~Win10都不存这个问题了

三、Win7及之后的系统APC调整

Win7及之后的系统版本动态库加载点ntdll!LdrInitializeThunk不再使用Apc的方式启动,而是直接将TrapFrame.EIP修改为ntdll!LdrInitializeThunk,这样UserMode Apc的执行机会就自然被延迟了,那么延迟到什么时候呢? (这是64位ntdll,不过跟32也没什么差别):

08c60fe29151b276f13e854df34708f4.png

ntdll!LdrInitializeThunk会调入_LdrpInitialize,在加载完导入表的一系列模块依赖之后会调用ZwTestAlert,他会将当前线程的Apc队列的UserPending重新置位,让已存在队列里的UserMode Apc得到执行(就在此次系统调用返回用户层之后)。

四、 XP~Win10 APC注入方案实现

XP之前由于进程回调的限制,所以与Win7后续要分两种情况处理,有安全软件的做法是采用劫持KiFastCallEntry,在进程初始化加载动态链接库的过程会调用NtQuerySection询问系统模块,以这个点作为Apc注入时机,这样麻烦,直接在模块回调通知exe加载时就可以了,而且又可以避免Apc插入到LdrInitializeThunk的UserApc之前,因为Image回调在通知exe加载的时候在这里:

5bc320349d8b2d0876c4ca5207666885.png

这里正好是待创建进程的主线程刚得到调度的时候,这里线程体什么的都已初始化完毕,可以无忧进行插入。

Win7及之后由于没有那么多限制,可以直接在进程回调完成。

备注: 如果需要相关验证代码,请关注我并给我私信留言

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值