Windows APC学习笔记(一)—— APC的本质&备用APC队列

  • 基础知识
  • APC的本质
    • APC队列
    • APC结构
    • 分析 KiServiceExit
    • 总结
  • 备用APC队列
    • 挂靠环境下ApcState的意义
    • ApcStatePointer
    • ApcStateIndex
    • 组合寻址
    • ApcQueueable

基础知识

  1. 线程是不能被“杀掉”、“挂起”、“恢复”的,线程在执行的时候自己占据着CPU,别人不能控制它
  2. 举个极端的例子:如果不调用API屏蔽中断并保证代码不出现异常,线程将永久占用CPU
  3. 所以说线程如果想“死”,一定是自己执行代码把自己杀死,不存在“他杀”的情况

思考:那如果想改变一个线程的行为该怎么办
答案:可以给他提供一个函数,让它自己去调用:APC(Asyncroneus Procedure Call,异步过程调用)

APC的本质

APC队列

在Windbg中查看


ApcListHead

  1. 由两个双向链表组成,共占16个字节
  2. 提供的APC函数可能是用户函数,也可能是系统函数(简单的区分方法就是判断函数地址是否大于0x80000000

Process:指向线程所属或者挂靠进程
KernelApcInProgress:内核Apc是否正在执行
KernelApcPending:是否存在等待状态的内核APC,存在则置1
UserApcPending:是否存在等待状态的用户APC,存在则置1

APC结构

在WinDbg中查看

NormalRoutine:找到提供的APC函数,并不完全等于APC函数的地址,后续将重点学习

分析 KiServiceExit

总结

如果我们想要改变一个线程,可以先提供一个APC,然后通过 _KAPC.NormalRoutine 指向我们提供的APC在哪里,再将APC存到 _KTHREAD.ApcState.ApcListHead 的第一个成员中

思考:当前线程什么时候将会执行提供的APC
答案

  1. KiServiceExit 函数(系统调用异常中断返回用户控件的必经之路)
  2. KiDeliverApc 函数(负责执行APC函数)

备用APC队列

描述

  1. _KTHREAD+0x14c 位置处,同样也存在一个 _KAPC_STATE 结构体,叫做 SavedApcState
  2. 线程APC队列中的APC函数都是与进程相关联的,具体点说:A进程的T线程中的所有APC函数,要访问的内存地址都是A进程的
  3. 但线程是可以挂靠到其他的进程:比如A进程的线程T,通过修改Cr3(改为B进程的页目录基址),就可以访问B进程地址空间,即所谓“进程挂靠”
  4. 当T线程挂靠B进程后,APC队列中存储的却仍然是原来的APC。具体点说,比如某个APC函数要读取一个地址为0x12345678的数据,如果此时进行读取,读到的将是B进程的地址空间,这样逻辑就错误了
  5. 为了避免混乱,在T线程挂靠B进程时,会将ApcState中的值暂时存储到SavedApcState中,等回到原进程A时,再将APC队列恢复。
  6. 因此,SavedApcState又称为备用APC队列

挂靠环境下ApcState的意义

在挂靠的环境下,也是可以先线程APC队列插入APC的

A进程的T线程挂靠B进程  A是T的所属进程  B是T的挂靠进程
ApcState        B进程相关的APC函数
SavedApcState   A进程相关的APC函数

在正常情况下,当前进程就是所属进程A,如果是挂靠情况下,当前进程就是挂靠进程B

ApcStatePointer

描述:为了操作方便,_KTHREAD 结构体中定义了一个指针数组 ApcStatePointer ,长度为2,位于 _KTHREAD+0x138

正常情况下

ApcStatePointer[0] 指向 ApcState
ApcStatePointer[1] 指向 SavedApcState

挂靠情况下

ApcStatePointer[0] 指向 SavedApcState
ApcStatePointer[1] 指向 ApcState

ApcStateIndex

描述ApcStateIndex 用来标识当前线程处于什么状态,位于 _KTHREAD+0x165

0:正常状态
1:挂靠状态

组合寻址

正常情况下,向ApcState队列中插入APC时:

ApcStatePointer[0] 指向 ApcState,此时 ApcStateIndex 的值为 0
ApcStatePointer[ApcStateIndex] 指向 ApcState

挂靠情况下,向ApcState队列中插入APC时:

ApcStatePointer[1] 指向 ApcState,此时 ApcStateIndex 的值为 1
ApcStatePointer[ApcStateIndex] 指向 ApcState

总结

无论什么环境下,ApcStatePointer[ApcStateIndex] 指向的都是 ApcState
ApcState 总是表示线程当前使用的apc状态

ApcQueueable

描述

  1. 位于 _KTHREAD+0x166,表示是否可以向线程的APC队列中插入APC
  2. 当线程正在执行退出的代码时,会将这个值设置为0 ,如果此时执行插入APC的代码(KeInsertQueueApc),在插入函数中会判断这个值的状态,如果为0,则插入失败

Windows APC学习笔记(一)—— APC的本质备用APC队列相关推荐

  1. Windows APC学习笔记(二)—— 挂入过程执行过程

    Windows APC学习笔记(二)-- 挂入过程&执行过程 基础知识 挂入过程 KeInitializeApc ApcStateIndex KiInsertQueueApc Alertabl ...

  2. Windows异常学习笔记(二)—— 内核异常处理流程用户异常的分发

    Windows异常学习笔记(二)-- 内核异常处理流程&用户异常分发 用户层与内核层异常 内核异常 分析 KiDispatchException 分析 RtlDispatchException ...

  3. Windows系统调用学习笔记(二)—— 3环进0环

    Windows系统调用学习笔记(二)-- 3环进0环 要点回顾 基本概念 _KUSER_SHARED_DATA 0x7FFE0300 实验:判断CPU是否支持快速调用 第一步:修改EAX=1 第二步: ...

  4. Windows异常学习笔记(五)—— 未处理异常

    Windows异常学习笔记(五)-- 未处理异常 要点回顾 最后一道防线 实验一:理解最后一道防线 实验二:新线程的最后一道防线 总结 UnhandledExceptionFilter 实验三:理解U ...

  5. Windows异常学习笔记(四)—— 编译器扩展SEH

    Windows异常学习笔记(四)-- 编译器扩展SEH 要点回顾 编译器支持的SEH 过滤表达式 实验一:理解_try_except 实验二:_try_except 嵌套 拓展SEH结构体 scope ...

  6. Windows异常学习笔记(一)—— CPU异常记录模拟异常记录

    Windows异常学习笔记(一)-- CPU异常记录 基础知识 异常的分类 CPU异常 分析中断处理函数 _KiTrap00 分析 CommonDispatchException 总结 软件模拟异常 ...

  7. Windows系统调用学习笔记(四)—— 系统服务表SSDT

    Windows系统调用学习笔记(四)-- 系统服务表&SSDT 要点回顾 系统服务表 实验:分析 KiSystemService 与 KiFastCallEntry 共同代码 SSDT 实验: ...

  8. Windows系统调用学习笔记(三)—— 保存现场

    Windows系统调用学习笔记(三)-- 保存现场 要点回顾 基本概念 Trap Frame 结构 线程相关的结构体 ETHREAD KTHREAD CPU相关的结构体 KPCR _NT_TIB KP ...

  9. Windows系统调用学习笔记(一)—— API函数调用过程

    Windows系统调用学习笔记(一)-- API函数调用过程 Windows API 实验1:分析ReadProcessMemory 第一步:定位函数 第二步:开始分析 总结 实验2:分析NtRead ...

最新文章

  1. 关于HashCode方法,可变对象和内存泄漏问题
  2. Cover the Tree(2020多校第二场C)
  3. “五一”档总票房破13亿 《你的婚礼》高居榜首
  4. jieba库初识与运用
  5. 计算机乐谱吃鸡,Capo可自动识别音乐生成乐谱
  6. WPF程序支持多国语言
  7. 联结全球技术桥梁,TGO 鲲鹏会台北分会将于 6/24 成立
  8. 求极值函数-MATLAB
  9. Android Couldn‘t find meta-data for provider with authority
  10. MarkDown的使用教程
  11. 使用php解析url中出现\u002乱码问题的方法
  12. Android自定义ImageView圆角
  13. Multi-Objective Computation Sharing in Energy and Delay Constrained Mobile Edge Computing
  14. PDF怎么转长图?这些方法不妨了解一下
  15. 啃完这些Java面试题,面试阿里P7稳了
  16. 我亲爱的朋友们_亲爱的lazyweb-我该如何处理所有电子邮件?
  17. 序列化--Serial
  18. 【Industry digitization】能源供应商的数字化转型,能源世界正在发生不可逆转的深刻变革
  19. 使用IMS实现LTE的语音通话(VoLTE)
  20. 树莓派使用VGA显示器输出

热门文章

  1. keras保存和载入模型继续训练
  2. 【MM系列】SAP 簇表 A017 物料信息记录 (指定工厂) 包含的透明表
  3. 老王Python-进阶篇4-面向对象第三节
  4. 倒计时321控制器设置
  5. linux软件管理(Vim编辑器使用) ——(七)
  6. Java 中浮点数---------BigDecimal和double(初探)
  7. 又拍云递归删除目录及文件
  8. 几个网页制作的小技巧
  9. 句法分析:依存分析(Dependency Parsing)
  10. c++新特性11 (10)shared_ptr六”构造函数unique_ptr参数“