1.APC机制

线程是不能“杀掉”、“挂起”、“恢复”的,线程在执行的时候自己占据着CPU,别人怎么可能控制它呢?

举个极端的例子:如果不调用API,屏蔽中断,并保证代码不出现异常,线程将永久占用CPU,何谈控制呢?所以说线程如果想“死",一定是自己执行代码把自己杀死,不存在“他杀”这种情况!

那如果想改变一个线程的行为该怎么办呢?

可以给他提供一个函数,让它自己去调用,这个函数就是APC (Asyncroneus Procedure Call),即异步过程调用

APC队列

kd> dt KTHREAD
 nt! KTHREAD
 ...
 +0x034 ApcState	_KAPC_STATE
 ...
kd> dt _kapc_state
nt!_KAPC_STATE
   +0x000 ApcListHead	//2个APC队列用户APC和内核APC
   +0x010 Process		//线程所属或者所挂靠的进程_KPROCESS
   +0x014 KernelApcInProgress //内核APC是否正在执行
   +0x015 KernelApcPending	//是否有正在等待执行的内核APC 1=有
   +0x016 UserApcPending	//是否有正在等待执行的用户APC	1=有

用户APC: APC函数地址位于用户空间,在用户空间执行
内核APC: APC函数地址位于内核空间,在内核空间执行

kd> dt _kapc
nt!_KAPC
   +0x000 Type				//类型APC类型为0x12
   +0x002 Size				//本结构体的大小0x30
   +0x004 Spare0			//未使用
   +0x008 Thread			//目标线程
   +0x00c ApcListEntry		//APC队列挂的位置
   +0x014 KernelRoutine	//指向一个函数(调用ExFreePoolWithTag释放APC)
   +0x018 RundownRoutine	//未使用
   +0x01c NormalRoutine		//用户APC总入口或者真正的内核apc函数
   +0x020 NormalContext		//内核APC: NULL用户APC:真正的APC函数 
   +0x024 SystemArgument1	//APC函数的参数
   +0x028 SystemArgument2	//APC函数的参数
   +0x02c ApcStateIndex		//挂哪个队列,有四个值: 0 1 2 3
   +0x02d ApcMode			//内核APC用户APC
   +0x02e Inserted		//表示本apc是否已挂入队列挂入前: 0挂入后1

+0x01c NormalRoutine 可以找到你提供APC函数在哪,并不完全等于APC函数的地址

如果我想改变一个线程:

  1. 提供一个APC
  2. 提供+0x01c执行要执行的函数在哪
  3. 把这个APC存到KTHREAD.+0x34 ApcState.ApcListHead

当前的线程什么时候会执行我们提供的这些APC函数?

判断是否有APC要执行
在这里插入图片描述

如果有APC
在这里插入图片描述
处理apc函数KiDeliverApc,这里我门发现只有用户的apc,其实内核的apc是一定会处理的它会先处理内核apc在处理用户的apc。



KiServiceExit函数:
这个函数是系统调用、异常或中断返回用户空间的必经之路。

KiDeliverApc函数:
负责执行APC函数

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值