吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2242|回复: 2
收起左侧

[C&C++ 原创] 系统调用和返回

[复制链接]
古月不傲 发表于 2020-3-10 01:19
本帖最后由 古月不傲 于 2020-3-10 03:03 编辑

_KiFastCallEntry:
[Asm] 纯文本查看 复制代码
.text:0046A520 ; PAE模式 系统调用必经之路
.text:0046A520
.text:0046A520 _KiFastCallEntry proc near              ; DATA XREF: KiLoadFastSyscallMachineSpecificRegisters(x)+24↑o
.text:0046A520                                         ; _KiTrap01+74↓o
.text:0046A520
.text:0046A520 Eflags_IF       = byte ptr -0Bh
.text:0046A520
.text:0046A520 ; FUNCTION CHUNK AT .text:0046A4ED SIZE 00000026 BYTES
.text:0046A520 ; FUNCTION CHUNK AT .text:0046A7C0 SIZE 00000014 BYTES
.text:0046A520
.text:0046A520                 mov     ecx, 23h
.text:0046A525                 push    30h
.text:0046A527                 pop     fs              ; fs:30
.text:0046A529                 mov     ds, ecx         ; ds:23
.text:0046A52B                 mov     es, ecx         ; es:23
.text:0046A52D                 mov     ecx, large fs:40h ; kpcr->ktss
.text:0046A534                 mov     esp, [ecx+4]    ; ktss->esp0 指向 _KTRAP_FRAME->+0x07c V86Es
.text:0046A537                 push    23h             ; KTRAP_FRAME->HardwareSegSs
.text:0046A539                 push    edx             ; KTRAP_FRAME->HardwareEsp 3环栈顶
.text:0046A53A                 pushf                   ; KTRAP_FRAME->EFlags
.text:0046A53B
.text:0046A53B loc_46A53B:                             ; CODE XREF: _KiFastCallEntry2+23↑j
.text:0046A53B                 push    2               ; KTRAP_FRAME->SegCs 暂存 2
.text:0046A53D                 add     edx, 8          ; 3环第一个参数
.text:0046A540                 popf                    ; KTRAP_FRAME->EFlags = 2
.text:0046A541                 or      [esp+0Ch+Eflags_IF], 2 ; Eflags IF位置1 允许开启中断
.text:0046A546                 push    1Bh             ; KTRAP_FRAME->SegCs
.text:0046A548                 push    dword ptr ds:0FFDF0304h ; KTRAP_FRAME->Eip 3环Eip 返回地址
.text:0046A54E                 push    0               ; KTRAP_FRAME->ErrCode
.text:0046A550                 push    ebp             ; KTRAP_FRAME->Ebp
.text:0046A551                 push    ebx             ; KTRAP_FRAME->Ebx
.text:0046A552                 push    esi             ; KTRAP_FRAME->Esi
.text:0046A553                 push    edi             ; KTRAP_FRAME->Edi
.text:0046A554                 mov     ebx, large fs:1Ch ; 取出SEH 结构化异常链表
.text:0046A55B                 push    3Bh             ; KTRAP_FRAME->SegFs
.text:0046A55D                 mov     esi, [ebx+124h] ; kpcr->kprcb->_KTHREAD 当前CPU正在执行的线程
.text:0046A563                 push    dword ptr [ebx] ; KTRAP_FRAME->ExceptionList
.text:0046A565                 mov     dword ptr [ebx], 0FFFFFFFFh ; 清除 SEH
.text:0046A56B                 mov     ebp, [esi+18h]  ; 得到当前内核栈底
.text:0046A56E                 push    1               ; KTRAP->FRAME->PreviousPreviousMode CPU先前模式 3环
.text:0046A570                 sub     esp, 48h        ; 调整栈顶 指向KTRAP_FRAME +0x00
.text:0046A573                 sub     ebp, 29Ch       ; 浮点堆栈大小+Ktrap->frame 大小
.text:0046A573                                         ; 让当前内核线程栈底 指向KTRAP_FRAME +0x00
.text:0046A573                                         ; 这样就达到了通过堆栈方式 访问3环的 数据
.text:0046A579                 mov     byte ptr [esi+140h], 1 ; kthread->PreviousMode 设置先前模式 为3环
.text:0046A580                 cmp     ebp, esp        ; 堆栈检查
.text:0046A582                 jnz     short 跳到6号中断门
.text:0046A584                 and     dword ptr [ebp+2Ch], 0 ; KTRAP->FRAME->Dr7 清零
.text:0046A588                 test    byte ptr [esi+2Ch], 0FFh ; kthread->DebugActive 检测有没有被调试
.text:0046A58C                 mov     [esi+134h], ebp ; kthread->TrapFrame 备份陷阱帧
.text:0046A58C                                         ; 陷阱帧:就是TrapFrame结构体
.text:0046A58C                                         ; 用于保存3环的上下文环境
.text:0046A58C                                         ;
.text:0046A58C                                         ; 由于已经备份
.text:0046A58C                                         ; 下面操作不会影响原有的3环上下文环境
.text:0046A592                 jnz     Dr_FastCallDrSave ; 调试状态 设置调试寄存器
.text:0046A598
.text:0046A598 内核权限跳转:                                 ; CODE XREF: Dr_FastCallDrSave+10↑j
.text:0046A598                                         ; Dr_FastCallDrSave+7C↑j
.text:0046A598                 mov     ebx, [ebp+60h]  ; KTRAP_FRAME->Ebp 3环栈底
.text:0046A59B                 mov     edi, [ebp+68h]  ; KTRAP_FRAME->Eip  3环返回地址
.text:0046A59E                 mov     [ebp+0Ch], edx  ; KTRAP_FRAME->DbgArgPointer 3环第一个参数
.text:0046A5A1                 mov     dword ptr [ebp+8], 0BADB0D00h ; KTRAP_FRAME->DbgArgMark
.text:0046A5A8                 mov     [ebp+0], ebx    ; KTRAP_FRAME->DbgEbp 调试相关
.text:0046A5AB                 mov     [ebp+4], edi    ; KTRAP_FRAME->DbgEip 调试相关
.text:0046A5AE                 sti                     ; 开中断
.text:0046A5AF
.text:0046A5AF loc_46A5AF:                             ; CODE XREF: _KiBBTUnexpectedRange+18↑j
.text:0046A5AF                                         ; _KiSystemService+72↑j
.text:0046A5AF                 mov     edi, eax        ; 系统服务号
.text:0046A5B1                 shr     edi, 8
.text:0046A5B4                 and     edi, 30h        ; 0:调用ntkrpa 10:调用Win32k
.text:0046A5B7                 mov     ecx, edi
.text:0046A5B9                 add     edi, [esi+0E0h] ; kthread->ServiceTable 系统服务表基址
.text:0046A5B9                                         ; _KeDescriporServiceTable
.text:0046A5B9                                         ; 0x00 PULONG ServiceTableBase;        // 系统服务表基址
.text:0046A5B9                                         ; 0x04 PULONG ServiceCounterTableBase; // 系统服务表被调用的次数
.text:0046A5B9                                         ; 0x08 ULONG  NumberOfServices;        // 系统服务表函数个数
.text:0046A5B9                                         ; 0x0C PULONG ParamTableBase;          // 系统服务表函数参数大小
.text:0046A5BF                 mov     ebx, eax
.text:0046A5C1                 and     eax, 0FFFh      ; 系统服务号保留低12位
.text:0046A5C6                 cmp     eax, [edi+8]
.text:0046A5C9                 jnb     _KiBBTUnexpectedRange ; 参数检查
.text:0046A5CF                 cmp     ecx, 10h
.text:0046A5D2                 jnz     short loc_46A5EF ; 调用ntkrnlpa.exe
.text:0046A5D4                 mov     ecx, large fs:18h ; 取 当前的_kpcr
.text:0046A5DB                 xor     ebx, ebx
.text:0046A5DD
.text:0046A5DD loc_46A5DD:                             ; DATA XREF: _KiTrap0E+117↓o
.text:0046A5DD                 or      ebx, [ecx+0F70h] ; 检测.... 不清楚写的是什么
.text:0046A5E3                 jz      short loc_46A5EF ; 调用ntkrnlpa.exe
.text:0046A5E5                 push    edx             ; 三环第一个参数
.text:0046A5E6                 push    eax             ; 系统服务号
.text:0046A5E7                 call    ds:_KeGdiFlushUserBatch ; 跳转win32k.sys
.text:0046A5ED                 pop     eax
.text:0046A5EE                 pop     edx
.text:0046A5EF
.text:0046A5EF loc_46A5EF:                             ; CODE XREF: _KiFastCallEntry+B2↑j
.text:0046A5EF                                         ; _KiFastCallEntry+C3↑j
.text:0046A5EF                 inc     large dword ptr fs:638h ; _KPRCB->KeSystemCalls 加1 我猜是系统服务表调用次数+1
.text:0046A5F6                 mov     esi, edx        ; 3环第一个参数
.text:0046A5F8                 mov     ebx, [edi+0Ch]  ; ServiceTable->ParamTableBase
.text:0046A5FB                 xor     ecx, ecx
.text:0046A5FD                 mov     cl, [eax+ebx]   ; 参数个数 (字节)
.text:0046A600                 mov     edi, [edi]      ; ServiceTable
.text:0046A602                 mov     ebx, [edi+eax*4] ; 系统服务函数
.text:0046A605                 sub     esp, ecx        ; 分配参数空间
.text:0046A607                 shr     ecx, 2          ; 计算循环次数
.text:0046A60A                 mov     edi, esp
.text:0046A60C                 cmp     esi, ds:_MmUserProbeAddress ; 3环参数检查
.text:0046A612                 jnb     loc_46A7C0      ; 非法跳转
.text:0046A618
.text:0046A618 loc_46A618:                             ; CODE XREF: _KiFastCallEntry+2A4↓j
.text:0046A618                                         ; DATA XREF: _KiTrap0E+10D↓o
.text:0046A618                 rep movsd               ; rep movs dword ptr es:[edi],dword ptr [esi]
.text:0046A61A                 call    ebx             ; 调用系统服务
.text:0046A61C
.text:0046A61C loc_46A61C:                             ; CODE XREF: _KiFastCallEntry+2AF↓j
.text:0046A61C                                         ; DATA XREF: _KiTrap0E+12D↓o ...
.text:0046A61C                 mov     esp, ebp
.text:0046A61E
.text:0046A61E loc_46A61E:                             ; CODE XREF: _KiBBTUnexpectedRange+38↑j
.text:0046A61E                                         ; _KiBBTUnexpectedRange+43↑j
.text:0046A61E                 mov     ecx, large fs:124h ; 当前线程
.text:0046A625                 mov     edx, [ebp+3Ch]  ; KTRAP_FRAME->Edx
.text:0046A628                 mov     [ecx+134h], edx ; 指向原有的 陷阱帧 准备返回3环
.text:0046A628 _KiFastCallEntry endp

_KiServiceExit:
[Asm] 纯文本查看 复制代码
.text:0046A62E ; 系统调用返回 必经之路
.text:0046A62E
.text:0046A62E _KiServiceExit  proc near               ; CODE XREF: KiCallUserMode(x,x)+EC↑j
.text:0046A62E                                         ; _KiSetLowWaitHighThread+80↓j ...
.text:0046A62E
.text:0046A62E tempCs          = dword ptr  10h
.text:0046A62E tempEsp         = dword ptr  14h
.text:0046A62E _Eax            = dword ptr  44h
.text:0046A62E PreviousMode    = dword ptr  48h
.text:0046A62E ExceptionList   = dword ptr  4Ch
.text:0046A62E ErrCode         = dword ptr  64h
.text:0046A62E _Eip            = dword ptr  68h
.text:0046A62E SegCs           = dword ptr  6Ch
.text:0046A62E EFlags          = dword ptr  70h
.text:0046A62E
.text:0046A62E ; FUNCTION CHUNK AT .text:0046A738 SIZE 00000088 BYTES
.text:0046A62E
.text:0046A62E                 cli                     ; 关闭中断
.text:0046A62F                 test    dword ptr [ebp+70h], 20000h ; _KTRAP_FRAME->Eflags 检查CPU模式
.text:0046A636                 jnz     short loc_46A63E ; 虚拟8086模式
.text:0046A638                 test    byte ptr [ebp+6Ch], 1 ; 检测CS CPL检查
.text:0046A63C                 jz      short 内核层处理     ; 内核
.text:0046A63E
.text:0046A63E loc_46A63E:                             ; CODE XREF: _KiServiceExit+8↑j
.text:0046A63E                                         ; _KiServiceExit+64↓j
.text:0046A63E                 mov     ebx, large fs:124h ; 当前运行的 kthread
.text:0046A645                 mov     byte ptr [ebx+2Eh], 0 ; kthread->Alerted 该线程是否可以被唤醒 0:NO
.text:0046A649                 cmp     byte ptr [ebx+4Ah], 0 ; _KAPC_STATE->UserApcPending 判断是否有 用户APC要执行
.text:0046A64D                 jz      short 内核层处理     ; 没有要执行的用户APC 跳转
.text:0046A64F                 mov     ebx, ebp        ; _KTRAP_FRAME
.text:0046A651                 mov     [ebx+44h], eax  ; _KTRAP_FRAME->Eax
.text:0046A654                 mov     dword ptr [ebx+50h], 3Bh ; _KTRAP_FRAME->FS
.text:0046A65B                 mov     dword ptr [ebx+38h], 23h ; _KTRAP_FRAME->DS
.text:0046A662                 mov     dword ptr [ebx+34h], 23h ; _KTRAP_FRAME->ES
.text:0046A669                 mov     dword ptr [ebx+30h], 0 ; _KTRAP_FRAME->GS
.text:0046A670                 mov     ecx, 1          ; APC_LEVEL
.text:0046A675                 call    ds:__imp_@KfRaiseIrql@4 ; 提升中断请求级别
.text:0046A67B                 push    eax             ; 源 中断级别
.text:0046A67C                 sti                     ; 开启中断
.text:0046A67D                 push    ebx             ; 传递 陷阱帧
.text:0046A67E                 push    0
.text:0046A680                 push    1               ; 0:处理内核APC 1:内核 用户都处理
.text:0046A682                 call    _KiDeliverApc@12 ; 分发APC关键函数
.text:0046A682                                         ; 线程切换调用了APC分发函数 系统调用返回调用了APC分发函数
.text:0046A687                 pop     ecx             ; NewIrql
.text:0046A688                 call    ds:__imp_@KfLowerIrql@4 ; 降低中断请求级别
.text:0046A68E                 mov     eax, [ebx+44h]
.text:0046A691                 cli                     ; 关闭中断
.text:0046A692                 jmp     short loc_46A63E ; 判断有没有下一个APC
.text:0046A694 ; ---------------------------------------------------------------------------
.text:0046A694
.text:0046A694 内核层处理:                                  ; CODE XREF: _KiServiceExit+E↑j
.text:0046A694                                         ; _KiServiceExit+1F↑j
.text:0046A694                 mov     edx, [esp+ExceptionList]
.text:0046A698                 mov     ebx, large fs:50h ; kpcr->DebugActive 调试端口 用于保存调试对象 _DEBUG_OBJECT
.text:0046A69F                 mov     large fs:0, edx ; 构造SEH
.text:0046A6A6                 mov     ecx, [esp+PreviousMode]
.text:0046A6AA                 mov     esi, large fs:124h ; kthread 当前执行线程
.text:0046A6B1                 mov     [esi+140h], cl  ; 设置先前模式
.text:0046A6B7                 test    ebx, 0FFh       ; 判断当前线程有没有被调试
.text:0046A6BD                 jnz     short 调试状态      ; 调试状态 跳转
.text:0046A6BF
.text:0046A6BF loc_46A6BF:                             ; CODE XREF: _KiServiceExit+11A↓j
.text:0046A6BF                                         ; _KiServiceExit+149↓j
.text:0046A6BF                 test    [esp+EFlags], 20000h ; ‭00100000000000000000‬
.text:0046A6BF                                         ; 判断 VM位 虚拟8086模式 [Virtual-8086 mode flag]
.text:0046A6BF                                         ; 0:保护模式 1:虚拟8086模式
.text:0046A6C7                 jnz     loc_46AFD8      ; 虚拟8086模式返回
.text:0046A6CD                 test    word ptr [esp+SegCs], 0FFF8h ; 不清楚在 判断什么
.text:0046A6D4                 jz      和中断返回有关         ; 通过 iret返回
.text:0046A6DA                 cmp     word ptr [esp+SegCs], 1Bh ; CPL 权限检查
.text:0046A6E0                 bt      word ptr [esp+SegCs], 0 ; 取cs 第0位 给 CF
.text:0046A6E7                 cmc                     ; CF取反
.text:0046A6E8                 ja      主要恢复了段寄存器       ; 3环权限 就跳转
.text:0046A6EE                 cmp     word ptr [ebp+6Ch], 8 ; 判断 _KTRAP_FRAME->SegCs CPL权限检查
.text:0046A6F3                 jz      short 内核层调用返回   ; 0环权限 跳转
.text:0046A6F5
.text:0046A6F5 loc_46A6F5:                             ; CODE XREF: _KiServiceExit+15B↓j
.text:0046A6F5                 lea     esp, [ebp+50h]  ; _KTRAP_FRAME->SegFs
.text:0046A6F8                 pop     fs              ; 恢复3环的 FS
.text:0046A6FA                 assume fs:nothing
.text:0046A6FA
.text:0046A6FA 内核层调用返回:                                ; CODE XREF: _KiServiceExit+C5↑j
.text:0046A6FA                 lea     esp, [ebp+54h]  ; _KTRAP_FRAME->Edi
.text:0046A6FD                 pop     edi
.text:0046A6FE                 pop     esi
.text:0046A6FF                 pop     ebx
.text:0046A700                 pop     ebp
.text:0046A701                 cmp     word ptr [esp-60h+_Eip], 80h
.text:0046A708                 ja      loc_46AFF4
.text:0046A70E                 add     esp, 4
.text:0046A711                 test    [esp-64h+_Eip], 1 ; 这里下面少了一句 判断是不是3环 是就跳转 _KiSystemCallExit2 回到3环
.text:0046A711 _KiServiceExit  endp ; sp-analysis failed
.text:0046A711
.text:0046A711 ; ---------------------------------------------------------------------------
.text:0046A719 _KiSystemCallExitBranch db 75h
.text:0046A71A byte_46A71A     db 5                    ; DATA XREF: KiDisableFastSyscallReturn()+9↑w
.text:0046A71A                                         ; KiEnableFastSyscallReturn():loc_427854↑r ...
.text:0046A71B ; ---------------------------------------------------------------------------
.text:0046A71B                 pop     edx             ; _KTRAP_FRAME->Eip
.text:0046A71C                 pop     ecx             ; _KTRAP_FRAME->SegCs
.text:0046A71D                 popf                    ; _KTRAP_FRAME->EFlags
.text:0046A71E                 jmp     edx             ; 回到0环
.text:0046A720 ; ---------------------------------------------------------------------------
.text:0046A720 ; START OF FUNCTION CHUNK FOR _KiSystemCallExit2
.text:0046A720
.text:0046A720 _KiSystemCallExit:                      ; CODE XREF: _KiSystemCallExit2+5↓j
.text:0046A720                                         ; DATA XREF: KiRestoreFastSyscallReturnState()+1B↑o
.text:0046A720                 iret
.text:0046A720 ; END OF FUNCTION CHUNK FOR _KiSystemCallExit2
.text:0046A721
.text:0046A721 ; =============== S U B R O U T I N E =======================================
.text:0046A721
.text:0046A721 ; 回到3环
.text:0046A721
.text:0046A721 _KiSystemCallExit2 proc near            ; DATA XREF: KiRestoreFastSyscallReturnState()+16↑o
.text:0046A721
.text:0046A721 Eflags_IF       = byte ptr  9
.text:0046A721
.text:0046A721 ; FUNCTION CHUNK AT .text:0046A720 SIZE 00000001 BYTES
.text:0046A721
.text:0046A721                 test    [esp+Eflags_IF], 1 ; 当前Esp指向 _KTRAP_FRAME->ErrCode
.text:0046A721                                         ; +9 指向 EFlags 第二个字节
.text:0046A726                 jnz     short _KiSystemCallExit ; 中断的形式进入0环的 直接通过 iretd 返回3环
.text:0046A728                 pop     edx             ; _KTRAP_FRAME->Eip
.text:0046A729                 add     esp, 4          ; _KTRAP_FRAME->SegCs
.text:0046A72C                 and     [esp-8+Eflags_IF], 0FDh ; 设置 Eflags寄存器
.text:0046A731                 popf                    ; _KTRAP_FRAME->EFlags
.text:0046A732                 pop     ecx             ; _KTRAP_FRAME->HardwareEsp
.text:0046A733                 sti                     ; 开启中断
.text:0046A734                 sysexit                 ; 返回3环
.text:0046A736                 iret


总结:
用户层内核层返回都走的是:_KiServiceExit
但是系统调用 用户层走的是:_KiFastCallEntry PAE模式下 内核层走的是:_KiSystemService
然后直接跳到系统调用那一段了 因为两种方式调用的细节不一样
用户层是通过硬件方式 快速调用 直接设置寄存器
但是内核层不能这样做(因为每次调用函数 都要传递 Eflags Cs Eip 3个参数 _KTRAP_FRAME+0x68 - +0x70的值 每次都需要动态变化)
_KiFastCallEntry Esp指向_KTRAP_FRAME+0x+0x078
_KiSystemService Esp指向_KTRAP_FRAME+0x64

所以要通过_KiSystemService 设置堆栈
本质上都是通过 _KTRAP_FRAME结构体构造堆栈的
I{M8MSV{F%4IF~J}NK4K1SI.png
C3W{}{BUWV){J2RT_PUJ]8Q.png

代码比较乱 有很多错误的地方 讲究看下吧

免费评分

参与人数 2威望 +1 吾爱币 +7 热心值 +2 收起 理由
苏紫方璇 + 1 + 6 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
红颜世家、 + 1 + 1 已经处理,感谢您对吾爱破解论坛的支持!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

yiyedd 发表于 2020-3-10 09:10
一脸懵逼的进来,一脸懵逼的出去
 楼主| 古月不傲 发表于 2020-3-15 00:50
本帖最后由 古月不傲 于 2020-3-15 00:57 编辑

源码清晰多了

KiServiceExit

KiServiceExit
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-17 02:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表