跟踪 Ring3 - Ring0 的运行流程
Posted yfceshi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了跟踪 Ring3 - Ring0 的运行流程相关的知识,希望对你有一定的参考价值。
理论知识
SYSENTER
指令是在 Inter Pentium(R) Ⅱ 处理器上作为“高速系统调用”功能的一部分被首次引用的。
SYSENTER 指令进行过专门的优化,能够以最佳性能由 Ring3 层切换到 Ring0 层。
微软首次引用 SYSENTER 指令是在 Windows 2000 的系统上,再次之前微软的系统是通过自陷指令 int 0x2E 进入 Ring0 层的系统空间的。
在 Windows 2000 及以后的系统中,假设想要从 Ring3 层进入 Ring0 层,系统首先会将要调用的系统调用号(SSDT调用号)放入 EAX 中。然后将当前栈指针 ESP 的内容放入 EDX 中后运行SYSENTER 指令;
SYSENTER 被运行后会将控制权传递给特殊模块寄存器 IA32_SYSENTER_EIP 所指向的函数中,完毕兴许操作。
特殊模块寄存器组(Model-Specific registers。MSRs)
是 CPU 中负责运行一些特定的、与计算逻辑相关性不大的、且操作较复杂的功能的一组寄存器。
特殊模块寄存器可通过使用 rdmsr/wrmsr 指令读写其位于 MSRs 指定偏移处的某个寄存器的信息。
MSRs 共包括上百种具有不同功能的寄存器。每一个寄存器所在的偏移与所占用的空间都不尽同样。眼下 MSRs 的可用偏移范围是 0x00000000 ~ 0xC0000103。
与 SYSENTER 相配合的 MSRs 共同拥有3个,其具体信息例如以下所看到的:
名称 | 偏移 | 说明 |
---|---|---|
SYSENTER_CS_MSR | 0x174 | 切换到 Ring0 层之后的 CS 选择器 |
SYSENTER_ESP_MSR | 0x175 | 切换到 Ring0 层之后的 ESP |
SYSENTER_EIP_MSR | 0x176 | 切换到 Ring0 层之后的 EIP |
SYSENTER 被运行时,这 3 个寄存器会运行以下操作配合.
SYSENTER 完毕的切换操作:
- 装载 SYSENTER_CS_MSR 到 CS 寄存器,设置目标代码段。
- 装载 SYSENTER_EIP_MSR 到 EIP 寄存器。设置目标指令;
- 将 SYSENTER_CS_MSR + 8 装载到 SS 寄存器,设置栈段;
- 装载 SYSENTER_ESP_MSR 到 ESP 寄存器,设置栈帧;
- 切换 Ring0。
- 清除 EFLAGS 的 VM 标志;(虚拟8086方式标志)
- 运行位于 EIP 处的 RING0 例程。
实验開始~
说了这么多理论,如今来实践一下咯:( 以 CreateFileW 函数为例 )
在虚拟机中运行 notepad.exe ,用 windbg 使断下
搜索 notepad.exe 进程:
2: kd> !process 0 0 notepad.exe
PROCESS 87b697c0 SessionId: 1 Cid: 0d10 Peb: 7ffdf000 ParentCid: 0474
DirBase: 6612b000 ObjectTable: 931868f0 HandleCount: 61.
Image: notepad.exe
我们得到了 notepad.exe 的进程首地址,如今转到他的进程空间:
2: kd> .process /i /p 87b697c0
You need to continue execution (press ‘g‘ <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
当中两个參数的含义:(注:此中文解释来自 http://www.dbgtech.net/windbghelp/。站长翻译了windbg的帮助文档,英语文盲的福音)
/i
(Windows XP 和之后的系统;仅活动调试;非本地内核调试) 指定要侵入(invasively)调试Process 。这样的调试意味着目标机上的操作系统实际上将指定的进程激活。(假设不带该參数。.process 命令改变调试器的输出,可是不会作用于目标机本身。
)假设使用了 /i,必须使用g (Go)命令来运行目标。
数秒之后,目标会再次中断到调试器中。而且指定的 Process 被激活并用作当前进程上下文。
/p
假设使用了/p 而且Process 非0。在訪问之前将该进程全部页表入口(PTE)转换成物理地址。这样的转换可能造成速度变慢,由于调试器必须找到该进程使用的全部内存的物理地址。调试器也须要通过调试电缆传输大量数据。
(该行为和.cache forcedecodeuser一样。
)
假设包括/p 而且Process为0或者省略,则禁用这样的转换。(这样的行为和.cache noforcedecodeptes一样。)
上面提示我们说要运行一下才干切换上下文,那么 g 一下
2: kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
8406dd00 cc int 3
如今我们就断在了 notepad.exe 的进程里
如今又一次载入一下符号表
2: kd> .reload /f /user
Loading User Symbols
.
DBGHELP: notepad - public symbols
f:\program files\nt_dbg_symbols\notepad.pdb\E325F5195AE94FAEB58D25C9DF8C0CFD2\notepad.pdb
.
DBGHELP: f:\program files\nt_dbg_symbols\ntdll.dll\4CE7B96E13c000\ntdll.dll - OK
DBGENG: Partial symbol load found image f:\program files\nt_dbg_symbols\ntdll.dll\4CE7B96E13c000\ntdll.dll.
DBGHELP: ntdll - public symbols
f:\program files\nt_dbg_symbols\ntdll.pdb\120028FA453F4CD5A6A404EC37396A582\ntdll.pdb
.
DBGHELP: f:\program files\nt_dbg_symbols\kernel32.dll\4CE7B8EFd4000\kernel32.dll - OK
DBGENG: Partial symbol load found image f:\program files\nt_dbg_symbols\kernel32.dll\4CE7B8EFd4000\kernel32.dll.
DBGHELP: kernel32 - public symbols
f:\program files\nt_dbg_symbols\kernel32.pdb\D4AC3906D49D487B9F69F9326A7D206A2\kernel32.pdb
.
DBGHELP: f:\program files\nt_dbg_symbols\KERNELBASE.dll\4CE7B8F04a000\KERNELBASE.dll - OK
DBGENG: Partial symbol load found image f:\program files\nt_dbg_symbols\KERNELBASE.dll\4CE7B8F04a000\KERNELBASE.dll.
DBGHELP: KERNELBASE - public symbols
f:\program files\nt_dbg_symbols\kernelbase.pdb\F50B25D282504188B73063D653B7D27E2\kernelbase.pdb
.
DBGHELP: f:\program files\nt_dbg_symbols\ADVAPI32.dll\4CE7B706a0000\ADVAPI32.dll - OK
DBGENG: Partial symbol load found image f:\program files\nt_dbg_symbols\ADVAPI32.dll\4CE7B706a0000\ADVAPI32.dll.
DBGHELP: ADVAPI32 - public symbols
f:\program files\nt_dbg_symbols\advapi32.pdb\3F32049F550C42B09CF114A1FB8A97E92\advapi32.pdb
.
DBGHELP: msvcrt - public symbols
f:\program files\nt_dbg_symbols\msvcrt.pdb\6EC79267530C45188F2A816AD59DBBF92\msvcrt.pdb
.
DBGHELP: sechost - public symbols
f:\program files\nt_dbg_symbols\sechost.pdb\7AF14D02D41E4CD6942745FE0E6372B11\sechost.pdb
.
DBGHELP: RPCRT4 - public symbols
f:\program files\nt_dbg_symbols\rpcrt4.pdb\189CC56E2D4A43DA8A269E088721F13D2\rpcrt4.pdb
.
DBGHELP: GDI32 - public symbols
f:\program files\nt_dbg_symbols\gdi32.pdb\96948E513A8747C58A699B8A7009DCB22\gdi32.pdb
.
DBGHELP: f:\program files\nt_dbg_symbols\USER32.dll\4CE7BA26c9000\USER32.dll - OK
DBGENG: Partial symbol load found image f:\program files\nt_dbg_symbols\USER32.dll\4CE7BA26c9000\USER32.dll.
DBGHELP: USER32 - public symbols
f:\program files\nt_dbg_symbols\user32.pdb\DD74D86F12624845A42A6A5BAAB4D7A82\user32.pdb
.
DBGHELP: LPK - public symbols
f:\program files\nt_dbg_symbols\lpk.pdb\B99319FE4427418F9EB5432B9F6A13412\lpk.pdb
.
DBGHELP: USP10 - public symbols
f:\program files\nt_dbg_symbols\usp10.pdb\F49786E2C7C54EA99E7C37120CDAEB9C1\usp10.pdb
.
DBGHELP: f:\program files\nt_dbg_symbols\COMDLG32.dll\4CE7B82D7b000\COMDLG32.dll - OK
DBGENG: Partial symbol load found image f:\program files\nt_dbg_symbols\COMDLG32.dll\4CE7B82D7b000\COMDLG32.dll.
DBGHELP: COMDLG32 - public symbols
f:\program files\nt_dbg_symbols\comdlg32.pdb\96BC483CDFF04D1AAFE462F093B954EC2\comdlg32.pdb
.
DBGHELP: SHLWAPI - public symbols
f:\program files\nt_dbg_symbols\shlwapi.pdb\E128B1CEE2EB438C8646E6967118F33E2\shlwapi.pdb
.
DBGHELP: COMCTL32 - public symbols
f:\program files\nt_dbg_symbols\comctl32.pdb\B4CE90AAB95E4B89A22A7711DFD7E6EF2\comctl32.pdb
.
DBGHELP: f:\program files\nt_dbg_symbols\SHELL32.dll\4CE7B9DEc4a000\SHELL32.dll - OK
DBGENG: Partial symbol load found image f:\program files\nt_dbg_symbols\SHELL32.dll\4CE7B9DEc4a000\SHELL32.dll.
DBGHELP: SHELL32 - public symbols
f:\program files\nt_dbg_symbols\shell32.pdb\4555A5FB02FA4E49B65A25616CD97A6B2\shell32.pdb
.
DBGHELP: f:\program files\nt_dbg_symbols\WINSPOOL.DRV\4CE7BA4B51000\WINSPOOL.DRV - OK
DBGENG: Partial symbol load found image f:\program files\nt_dbg_symbols\WINSPOOL.DRV\4CE7BA4B51000\WINSPOOL.DRV.
DBGHELP: WINSPOOL - public symbols
f:\program files\nt_dbg_symbols\winspool.pdb\B165BBE7CD8C4F39BE373C0D9DFCD77B2\winspool.pdb
.
DBGHELP: f:\program files\nt_dbg_symbols\ole32.dll\4CE7B96F15c000\ole32.dll - OK
DBGENG: Partial symbol load found image f:\program files\nt_dbg_symbols\ole32.dll\4CE7B96F15c000\ole32.dll.
DBGHELP: ole32 - public symbols
f:\program files\nt_dbg_symbols\ole32.pdb\5061F11A9A57433595EA5EA75A156F4B2\ole32.pdb
.
DBGHELP: f:\program files\nt_dbg_symbols\OLEAUT32.dll\4CE7B9728f000\OLEAUT32.dll - OK
DBGENG: Partial symbol load found image f:\program files\nt_dbg_symbols\OLEAUT32.dll\4CE7B9728f000\OLEAUT32.dll.
DBGHELP: OLEAUT32 - public symbols
f:\program files\nt_dbg_symbols\oleaut32.pdb\312BF231E76A450ABF027EBFB52FA2162\oleaut32.pdb
.
DBGHELP: VERSION - public symbols
f:\program files\nt_dbg_symbols\version.pdb\52234E5C7EC44646B62D56357B2C94872\version.pdb
.
DBGHELP: IMM32 - public symbols
f:\program files\nt_dbg_symbols\imm32.pdb\91A0004474E24AA89F185029E31144892\imm32.pdb
.
DBGHELP: MSCTF - public symbols
f:\program files\nt_dbg_symbols\msctf.pdb\173DAEF86B2548DBA6134EB74C4D2F232\msctf.pdb
.
DBGHELP: CRYPTBASE - public symbols
f:\program files\nt_dbg_symbols\cryptbase.pdb\E62FEAE559EE4CD995614215B01AC2102\cryptbase.pdb
.
DBGHELP: uxtheme - public symbols
f:\program files\nt_dbg_symbols\UxTheme.pdb\5BECAB35E7714835A6BF3DADD891BB3A2\UxTheme.pdb
.
DBGHELP: dwmapi - public symbols
f:\program files\nt_dbg_symbols\dwmapi.pdb\D8D91B3F339A4FDC960FC7121D146DF42\dwmapi.pdb
当中參数含义:
/f(马上载入)
Forces the debugger to immediately load the symbols. This parameter overrides lazy symbol loading. For more information, see the following
Remarks section.
/user (仅仅载入用户符号)
Reloads user symbols only. (You can use this option only during kernel-mode debugging.)
我之前下载了一个完整版的。全部基本都是本地载入。
假设没有而且网速又慢。。。
能够等到 kernel 等 pdb 下载过后按Ctrl + C终止。不然就要等到天荒地老。
。。
。
。
如今保证了符号已经没问题,就能够开心的继续咯。直到如今我们才真正開始…….
由于我们要观察 CreateFileW ,我们就在这个函数下断点
2: kd> bp kernel32!CreateFileW
为了放心。看一下断点列表:
2: kd> bl
0 e 759ecca9 0001 (0001) kernel32!CreateFileW
我们如今继续运行:
2: kd> g
Breakpoint 0 hit
kernel32!CreateFileW:
001b:759ecca9 ff25e0199a75 jmp dword ptr [kernel32!_imp__CreateFileW (759a19e0)]
进程断在了这里。
单步一次进入jmp的函数内部:
3: kd> t
KERNELBASE!CreateFileW:
001b:7574a850 8bff mov edi,edi
以函数地址開始反汇编100条:
3: kd> u KERNELBASE!CreateFileW l100
KERNELBASE!CreateFileW:
7574a850 8bff mov edi,edi
7574a852 55 push ebp
7574a853 8bec mov ebp,esp
7574a855 8b4518 mov eax,dword ptr [ebp+18h]
7574a858 83ec64 sub esp,64h
7574a85b 48 dec eax
7574a85c 0f8499e5ffff je KERNELBASE!CreateFileW+0x57 (75748dfb)
7574a862 48 dec eax
7574a863 0f8468360000 je KERNELBASE!CreateFileW+0x4e (7574ded1)
7574a869 48 dec eax
7574a86a 0f8579360000 jne KERNELBASE!CreateFileW+0x14 (7574dee9)
7574a870 c745fc01000000 mov dword ptr [ebp-4],1
7574a877 53 push ebx
7574a878 56 push esi
7574a879 8b7508 mov esi,dword ptr [ebp+8]
7574a87c 56 push esi
7574a87d 8d45d8 lea eax,[ebp-28h]
7574a880 50 push eax
7574a881 ff15fc117475 call dword ptr [KERNELBASE!_imp__RtlInitUnicodeStringEx (757411fc)]
7574a887 33db xor ebx,ebx
7574a889 3bc3 cmp eax,ebx
7574a88b 0f8ce46a0000 jl KERNELBASE!CreateFileW+0xc0 (75751375)
7574a891 33c0 xor eax,eax
7574a893 40 inc eax
7574a894 663945d8 cmp word ptr [ebp-28h],ax
7574a898 7611 jbe KERNELBASE!CreateFileW+0x8e (7574a8ab)
7574a89a 0fb74dd8 movzx ecx,word ptr [ebp-28h]
7574a89e d1e9 shr ecx,1
7574a8a0 66837c4efe5c cmp word ptr [esi+ecx*2-2],5Ch
7574a8a6 8945ec mov dword ptr [ebp-14h],eax
7574a8a9 7403 je KERNELBASE!CreateFileW+0x91 (7574a8ae)
7574a8ab 895dec mov dword ptr [ebp-14h],ebx
7574a8ae 8d45b4 lea eax,[ebp-4Ch]
7574a8b1 50 push eax
7574a8b2 53 push ebx
7574a8b3 8d45d8 lea eax,[ebp-28h]
7574a8b6 50 push eax
7574a8b7 56 push esi
7574a8b8 895d08 mov dword ptr [ebp+8],ebx
7574a8bb ff15fc137475 call dword ptr [KERNELBASE!_imp__RtlDosPathNameToRelativeNtPathName_U_WithStatus (757413fc)]
7574a8c1 3bc3 cmp eax,ebx
7574a8c3 0f8c73750100 jl KERNELBASE!CreateFileW+0xa8 (75761e3c)
7574a8c9 8b45dc mov eax,dword ptr [ebp-24h]
7574a8cc 8945f0 mov dword ptr [ebp-10h],eax
7574a8cf 8b45b4 mov eax,dword ptr [ebp-4Ch]
7574a8d2 663bc3 cmp ax,bx
7574a8d5 0f851c390000 jne KERNELBASE!CreateFileW+0xdc (7574e1f7)
7574a8db 895dbc mov dword ptr [ebp-44h],ebx
7574a8de 8b45bc mov eax,dword ptr [ebp-44h]
7574a8e1 8b551c mov edx,dword ptr [ebp+1Ch]
7574a8e4 8945a0 mov dword ptr [ebp-60h],eax
7574a8e7 8d45d8 lea eax,[ebp-28h]
7574a8ea 8bca mov ecx,edx
7574a8ec c1e912 shr ecx,12h
7574a8ef 8945a4 mov dword ptr [ebp-5Ch],eax
7574a8f2 8bc2 mov eax,edx
7574a8f4 f7d1 not ecx
7574a8f6 83e140 and ecx,40h
7574a8f9 2500001f00 and eax,1F0000h
7574a8fe c7459c18000000 mov dword ptr [ebp-64h],18h
7574a905 894da8 mov dword ptr [ebp-58h],ecx
7574a908 895dac mov dword ptr [ebp-54h],ebx
7574a90b a900001000 test eax,100000h
7574a910 0f85eb420000 jne KERNELBASE!CreateFileW+0x11e (7574ec01)
7574a916 c645cc01 mov byte ptr [ebp-34h],1
7574a91a c745c802000000 mov dword ptr [ebp-38h],2
7574a921 c645cd01 mov byte ptr [ebp-33h],1
7574a925 8d45c4 lea eax,[ebp-3Ch]
7574a928 8945b0 mov dword ptr [ebp-50h],eax
7574a92b 8b4514 mov eax,dword ptr [ebp+14h]
7574a92e c745c40c000000 mov dword ptr [ebp-3Ch],0Ch
7574a935 3bc3 cmp eax,ebx
7574a937 0f85493a0000 jne KERNELBASE!CreateFileW+0x178 (7574e386)
7574a93d 57 push edi
7574a93e 895d14 mov dword ptr [ebp+14h],ebx
7574a941 895df4 mov dword ptr [ebp-0Ch],ebx
7574a944 395d20 cmp dword ptr [ebp+20h],ebx
7574a947 0f8586710000 jne KERNELBASE!CreateFileW+0x199 (75751ad3)
7574a94d 8bf2 mov esi,edx
7574a94f c1ee04 shr esi,4
7574a952 b800000008 mov eax,8000000h
7574a957 23f0 and esi,eax
7574a959 8bfa mov edi,edx
7574a95b 81e700000020 and edi,20000000h
7574a961 0bf7 or esi,edi
7574a963 d1ee shr esi,1
7574a965 8bfa mov edi,edx
7574a967 23f8 and edi,eax
7574a969 0bf7 or esi,edi
7574a96b c1ee08 shr esi,8
7574a96e 8bc2 mov eax,edx
7574a970 2500000010 and eax,10000000h
7574a975 0bf0 or esi,eax
7574a977 c1ee06 shr esi,6
7574a97a 8bca mov ecx,edx
7574a97c 8bc2 mov eax,edx
7574a97e c1e819 shr eax,19h
7574a981 81e100000002 and ecx,2000000h
7574a987 0bf1 or esi,ecx
7574a989 f7d0 not eax
7574a98b c1ee0b shr esi,0Bh
7574a98e 83e020 and eax,20h
7574a991 0bf0 or esi,eax
7574a993 097508 or dword ptr [ebp+8],esi
7574a996 f7c200000004 test edx,4000000h
7574a99c 0f85644a0000 jne KERNELBASE!CreateFileW+0x28b (7574f406)
7574a9a2 b800002000 mov eax,200000h
7574a9a7 85d0 test eax,edx
7574a9a9 0f85013b0000 jne KERNELBASE!CreateFileW+0x2a2 (7574e4b0)
7574a9af f7c200001000 test edx,100000h
7574a9b5 0f8572420000 jne KERNELBASE!CreateFileW+0x2ad (7574ec2d)
7574a9bb 3bcb cmp ecx,ebx
7574a9bd 0f8531caffff jne KERNELBASE!CreateFileW+0x2ed (757473f4)
7574a9c3 834d0840 or dword ptr [ebp+8],40h
7574a9c7 6a01 push 1
7574a9c9 6814a87475 push offset KERNELBASE!g_SbModuleTable_Scenario (7574a814)
7574a9ce 6a01 push 1
7574a9d0 68abababab push 0ABABABABh
7574a9d5 e863feffff call KERNELBASE!SbSelectProcedure (7574a83d)
7574a9da 3bc3 cmp eax,ebx
7574a9dc 7406 je KERNELBASE!CreateFileW+0x321 (7574a9e4)
7574a9de 8d4d08 lea ecx,[ebp+8]
7574a9e1 51 push ecx
7574a9e2 ffd0 call eax
7574a9e4 ff75f4 push dword ptr [ebp-0Ch]
7574a9e7 8b4d1c mov ecx,dword ptr [ebp+1Ch]
7574a9ea ff7514 push dword ptr [ebp+14h]
7574a9ed 8b450c mov eax,dword ptr [ebp+0Ch]
7574a9f0 ff7508 push dword ptr [ebp+8]
7574a9f3 8b35b0107475 mov esi,dword ptr [KERNELBASE!_imp__NtCreateFile (757410b0)]
7574a9f9 ff75fc push dword ptr [ebp-4]
7574a9fc 81e1a77f0000 and ecx,7FA7h
7574aa02 ff7510 push dword ptr [ebp+10h]
7574aa05 894d1c mov dword ptr [ebp+1Ch],ecx
7574aa08 51 push ecx
7574aa09 53 push ebx
7574aa0a 8d4de0 lea ecx,[ebp-20h]
7574aa0d 51 push ecx
7574aa0e 0d80001000 or eax,100080h
7574aa13 8d4d9c lea ecx,[ebp-64h]
7574aa16 51 push ecx
7574aa17 50 push eax
7574aa18 89450c mov dword ptr [ebp+0Ch],eax
7574aa1b 8d45f8 lea eax,[ebp-8]
7574aa1e 50 push eax
7574aa1f ffd6 call esi
7574aa21 8bd8 mov ebx,eax
7574aa23 bf220000c0 mov edi,0C0000022h
7574aa28 3bdf cmp ebx,edi
7574aa2a 0f8433690000 je KERNELBASE!CreateFileW+0x369 (75751363)
7574aa30 8d45b4 lea eax,[ebp-4Ch]
7574aa33 50 push eax
7574aa34 ff15f4137475 call dword ptr [KERNELBASE!_imp__RtlReleaseRelativeName (757413f4)]
7574aa3a ff75f0 push dword ptr [ebp-10h]
7574aa3d 64a118000000 mov eax,dword ptr fs:[00000018h]
7574aa43 8b4030 mov eax,dword ptr [eax+30h]
7574aa46 8b3514107475 mov esi,dword ptr [KERNELBASE!_imp__RtlFreeHeap (75741014)]
7574aa4c 33ff xor edi,edi
7574aa4e 57 push edi
7574aa4f ff7018 push dword ptr [eax+18h]
7574aa52 ffd6 call esi
7574aa54 ff7514 push dword ptr [ebp+14h]
7574aa57 64a118000000 mov eax,dword ptr fs:[00000018h]
7574aa5d 8b4030 mov eax,dword ptr [eax+30h]
7574aa60 57 push edi
7574aa61 ff7018 push dword ptr [eax+18h]
7574aa64 ffd6 call esi
7574aa66 3bdf cmp ebx,edi
7574aa68 7c2f jl KERNELBASE!CreateFileW+0x3fe (7574aa99)
7574aa6a 837d1802 cmp dword ptr [ebp+18h],2
7574aa6e 0f8469340000 je KERNELBASE!CreateFileW+0x434 (7574dedd)
7574aa74 837d1804 cmp dword ptr [ebp+18h],4
7574aa78 0f847e340000 je KERNELBASE!CreateFileW+0x440 (7574defc)
7574aa7e 57 push edi
7574aa7f ff1548107475 call dword ptr [KERNELBASE!_imp__RtlSetLastWin32Error (75741048)]
7574aa85 837d1805 cmp dword ptr [ebp+18h],5
7574aa89 0f8441d40100 je KERNELBASE!CreateFileW+0x45a (75767ed0)
7574aa8f 8b45f8 mov eax,dword ptr [ebp-8]
7574aa92 5f pop edi
7574aa93 5e pop esi
7574aa94 5b pop ebx
7574aa95 c9 leave
7574aa96 c21c00 ret 1Ch
7574aa99 53 push ebx
7574aa9a e856c0ffff call KERNELBASE!BaseSetLastNTError (75746af5)
7574aa9f 81fb350000c0 cmp ebx,0C0000035h
7574aaa5 0f844fa10000 je KERNELBASE!CreateFileW+0x40c (75754bfa)
7574aaab 81fbba0000c0 cmp ebx,0C00000BAh
7574aab1 0f8462a10000 je KERNELBASE!CreateFileW+0x418 (75754c19)
7574aab7 83c8ff or eax,0FFFFFFFFh
7574aaba ebd6 jmp KERNELBASE!CreateFileW+0x48f (7574aa92)
7574aabc 90 nop
7574aabd 90 nop
7574aabe 90 nop
7574aabf 90 nop
7574aac0 90 nop
KERNELBASE!AllocateAndInitializeSid:
7574aac1 8bff mov edi,edi
7574aac3 55 push ebp
7574aac4 8bec mov ebp,esp
7574aac6 ff7530 push dword ptr [ebp+30h]
7574aac9 ff752c push dword ptr [ebp+2Ch]
7574aacc ff7528 push dword ptr [ebp+28h]
7574aacf ff7524 push dword ptr [ebp+24h]
7574aad2 ff7520 push dword ptr [ebp+20h]
7574aad5 ff751c push dword ptr [ebp+1Ch]
7574aad8 ff7518 push dword ptr [ebp+18h]
7574aadb ff7514 push dword ptr [ebp+14h]
7574aade ff7510 push dword ptr [ebp+10h]
7574aae1 ff750c push dword ptr [ebp+0Ch]
7574aae4 ff7508 push dword ptr [ebp+8]
7574aae7 ff1520137475 call dword ptr [KERNELBASE!_imp__RtlAllocateAndInitializeSid (75741320)]
7574aaed 85c0 test eax,eax
7574aaef 0f8c6d260200 jl KERNELBASE!AllocateAndInitializeSid+0x30 (7576d162)
7574aaf5 33c0 xor eax,eax
7574aaf7 40 inc eax
7574aaf8 5d pop ebp
7574aaf9 c22c00 ret 2Ch
7574aafc 90 nop
7574aafd 90 nop
7574aafe 90 nop
7574aaff 90 nop
7574ab00 90 nop
KERNELBASE!FreeSid:
7574ab01 8bff mov edi,edi
7574ab03 55 push ebp
7574ab04 8bec mov ebp,esp
7574ab06 5d pop ebp
7574ab07 ff2508137475 jmp dword ptr [KERNELBASE!_imp__RtlFreeSid (75741308)]
7574ab0d 90 nop
7574ab0e 90 nop
7574ab0f 90 nop
7574ab10 90 nop
7574ab11 90 nop
KERNELBASE!DuplicateTokenEx:
7574ab12 8bff mov edi,edi
7574ab14 55 push ebp
7574ab15 8bec mov ebp,esp
7574ab17 83ec24 sub esp,24h
7574ab1a 8b4514 mov eax,dword ptr [ebp+14h]
7574ab1d 8945f8 mov dword ptr [ebp-8],eax
7574ab20 8b4510 mov eax,dword ptr [ebp+10h]
7574ab23 c745f40c000000 mov dword ptr [ebp-0Ch],0Ch
7574ab2a c645fc01 mov byte ptr [ebp-4],1
7574ab2e c645fd00 mov byte ptr [ebp-3],0
7574ab32 85c0 test eax,eax
7574ab34 0f858cc40000 jne KERNELBASE!DuplicateTokenEx+0x24 (75756fc6)
7574ab3a 33c9 xor ecx,ecx
7574ab3c 33c0 xor eax,eax
7574ab3e ff751c push dword ptr [ebp+1Ch]
7574ab41 8365e000 and dword ptr [ebp-20h],0
7574ab45 ff7518 push dword ptr [ebp+18h]
7574ab48 8365e400 and dword ptr [ebp-1Ch],0
7574ab4c 8945e8 mov dword ptr [ebp-18h],eax
7574ab4f 8d45f4 lea eax,[ebp-0Ch]
7574ab52 6a00 push 0
7574ab54 8945f0 mov dword ptr [ebp-10h],eax
7574ab57 8d45dc lea eax,[ebp-24h]
7574ab5a 50 push eax
100条仅仅是測试,看有没有得到完整的 CreateFileW 函数的反汇编。非常明显这里面的后半部分是 KERNELBASE!AllocateAndInitializeSid 的代码。所以我们仅仅关注上半部分。
先从 call 语句 逐条来看:
从上往下各自是
7574a881 ff15fc117475 call dword ptr [KERNELBASE!_imp__RtlInitUnicodeStringEx (757411fc)]
7574a8bb ff15fc137475 call dword ptr [KERNELBASE!_imp__RtlDosPathNameToRelativeNtPathName_U_WithStatus (757413fc)]
7574a9d5 e863feffff call KERNELBASE!SbSelectProcedure (7574a83d)
7574aa1f ffd6 call esi
这一条 esi ,所以须要往上看 esi 的值是什么,于是:(新大陆~~)
7574a9f3 8b35b0107475 mov esi,dword ptr [KERNELBASE!_imp__NtCreateFile (757410b0)]
我们知道 CreateFileW 内部的函数确实是 NtCreateFile。
那么我们就在 call esi 处下断点:
3: kd> bp 7574aa1f
3: kd> bl
0 e 759ecca9 0001 (0001) kernel32!CreateFileW
1 e 7574aa1f 0001 (0001) KERNELBASE!CreateFileW+0x35c
运行:
3: kd> g
Breakpoint 1 hit
KERNELBASE!CreateFileW+0x35c:
001b:7574aa1f ffd6 call esi
单步进入:
3: kd> t
ntdll!NtCreateFile:
001b:774d55c8 b842000000 mov eax,42h
如今我们就来到了 ntdll 中的 NtCreateFile 函数中了。
当前地址反汇编:
3: kd> u
ntdll!NtCreateFile:
774d55c8 b842000000 mov eax,42h
774d55cd ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
774d55d2 ff12 call dword ptr [edx]
774d55d4 c22c00 ret 2Ch
774d55d7 90 nop
ntdll!NtCreateIoCompletion:
774d55d8 b843000000 mov eax,43h
774d55dd ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
774d55e2 ff12 call dword ptr [edx]
如今正处在过渡的关键时刻!就要用到之前的理论知识了。忘了?再来:
假设想要从 Ring3 层进入 Ring0 层,
- 系统首先会将要调用的系统调用号(SSDT调用号)放入 EAX 中,
- 然后将当前栈指针 ESP 的内容放入 EDX 中后 运行SYSENTER 指令;
- SYSENTER 被运行后会将控制权传递给特殊模块寄存器IA32_SYSENTER_EIP 所指向的函数中,完毕兴许操作。
如今地址 774d55c8 处就是“将要调用的系统调用号(SSDT调用号)放入 EAX 中”。啥?什么是 SSDT 调用号?如今我们能够觉得系统函数的地址都放在一个大数组里面,仅仅要知道一个索引。就能依据它找到函数地址从而调用。
如今单步三次进入call的函数内部:
3: kd> t
ntdll!NtCreateFile+0x5:
001b:774d55cd ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300)
3: kd> t
ntdll!NtCreateFile+0xa:
001b:774d55d2 ff12 call dword ptr [edx]
3: kd> t
ntdll!KiFastSystemCall:
001b:774d70b0 8bd4 mov edx,esp
反汇编:
3: kd> u
ntdll!KiFastSystemCall:
774d70b0 8bd4 mov edx,esp
774d70b2 0f34 sysenter
ntdll!KiFastSystemCallRet:
774d70b4 c3 ret
774d70b5 8da42400000000 lea esp,[esp]
774d70bc 8d642400 lea esp,[esp]
ntdll!KiIntSystemCall:
774d70c0 8d542408 lea edx,[esp+8]
774d70c4 cd2e int 2Eh
774d70c6 c3 ret
774d70b0 反地址处就是 “将当前 栈指针 ESP 的内容放入 EDX ”的操作
以下一句当然就是 “运行SYSENTER 指令”咯。
主要的流程已经验证,那我们来找一下SSDT数组的基址。
so,我们如今的情况是:
EAX:SSDT 调用号(当前是 0x42)
EDX:ESP 的内容
我们又知道 SYSENTER_EIP_MSR 在偏移 0x176 处,功能:切换到 Ring0 层之后的 EIP,设置目标指令。
查看一下 SYSENTER_EIP_MSR 的内容:
3: kd> rdmsr 176
msr[176] = 00000000`8404a750
所以目标指令就在 00000000`8404a750 处。
我们就在这里下个条件断点(由于sysenter仅仅是一条指令并不是函数,直接t会跳过。在用户态的代码运行了SYSENTER指令之后,处理器中的控制单元将寄存器MSR_IA32_SYSENTER_EIP的值装载到指令指针寄存器eip中)。假设断在这里时 SSDT调用号也为0x42,那么就断下来,否则继续运行
3: kd> bp 8404a750 ".if (@eax & 0x0‘ffffffff)=0x0‘42 {} .else {gc}"
3: kd> bl
0 e 759ecca9 0001 (0001) kernel32!CreateFileW
1 e 7574aa1f 0001 (0001) KERNELBASE!CreateFileW+0x35c
2 e 8404a750 0001 (0001) nt!KiFastCallEntry ".if (@eax & 0x0‘ffffffff)=0x0‘42 {}
关于 gc:(从条件断点处继续运行)
The gc command resumes execution from a conditional breakpoint in the same fashion that was used to hit the breakpoint (stepping, tracing, or freely executing).
运行:
3: kd> g
Syntax error at ‘‘ffffffff)=0x0‘42 {} .else {gc}‘
nt!KiFastCallEntry:
8404a750 b923000000 mov ecx,23h
(此时 SYSENTER 的切换操作已经完毕大部分)
反汇编来一套:
3: kd> u nt!KiFastCallEntry l50
nt!KiFastCallEntry:
8404a750 b923000000 mov ecx,23h
8404a755 6a30 push 30h
8404a757 0fa1 pop fs
8404a759 8ed9 mov ds,cx
8404a75b 8ec1 mov es,cx
8404a75d 648b0d40000000 mov ecx,dword ptr fs:[40h]
8404a764 8b6104 mov esp,dword ptr [ecx+4]
8404a767 6a23 push 23h
8404a769 52 push edx
8404a76a 9c pushfd
8404a76b 6a02 push 2
8404a76d 83c208 add edx,8
8404a770 9d popfd
8404a771 804c240102 or byte ptr [esp+1],2
8404a776 6a1b push 1Bh
8404a778 ff350403dfff push dword ptr ds:[0FFDF0304h]
8404a77e 6a00 push 0
8404a780 55 push ebp
8404a781 53 push ebx
8404a782 56 push esi
8404a783 57 push edi
8404a784 648b1d1c000000 mov ebx,dword ptr fs:[1Ch]
8404a78b 6a3b push 3Bh
8404a78d 8bb324010000 mov esi,dword ptr [ebx+124h]
8404a793 ff33 push dword ptr [ebx]
8404a795 c703ffffffff mov dword ptr [ebx],0FFFFFFFFh
8404a79b 8b6e28 mov ebp,dword ptr [esi+28h]
8404a79e 6a01 push 1
8404a7a0 83ec48 sub esp,48h
8404a7a3 81ed9c020000 sub ebp,29Ch
8404a7a9 c6863a01000001 mov byte ptr [esi+13Ah],1
8404a7b0 3bec cmp ebp,esp
8404a7b2 7597 jne nt!KiFastCallEntry2+0x49 (8404a74b)
8404a7b4 83652c00 and dword ptr [ebp+2Ch],0
8404a7b8 f64603df test byte ptr [esi+3],0DFh
8404a7bc 89ae28010000 mov dword ptr [esi+128h],ebp
8404a7c2 0f8538feffff jne nt!Dr_FastCallDrSave (8404a600)
8404a7c8 8b5d60 mov ebx,dword ptr [ebp+60h]
8404a7cb 8b7d68 mov edi,dword ptr [ebp+68h]
8404a7ce 89550c mov dword ptr [ebp+0Ch],edx
8404a7d1 c74508000ddbba mov dword ptr [ebp+8],0BADB0D00h
8404a7d8 895d00 mov dword ptr [ebp],ebx
8404a7db 897d04 mov dword ptr [ebp+4],edi
8404a7de fb sti
8404a7df 8bf8 mov edi,eax
8404a7e1 c1ef08 shr edi,8
8404a7e4 83e710 and edi,10h
8404a7e7 8bcf mov ecx,edi
8404a7e9 03bebc000000 add edi,dword ptr [esi+0BCh]
8404a7ef 8bd8 mov ebx,eax
8404a7f1 25ff0f0000 and eax,0FFFh
8404a7f6 3b4708 cmp eax,dword ptr [edi+8]
8404a7f9 0f8333fdffff jae nt!KiBBTUnexpectedRange (8404a532)
8404a7ff 83f910 cmp ecx,10h
8404a802 751a jne nt!KiFastCallEntry+0xce (8404a81e)
8404a804 8b8e88000000 mov ecx,dword ptr [esi+88h]
8404a80a 33f6 xor esi,esi
8404a80c 0bb1700f0000 or esi,dword ptr [ecx+0F70h]
8404a812 740a je nt!KiFastCallEntry+0xce (8404a81e)
8404a814 52 push edx
8404a815 50 push eax
8404a816 ff152c581784 call dword ptr [nt!KeGdiFlushUserBatch (8417582c)]
8404a81c 58 pop eax
8404a81d 5a pop edx
8404a81e 64ff05b0060000 inc dword ptr fs:[6B0h]
8404a825 8bf2 mov esi,edx
8404a827 33c9 xor ecx,ecx
8404a829 8b570c mov edx,dword ptr [edi+0Ch]
8404a82c 8b3f mov edi,dword ptr [edi]
8404a82e 8a0c10 mov cl,byte ptr [eax+edx]
8404a831 8b1487 mov edx,dword ptr [edi+eax*4]
8404a834 2be1 sub esp,ecx
8404a836 c1e902 shr ecx,2
8404a839 8bfc mov edi,esp
8404a83b 3b3504571784 cmp esi,dword ptr [nt!MmUserProbeAddress (84175704)]
8404a841 0f832e020000 jae nt!KiSystemCallExit2+0xa5 (8404aa75)
8404a847 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
8404a849 f6456c01 test byte ptr [ebp+6Ch],1
8404a84d 7416 je nt!KiFastCallEntry+0x115 (8404a865)
8404a84f 648b0d24010000 mov ecx,dword ptr fs:[124h]
在这段代码里面系统须要依据 SSDT调用号找到所在的地址,所以必须回出现 EAX*4 这个字眼,果然。我们就在这里发现了它。
8404a831 8b1487 mov edx,dword ptr [edi+eax*4]
那么 edi 必须就是 SSDT大数组的起始地址。
我们须要找到它是在哪里被赋值的。
往上发现:
8404a82c 8b3f mov edi,dword ptr [edi]
往上找 edi:
8404a7df 8bf8 mov edi,eax
8404a7e1 c1ef08 shr edi,8
8404a7e4 83e710 and edi,10h
8404a7e7 8bcf mov ecx,edi
8404a7e9 03bebc000000 add edi,dword ptr [esi+0BCh]
往上找 esi:
8404a78d 8bb324010000 mov esi,dword ptr [ebx+124h]
往上找 ebx:
8404a784 648b1d1c000000 mov ebx,dword ptr fs:[1Ch]
我们知道 fs寄存器 是专门指向 TEB 结构的。
fs:[1ch] 处:EnvironmentPointer:环境指针。
那么我们在 8404a831 处(mov edx,dword ptr [edi+eax*4])下断点。
3: kd> bp 8404a831
3: kd> bl
0 e 759ecca9 0001 (0001) kernel32!CreateFileW
1 e 7574aa1f 0001 (0001) KERNELBASE!CreateFileW+0x35c
2 e 8404a750 0001 (0001) nt!KiFastCallEntry ".if (@eax & 0x0‘ffffffff)=0x0‘42 {} .else {gc}"
3 e 8404a831 0001 (0001) nt!KiFastCallEntry+0xe1
运行:
3: kd> g
Breakpoint 3 hit
nt!KiFastCallEntry+0xe1:
8404a831 8b1487 mov edx,dword ptr [edi+eax*4]
看一下此时 edi 的值(数组基址)
3: kd> r edi
edi=8407173c
此地址的内容:
3: kd> dd edi
8407173c 8424fa7a 8409ff84 84287e50 840cbb2e
8407174c 8426a1c1 8410b9d2 842f6d4d 842f6d96
8407175c 84273c93 84310424 8431167d 841e1f06
8407176c 84281082 842ea209 842728cb 8426e15a
8407177c 841a352d 842dc3de 841e7f2a 8421fe43
8407178c 84265890 841e00e9 84233141 8427ba08
8407179c 84273989 841fd65f 84273769 8423cfc0
840717ac 84274833 842d743f 842557da 842474a0
全部都是一些 以 84 开头的地址
曾经两个为例,反汇编看一下:
3: kd> u 8407173c
nt!KiServiceTable:(SSDT首地址)
8407173c 7afa jp nt!KeFlushMultipleRangeTb+0x2e9 (84071738)
8407173e 2484 and al,84h
84071740 84ff test bh,bh
84071742 0984507e28842e or dword ptr [eax+edx*2+2E84287Eh],eax
84071749 bb0c84c1a1 mov ebx,0A1C1840Ch
8407174e 2684d2 test dl,dl
84071751 b910844d6d mov ecx,6D4D8410h
84071756 2f das
3: kd> u 8424fa7a
nt!NtAcceptConnectPort:(第一个函数)
8424fa7a 8bff mov edi,edi
8424fa7c 55 push ebp
8424fa7d 8bec mov ebp,esp
8424fa7f 64a124010000 mov eax,dword ptr fs:[00000124h]
8424fa85 66ff8884000000 dec word ptr [eax+84h]
8424fa8c 56 push esi
8424fa8d 57 push edi
8424fa8e 6a01 push 1
you know it. :)
从 NtCreateFile 函数中開始后的流程大致为:
- [SharedUserData!SystemCallStub]=ntdll!KiFastSystemCall
- sysenter
- nt!KiFastCallEntry
- 查找调用号在SSDT的地址
最后再来回想一下 ring3-ring0 的步骤:
1. 系统首先会将要调用的系统调用号(SSDT调用号)放入 EAX 中。
2. 然后将当前栈指针 ESP 的内容放入 EDX 中后运行SYSENTER 指令;
3. SYSENTER 被运行后会将控制权传递给特殊模块寄存器 IA32_SYSENTER_EIP 所指向的函数中,完毕兴许操作。
写完这个流水账之后发现了这篇文章 《重要》从用户模式切换到内核模式的完整过程分析。解说的更为清晰透彻。
我等文笔什么时候才干达成这样的成就。:(
以上是关于跟踪 Ring3 - Ring0 的运行流程的主要内容,如果未能解决你的问题,请参考以下文章