APC篇——总结与提升

博客 动态
0 260
羽尘
羽尘 2022-02-07 16:55:02
悬赏:0 积分 收藏

APC 篇——总结与提升

APC 篇之总结与提升,强调一些知识点并回去讲解系统调用剩余流程。

写在前面

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

你如果是从中间插过来看的,请仔细阅读 羽夏看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 10hIsRing0:                                ; 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 IsDebuggingFillDebugInfoBack:                      ; 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_0loc_466711:                             ; CODE XREF: _KiServiceExit+15C↓j                lea     esp, [ebp+_KTRAP_FRAME.SegFs]                pop     fs                assume fs:nothingIsRing0_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↑oarg_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系统内核——句柄表篇

知识共享许可协议
知识共享许可协议
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
本文来自博客园,作者:寂静的羽夏 ,一个热爱计算机技术的菜鸟
转载请注明原文链接:https://www.cnblogs.com/wingsummer/p/15868361.html
posted @ 2022-02-07 16:34 寂静的羽夏 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员