APC的本质

什么是APC

如果想改变一个线程的行为,可以给它提供一个函数,让他自己去调用,这个函数就是APC(Asyncroneus Procedure Call),即异步过程调用

谁插入的APC
一定是由别的线程插入。给别的线程插入APC相当于给它写一封信,程序会每隔一段时间去信箱里面检查有没有信。

插入到哪里
_KTHREAD +0x34 有两个APC队列 用户APC和内核APC
谁执行的APC
插入的目标线程执行的APC
什么时候执行的APC
内核APC在线程切换的时候执行
用户APC在KiServiceExit的时候执行

在这里插入图片描述

Apc队列 _KAPC_STATE

+dt _KAPC_STATE
+0 ApcLIstHead // +0 内核APC队列 +8用户Apc 队列 记录的是所有APC结构体(初始化APC时,申请了一块内存来保存APC信息,链表记录的就是这个结构体+c的地址) 。
+0x10 Process //线程所属或者所挂靠的进程
+0x14 KernelApcInProcess //内核APC是否正在执行
+0x15 KernelApcInPending //是否有正在等待执行的内核APC
+0x16 UserApcPending //是否有正在等待执行的用户APC

_KAPC结构体

typedef struct _KAPC {
    CSHORT Type;    //apc类型为0x12
    CSHORT Size;	//结构体大小0x30
    ULONG Spare0;	//未使用
    PVOID Thread;	//PKTHREAD 目标线程
    LIST_ENTRY ApcListEntry; //LIST_ENTRY 
    PKKERNEL_ROUTINE KernelRoutine;  //指向函数IopDeallocateApc (调用ExFreePoolWithTag释放APC)
    PKRUNDOWN_ROUTINE RundownRoutine;  
    PKNORMAL_ROUTINE NormalRoutine;   //用户APC总入口 全局变量KeUserApcDispatcher的值 指向KiUserApcDispatcher函数   或者真正内核apc函数
    PVOID NormalContext;    //内核APC :NULL 用户APC :真正的apc函数
    PVOID SystemArgument1;	//QueueUserApc的参数三
    PVOID SystemArgument2;  //返回值
    CCHAR ApcStateIndex;	//挂哪一个队列,0 1 2 3 自己用的时候使用0或者1   0挂亲爹  1挂养父
    KPROCESSOR_MODE ApcMode; //内核APC 0 用户APC 1
    BOOLEAN Inserted;		 // 表示本APC是否已挂入队列 挂入前 0 挂入后 1
} KAPC, *PKAPC, *RESTRICTED_POINTER PRKAPC;

APC队列结构体的查找

链表里面的值(_KAPC)取出来要-0c才是结构体的首地址(链表挂在腰上)

在这里插入图片描述

练习:

1、自己编写代码向某个线程插入一个用户APC

2、分析TerminateThread/SuspendThread是如何实现的(从3环开始分析)

3、自己分析APC的插入过程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值