系统调用和返回
本帖最后由 古月不傲 于 2020-3-10 03:03 编辑_KiFastCallEntry:
.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, ; 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 , 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, ; kpcr->kprcb->_KTHREAD 当前CPU正在执行的线程
.text:0046A563 push dword ptr ; KTRAP_FRAME->ExceptionList
.text:0046A565 mov dword ptr , 0FFFFFFFFh ; 清除 SEH
.text:0046A56B mov ebp, ; 得到当前内核栈底
.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 , 1 ; kthread->PreviousMode 设置先前模式 为3环
.text:0046A580 cmp ebp, esp ; 堆栈检查
.text:0046A582 jnz short 跳到6号中断门
.text:0046A584 and dword ptr , 0 ; KTRAP->FRAME->Dr7 清零
.text:0046A588 test byte ptr , 0FFh ; kthread->DebugActive 检测有没有被调试
.text:0046A58C mov , 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, ; KTRAP_FRAME->Ebp 3环栈底
.text:0046A59B mov edi, ; KTRAP_FRAME->Eip3环返回地址
.text:0046A59E mov , edx; KTRAP_FRAME->DbgArgPointer 3环第一个参数
.text:0046A5A1 mov dword ptr , 0BADB0D00h ; KTRAP_FRAME->DbgArgMark
.text:0046A5A8 mov , ebx ; KTRAP_FRAME->DbgEbp 调试相关
.text:0046A5AB mov , 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, ; kthread->ServiceTable 系统服务表基址
.text:0046A5B9 ; _KeDescriporServiceTable
.text:0046A5B9 ; 0x00 PULONG ServiceTableBase; // 系统服务表基址
.text:0046A5B9 ; 0x04 PULONG ServiceCounterTableBase; // 系统服务表被调用的次数
.text:0046A5B9 ; 0x08 ULONGNumberOfServices; // 系统服务表函数个数
.text:0046A5B9 ; 0x0C PULONG ParamTableBase; // 系统服务表函数参数大小
.text:0046A5BF mov ebx, eax
.text:0046A5C1 and eax, 0FFFh ; 系统服务号保留低12位
.text:0046A5C6 cmp eax,
.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, ; 检测.... 不清楚写的是什么
.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, ; ServiceTable->ParamTableBase
.text:0046A5FB xor ecx, ecx
.text:0046A5FD mov cl, ; 参数个数 (字节)
.text:0046A600 mov edi, ; ServiceTable
.text:0046A602 mov ebx, ; 系统服务函数
.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:,dword ptr
.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, ; KTRAP_FRAME->Edx
.text:0046A628 mov , edx ; 指向原有的 陷阱帧 准备返回3环
.text:0046A628 _KiFastCallEntry endp
_KiServiceExit:
.text:0046A62E ; 系统调用返回 必经之路
.text:0046A62E
.text:0046A62E _KiServiceExitproc near ; CODE XREF: KiCallUserMode(x,x)+EC↑j
.text:0046A62E ; _KiSetLowWaitHighThread+80↓j ...
.text:0046A62E
.text:0046A62E tempCs = dword ptr10h
.text:0046A62E tempEsp = dword ptr14h
.text:0046A62E _Eax = dword ptr44h
.text:0046A62E PreviousMode = dword ptr48h
.text:0046A62E ExceptionList = dword ptr4Ch
.text:0046A62E ErrCode = dword ptr64h
.text:0046A62E _Eip = dword ptr68h
.text:0046A62E SegCs = dword ptr6Ch
.text:0046A62E EFlags = dword ptr70h
.text:0046A62E
.text:0046A62E ; FUNCTION CHUNK AT .text:0046A738 SIZE 00000088 BYTES
.text:0046A62E
.text:0046A62E cli ; 关闭中断
.text:0046A62F test dword ptr , 20000h ; _KTRAP_FRAME->Eflags 检查CPU模式
.text:0046A636 jnz short loc_46A63E ; 虚拟8086模式
.text:0046A638 test byte ptr , 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 , 0 ; kthread->Alerted 该线程是否可以被唤醒 0:NO
.text:0046A649 cmp byte ptr , 0 ; _KAPC_STATE->UserApcPending 判断是否有 用户APC要执行
.text:0046A64D jz short 内核层处理 ; 没有要执行的用户APC 跳转
.text:0046A64F mov ebx, ebp ; _KTRAP_FRAME
.text:0046A651 mov , eax; _KTRAP_FRAME->Eax
.text:0046A654 mov dword ptr , 3Bh ; _KTRAP_FRAME->FS
.text:0046A65B mov dword ptr , 23h ; _KTRAP_FRAME->DS
.text:0046A662 mov dword ptr , 23h ; _KTRAP_FRAME->ES
.text:0046A669 mov dword ptr , 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,
.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,
.text:0046A698 mov ebx, large fs:50h ; kpcr->DebugActive 调试端口 用于保存调试对象 _DEBUG_OBJECT
.text:0046A69F mov large fs:0, edx ; 构造SEH
.text:0046A6A6 mov ecx,
.text:0046A6AA mov esi, large fs:124h ; kthread 当前执行线程
.text:0046A6B1 mov , 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 , 20000h ; 00100000000000000000
.text:0046A6BF ; 判断 VM位 虚拟8086模式
.text:0046A6BF ; 0:保护模式 1:虚拟8086模式
.text:0046A6C7 jnz loc_46AFD8 ; 虚拟8086模式返回
.text:0046A6CD test word ptr , 0FFF8h ; 不清楚在 判断什么
.text:0046A6D4 jz 和中断返回有关 ; 通过 iret返回
.text:0046A6DA cmp word ptr , 1Bh ; CPL 权限检查
.text:0046A6E0 bt word ptr , 0 ; 取cs 第0位 给 CF
.text:0046A6E7 cmc ; CF取反
.text:0046A6E8 ja 主要恢复了段寄存器 ; 3环权限 就跳转
.text:0046A6EE cmp word ptr , 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, ; _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, ; _KTRAP_FRAME->Edi
.text:0046A6FD pop edi
.text:0046A6FE pop esi
.text:0046A6FF pop ebx
.text:0046A700 pop ebp
.text:0046A701 cmp word ptr , 80h
.text:0046A708 ja loc_46AFF4
.text:0046A70E add esp, 4
.text:0046A711 test , 1 ; 这里下面少了一句 判断是不是3环 是就跳转 _KiSystemCallExit2 回到3环
.text:0046A711 _KiServiceExitendp ; 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 ptr9
.text:0046A721
.text:0046A721 ; FUNCTION CHUNK AT .text:0046A720 SIZE 00000001 BYTES
.text:0046A721
.text:0046A721 test , 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 , 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结构体构造堆栈的
代码比较乱 有很多错误的地方 讲究看下吧 一脸懵逼的进来,一脸懵逼的出去 本帖最后由 古月不傲 于 2020-3-15 00:57 编辑
源码清晰多了
页:
[1]