写在前面

  此系列是本人一个字一个字码出来的,包括示例和实验截图。由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我

你如果是从中间插过来看的,请仔细阅读 羽夏看Win系统内核——简述 ,方便学习本教程。

  看此教程之前,问几个问题,基础知识储备好了吗?保护模式篇学会了吗?练习做完了吗?没有的话就不要继续了。


华丽的分割线


小结

  本篇章我们从APC是什么?是怎样初始化的,是怎样插入的,是怎样执行的这几个方面学习。总体来说APC基础知识也就这些。下面先强调一些我介绍过但没有指明出来的知识点。

  我提出几个问题,如果你能回答上来,就说明仔细学了或者自己能够挖掘我没明说的东西。

  1. 当处理 APC 的时候,内核 APC 一定会处理吗?用户 APC 一定处理吗?在那个函数点进行处理的?
  2. 挂 APC 的链表有两个,存放于一个具有两个成员链表数组中,请问索引是0的是挂内核 APC 的还是用户 APC 的,索引是1的同理?
  3. 应用层的用户 APC 是怎样到3环执行的?

  我给出如下答案:

  1. 内核 APC 一定会处理,用户 APC 不一定会处理。处理的点是线程交换(只处理内核 APC)和 API调用与中断异常退出函数处(都处理)。
  2. 索引是0的是挂的是内核 APC ,索引是1的是挂的用户 APC。
  3. 通过用 CONTEXT 保存原来的 TrapFrame ,然后修改返回到一个函数处理。

系统调用返回分析

  我们学系统调用的时候有一个坑还没填完,那就是系统API是如何返回的,但是学完APC之后,这就没什么好讲的了,自己继续逆向就差不多了,但是还是逆向的结果还是有坑,下面我就把这个坑给你填上。现在我把如下我的反汇编结果给你:

loc_46663A:                             ; CODE XREF: _KiBBTUnexpectedRange+38↑j
; _KiBBTUnexpectedRange+43↑j
mov ecx, ds:0FFDFF124h
mov edx, [ebp+_KTRAP_FRAME._Edx]
mov [ecx+_KTHREAD.TrapFrame], edx
_KiFastCallEntry endp _KiServiceExit proc near ; CODE XREF: KiCallUserMode(x,x)+E7↑j
; _KiSetLowWaitHighThread+7D↓j ... ; FUNCTION CHUNK AT .text:00466754 SIZE 00000088 BYTES cli
test [ebp+_KTRAP_FRAME.EFlags], 20000h
jnz short IsVM8086_0
test byte ptr [ebp+_KTRAP_FRAME.SegCs], 1
jz short IsRing0 ; 开始还原堆栈存储的环境 IsVM8086_0: ; CODE XREF: _KiServiceExit+8↑j
; _KiServiceExit+63↓j
mov ebx, ds:0FFDFF124h
mov [ebx+_KTHREAD.Alerted], 0
cmp [ebx+_KTHREAD.ApcState.UserApcPending], 0
jz short IsRing0 ; 开始还原堆栈存储的环境
mov ebx, ebp
mov [ebx+_KTHREAD.ApcState.Process], eax
mov dword ptr [ebx+_KTHREAD.IdleSwapBlock], 3Bh ; ';'
mov [ebx+_KTHREAD.ApcState.ApcListHead.Blink], 23h ; '#'
mov [ebx+_KTHREAD.ApcState.ApcListHead.Flink], 23h ; '#'
mov dword ptr [ebx+_KTHREAD.Iopl], 0
mov ecx, 1 ; NewIrql
call ds:__imp_@KfRaiseIrql@4 ; KfRaiseIrql(x)
push eax
sti
push ebx ; trapframe
push 0 ; unknown
push 1 ; CanUserAPC
call _KiDeliverApc@12 ; KiDeliverApc(x,x,x)
pop ecx ; NewIrql
call ds:__imp_@KfLowerIrql@4 ; KfLowerIrql(x)
mov eax, [ebx+_KTHREAD.ApcState.Process]
cli
jmp short IsVM8086_0
; ---------------------------------------------------------------------------
align 10h IsRing0: ; CODE XREF: _KiServiceExit+E↑j
; _KiServiceExit+1E↑j
mov edx, [esp+_KTRAP_FRAME.ExceptionList] ; 开始还原堆栈存储的环境
mov ebx, large fs:_KPCR.DebugActive
mov large fs:_KPCR, edx
mov ecx, [esp+_KTRAP_FRAME.PreviousPreviousMode]
mov esi, large fs:_KPCR.PrcbData.CurrentThread
mov [esi+_KTHREAD.PreviousMode], cl
test ebx, 0FFh
jnz short IsDebugging FillDebugInfoBack: ; CODE XREF: _KiServiceExit+11B↓j
; _KiServiceExit+14A↓j
test [esp+_KTRAP_FRAME.EFlags], 20000h
jnz IsVM8086_Exit
test word ptr [esp+_KTRAP_FRAME.SegCs], 1111111111111000b
jz loc_4667AA
cmp word ptr [esp+_KTRAP_FRAME.SegCs], 1Bh
bt word ptr [esp+_KTRAP_FRAME.SegCs], 0 ; CF = CS & 1
cmc ; CF = !CF
ja IsRing3_Exit
cmp word ptr [ebp+_KTRAP_FRAME.SegCs], 8
jz short IsRing0_0 loc_466711: ; CODE XREF: _KiServiceExit+15C↓j
lea esp, [ebp+_KTRAP_FRAME.SegFs]
pop fs
assume fs:nothing IsRing0_0: ; CODE XREF: _KiServiceExit+C6↑j
lea esp, [ebp+_KTRAP_FRAME._Edi]
pop edi
pop esi
pop ebx
pop ebp
cmp word ptr [esp+8], 80h ; '€' ; cmp tf.cs , 80
ja loc_466FF0 ; 这个地方一定不会跳转
add esp, 4
test dword ptr [esp+4], 1 ; test tf.cs,1,判断是3环还是0环
_KiServiceExit endp ; sp-analysis failed

  好,也就是这里开始有坑,我继续把反汇编结果列上:

_KiSystemCallExitBranch proc near       ; DATA XREF: KiDisableFastSyscallReturn()+9↑w
; KiEnableFastSyscallReturn():loc_425D2C↑r ... ; FUNCTION CHUNK AT .text:0046673C SIZE 00000001 BYTES jnz short _KiSystemCallExit
pop edx
pop ecx
popf
jmp edx
_KiSystemCallExitBranch endp ; ---------------------------------------------------------------------------
; START OF FUNCTION CHUNK FOR _KiSystemCallExit2
; ADDITIONAL PARENT FUNCTION _KiSystemCallExitBranch _KiSystemCallExit: ; CODE XREF: _KiSystemCallExitBranch↑j
; _KiSystemCallExit2+5↓j
; DATA XREF: ...
iret
; END OF FUNCTION CHUNK FOR _KiSystemCallExit2 ; =============== S U B R O U T I N E ======================================= _KiSystemCallExit2 proc near ; DATA XREF: KiRestoreFastSyscallReturnState()+16↑o arg_5 = byte ptr 9 ; FUNCTION CHUNK AT .text:0046673C SIZE 00000001 BYTES test byte ptr [esp+9], 1
jnz short _KiSystemCallExit
pop edx
add esp, 4
and byte ptr [esp+1], 0FDh
popf
pop ecx
sti
sysexit
iret
_KiSystemCallExit2 endp ; sp-analysis failed

  通过test判断是否是3环,如果是的话跳走用iret返回,看似没啥问题。但是如果我是快速调用进入的,这就有问题了,因为有对应的sysexit退出的。我们用WinDbg得出如下结果:

  是不是很奇怪?发现实际是通过KiSystemCallExit2退出的。这就是静态分析和动态分析的不同之处。

  sysexit的为我们做哪些事情呢?我给说明一下:

  1. 将 IA32_SYSENTER_CS + 0x10 装载到 cs 寄存器,将 edx 寄存器中的指令的指针装载到 eip ;
  2. 将IA32_SYSENTER_CS + 0x18 装载到 ss 寄存器中;
  3. 将 ecx 寄存器中的指针装载到 esp 中,切换到3环权限;

  到此系统调用怎么进0环,做了那些事情,怎么出0环,就结束了。

下一篇

  羽夏看Win系统内核——句柄表篇

APC 篇——总结与提升的更多相关文章

  1. 羽夏看Win系统内核—— APC 篇

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  2. APC 篇—— APC 执行

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  3. APC 篇——初识 APC

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  4. APC 篇——备用 APC 队列

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  5. APC 篇—— APC 挂入

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  6. 【Spark机器学习速成宝典】模型篇07梯度提升树【Gradient-Boosted Trees】(Python版)

    目录 梯度提升树原理 梯度提升树代码(Spark Python) 梯度提升树原理 待续... 返回目录 梯度提升树代码(Spark Python) 代码里数据:https://pan.baidu.co ...

  7. 1. 不吹不擂,第一篇就能提升你对Bean Validation数据校验的认知

    乔丹是我听过的篮球之神,科比是我亲眼见过的篮球之神.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免 ...

  8. 高并发高负载系统架构-php篇

    首先呢,我罗列一下文章的目录,让大家有个整体轮廓的了解! 1.为什么要进行高并发和高负载的研究 2.高并发和高负载的约束条件 3.解决之道——硬件篇 4.解决之道——部署篇 5.解决之道——环境篇 6 ...

  9. 羽夏看Win系统内核——进程线程篇

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

随机推荐

  1. 1016 - Brush (II)

    1016 - Brush (II)    PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Afte ...

  2. Codeforces629 C. Famil Door and Brackets

    C. Famil Door and Brackets time limit per test 2 seconds memory limit per test 256 megabytes input s ...

  3. 计算机视觉1->opencv4学习指南1 | 环境配置与例程

    opencv虽然很有名,但是自己一直没怎么玩过,暑假的时候使用深度相机做项目,但负责的不是代码模块,也只是配好了环境,没有继续了解图像处理.最近电子实习老师有教这个东西,但是身边不少同学遇到了麻烦,所 ...

  4. WebRTC下 的 NAT 穿透技术

    NAT的概念模型 NAT名字很准确,网络地址转换,就是替换IP报文头部的地址信息.NAT通常部署在一个组织的网络出口位置,通过将内部网络IP地址替换为出口的IP地址提供公网可达性和上层协议的连接能力. ...

  5. [云原生]Kubernetes - 集群搭建(第2章)

    目录 一.前置知识点 二.kubeadm部署方式介绍 三.安装要求 四.最终目标 五.准备环境 六.环境初始化 6.1 设置系统主机名以及Hosts文件的相互解析 6.2 安装依赖文件(所有节点) 6 ...

  6. Java初学者作业——编写JAVA程序,要求输入技术部门5位员工的理论成绩和实操成绩,计算并输出各位员工的最终评测成绩。

    返回本章节 返回作业目录 需求说明: 某软件公司要求对技术部门的所有员工进行技能评测,技术评测分为两个部分:理论部分以及实操部分,最终评测成绩=理论成绩×0.4+实操成绩×0.6,要求输入技术部门5位 ...

  7. 编写Java程序,模拟文件操作过程中的异常处理

    返回本章节 返回作业目录 需求说明: 从控制中输入计算机磁盘中后缀名为".txt"的文件的完整物理路径. 如果该文件存在,则在控制台输出友好提示信息,告知用户该文件存在,如果文件不 ...

  8. EMQX源码编译过程

    以emqx4.0.7版本为例 1.安装erlang环境 可以参考:https://www.cnblogs.com/shanfeng1000/p/11951703.html 这里需要注意一下,要按照em ...

  9. 初识python: 属性方法 @property

    属性方法:通过@property把一个方法变成一个静态属性 实例: 调用航班的状态 # 查看航班状态 import random class CheckState(object): def __ini ...

  10. 详谈 Java工厂 ---工厂方法模式

    1.前言 有个场景,消费者需要付钱,有可能是使用支付宝.微信.银行卡,那么该怎么选择呢? 是不是想到了使用用if else判断?还是使用switch? 一个地方这样写还好,如果有很多这样的业务,难道都 ...