MSR寄存器
sysenter进入0环直接从MSR寄存器获取寄存器的值
中断门进入0环需要查内存(TSS\IDT)获取寄存器的值
MSR 地址
IA32_SYSENTER_CS 174H
IA32_SYSENTER_ESP 175H
IA32_SYSENTER_EIP 176H
可以通过RDMSR/WRMSR来进行读写
rdmsr 174 //查看cs
rdmsr 175 //查看esp
rdmsr 176 //查看eip
ss = cs + 0x8
_KiSystemService
如何找到这个函数
中断门进入,中断号是 0x2e
kd> dq 8003f400+2e*8
8003f570 804dee00`0008f631 804e8e00`0008297c
8003f580 806f8e00`00085d54 89938e00`0008371c
8003f590 804d8e00`0008ed04 804d8e00`0008ed0e
我们找到EIP的地址是 : 804df631
查找该函数在什么模块中 :
kd> dd PsLoadedModuleList
8055c1c0 89c403b8 89ab0730 00000000 00000000
8055c1d0 00000000 00000000 00000000 00000000
kd> dt _LDR_DATA_TABLE_ENTRY 89c403b8
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x89c40350 - 0x8055c1c0 ]
+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x018 DllBase : 0x804d8000 Void
+0x01c EntryPoint : 0x806afb2c Void
+0x020 SizeOfImage : 0x216580
+0x024 FullDllName : _UNICODE_STRING "\WINDOWS\system32\ntoskrnl.exe"
+0x02c BaseDllName : _UNICODE_STRING "ntoskrnl.exe"
+0x034 Flags : 0xc004000
+0x038 LoadCount : 1
+0x03a TlsIndex : 0
+0x03c HashLinks : _LIST_ENTRY [ 0x0 - 0x224a17 ]
+0x03c SectionPointer : (null)
+0x040 CheckSum : 0x224a17
+0x044 TimeDateStamp : 0
+0x044 LoadedImports : (null)
+0x048 EntryPointActivationContext : (null)
+0x04c PatchInformation : 0x0074006e Void
可以看到 函数地址 804df631 在该模块中 ntoskrnl.exe 中 0x804df631 - 0x804d8000 = 0x7631
加上它的imagebase就可以定位到了
逆向分析
.text:00407631 _KiSystemService: ; DATA XREF: INIT:005DD660↓o
.text:00407631 push 0 ;错误码,如果发生异常的时候,CPU会自动填充,如果不是需要自己填充0
.text:00407633 push ebp
push ebx
push esi
push edi
push fs
mov ebx, 30h
mov fs, ebx ;GDT表0x30段描述符加载到fs寄存器
assume fs:nothing
push dword ptr ds:0FFDFF000h ; NT_TIB (ExceptionList) 异常处理链表
mov dword ptr ds:0FFDFF000h, 0FFFFFFFFh ;将KPCR的ExceptionList置为-1
mov esi, ds:0FFDFF124h ;esi = 从KPCR中获取CurrentThread的地址
push dword ptr [esi+140h] ; 从当前线程中获取PreviousMode放到_KTrap_Frame中
sub esp, 48h ;提升堆栈,这个时候 esp => _KTrap_Frame
mov ebx, [esp+6Ch] ;3环的CS的值
and ebx, 1 ;cs and 1 => 判断 (3环 = 1) (0环 = 0)操作系统没有使用1和2环
mov [esi+140h], bl ;设置当前线程ETHREAD的先前模式
mov ebp, esp ; ebp = esp = _KTrap_Frame
mov ebx, [esi+134h] ; THREAD的_KTrap_Frame的结构体的地址
mov [ebp+3Ch], ebx ;旧的_KTrap_Frame存储到新的_KTrap_Frame的Edx中
mov [esi+134h], ebp ;将当前的_KTrap_Frame的地址存储到ETHREAD的_KTrap_Frame属性中
cld
mov ebx, [ebp+60h] ;3环的ebp
mov edi, [ebp+68h] ;3环的eip
mov [ebp+0Ch], edx ; 3环参数指针
mov dword ptr [ebp+8], 0BADB0D00h ;这个不清楚啊,知道的老铁可以评论区留言
mov [ebp+0], ebx ;备份了一份3环ebp
mov [ebp+4], edi ;备份了一份3环eip
test byte ptr [esi+2Ch], 0FFh ; DebugActive 判断当前线程是不是调试状态
jnz loc_40752C ;不相等则跳转 如果处于调试状态,则会进入,将调式相关的寄存器进行保存
.text:0040769E loc_40769E: ; CODE XREF: sub_407631-F5↑j
.text:0040769E ; sub_407631-89↑j
.text:0040769E sti
.text:0040769F jmp loc_407781
----------------------------------------------------------------------------------------------------------
loc_407781:
; CODE XREF: sub_407631-137↑j
.text:00407781 ; sub_407631+6E↑j
.text:00407781 mov edi, eax ;获取函数编号
.text:00407783 shr edi, 8 ;
.text:00407786 and edi, 30h ; edi = 0 (gui函数 = 0x10)
.text:00407789 mov ecx, edi ; ecx = 0 (gui函数 = 0x10)
.text:0040778B add edi, [esi+0E0h] ; ServiceTable指向系统服务表基址
.text:00407791 mov ebx, eax ; ebx = 函数的编号
.text:00407793 and eax, 0FFFh ; 系统调用号 只保留后12位
.text:00407798 cmp eax, [edi+8] ;limit 和 eax 比较,是否超过范围
.text:0040779B jnb loc_4074E2 ;大于等于则跳转,一般是不会超过的
.text:004077A1 cmp ecx, 10h ;判断是什么函数
.text:004077A4 jnz short loc_4077C0
.text:004077A6 mov ecx, ds:0FFDFF018h
.text:004077AC xor ebx, ebx
----------------------------------------------------------------------------------------------------------
loc_4077C0:
; CODE XREF: sub_407631+173↑j
.text:004077C0 ; sub_407631+183↑j
.text:004077C0 inc dword ptr ds:0FFDFF638h ; KeSystemCalls 加一
.text:004077C6 mov esi, edx ;edx是函数的参数的地址
.text:004077C8 mov ebx, [edi+0Ch] ;ebx = 函数的参数的个数表的地址
.text:004077CB xor ecx, ecx ;ecx = 0
.text:004077CD mov cl, [eax+ebx] ;这个时候cl获取的是参数的个数
.text:004077D0 mov edi, [edi] ;edi = 函数地址表的地址
.text:004077D2 mov ebx, [edi+eax*4] ;ebx = 函数的地址,eax是index
.text:004077D5 sub esp, ecx ;提升堆栈,就是参数的大小
.text:004077D7 shr ecx, 2 ; ecx = ecx / 4 循环的次数
.text:004077DA mov edi, esp ; edi = 栈顶,参数复制的startAddress
.text:004077DC cmp esi, ds:MmUserProbeAddress ; 判断三环的参数的地址范围是否越界
.text:004077E2 jnb loc_407990
.text:004077E8
----------------------------------------------------------------------------------------------------------
loc_4077E8:
; CODE XREF: sub_407631+363↓j
.text:004077E8 ; DATA XREF: .text:0040A755↓o
.text:004077E8 rep movsd ;复制参数,到0环环境
.text:004077EA call ebx ;调用函数
----------------------------------------------------------------------------------------------------------
loc_407990:
; CODE XREF: sub_407631+1B1↑j
.text:00407990 test byte ptr [ebp+6Ch], 1
.text:00407994 jz loc_4077E8 ;如果是0环则跳转
.text:0040799A mov eax, 0C0000005h
.text:0040799F jmp loc_4077EC
KiFastCallEntry
sysenter进入0环的
rdmsr 176 可以查看要执行的EIP
.text:7C92D9E0 ZwReadVirtualMemory proc near ; CODE XREF: LdrFindCreateProcessManifest+1CC↓p
.text:7C92D9E0 ; LdrCreateOutOfProcessImage+7C↓p ...
.text:7C92D9E0 mov eax, 0BAh ; NtReadVirtualMemory
.text:7C92D9E5 mov edx, 7FFE0300h
.text:7C92D9EA call dword ptr [edx] ;这个找到就是0环和3环共享的数据区 : dt _KUSER_SHARED_DATA 0xffdf0000(0x7ffe0000)的SystemCall的值
.text:7C92D9EC retn 14h
.text:7C92D9EC ZwReadVirtualMemory endp
----------------------------------------------------------------------------------------------------------
.text:7C92E4F0 KiFastSystemCall proc near ; DATA XREF: .text:off_7C923428↑o
.text:7C92E4F0 mov edx, esp
.text:7C92E4F2 sysenter
;快速调用 , 不去tss找esp0的值,而是直接去msr寄存器中获取 cs 、 esp 、eip
----------------------------------------------------------------------------------------------------------
; eip 指向的就是下面的代码
; 前面的代码是需要我们赋值多个
; 后面调用系统服务表和上面都是一样的操作
loc_4076F0:
; DATA XREF: .text:0040853A↓o
.text:004076F0 ; .text:0043A074↓o
.text:004076F0 mov ecx, 23h
.text:004076F5 push 30h
.text:004076F7 pop fs ;查看GDT表 0x30的段描述符 ffc093df`f0000001
; 数据段,可读可写
; fs.Base = ffdff000
; fs.Limit= 1(单位4kb)
.text:004076F9 mov ds, ecx
.text:004076FB mov es, ecx
.text:004076FD mov ecx, ds:0FFDFF040h ; ecx = TSS
.text:00407703 mov esp, [ecx+4] ; esp = TSS的Esp0
.text:00407706 push 23h ;3环的SS
.text:00407708 push edx ; edx是3环esp
.text:00407709 pushf ; 3环的eflags
.text:0040770A
.text:0040770A push 2
.text:0040770C add edx, 8
.text:0040770F popf
.text:00407710 or byte ptr [esp+1], 2
.text:00407715 push 1Bh ;3环的CS
.text:00407717 push dword ptr ds:0FFDF0304h ;3环的EIP
.text:0040771D push 0
.text:0040771F push ebp
.text:00407720 push ebx
.text:00407721 push esi
.text:00407722 push edi
.text:00407723 mov ebx, ds:0FFDFF01Ch
.text:00407729 push 3Bh
.text:0040772B mov esi, [ebx+124h]
.text:00407731 push dword ptr [ebx]
.text:00407733 mov dword ptr [ebx], 0FFFFFFFFh
.text:00407739 mov ebp, [esi+18h]
.text:0040773C push 1
查看当前有几个核
dt KeNumberProcessors
查看KPCR列表
dd KiProcessorBlock
减去 0x120 就是KPCR的地址
_KTrap_Frame
进来的时候都走这
TSS一个core只有一个,切换线程的时候,它就要改变TSS保证当前线程进0环的时候,能够找到当前线程正确的_KTrap_Frame的结构
一个线程一个 _KTrap_Frame
kd> dt _KTrap_Frame
ntdll!_KTRAP_FRAME
+0x000 DbgEbp : Uint4B
+0x004 DbgEip : Uint4B
+0x008 DbgArgMark : Uint4B
+0x00c DbgArgPointer : Uint4B ;3环参数指针
+0x010 TempSegCs : Uint4B
+0x014 TempEsp : Uint4B
+0x018 Dr0 : Uint4B
+0x01c Dr1 : Uint4B
+0x020 Dr2 : Uint4B
+0x024 Dr3 : Uint4B
+0x028 Dr6 : Uint4B
+0x02c Dr7 : Uint4B
+0x030 SegGs : Uint4B
+0x034 SegEs : Uint4B
+0x038 SegDs : Uint4B
+0x03c Edx : Uint4B
+0x040 Ecx : Uint4B
+0x044 Eax : Uint4B
+0x048 PreviousPreviousMode : Uint4B ;先前模式,指示程序是0环调用还是3环调用的
+0x04c ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD ;存储当前线程内核异常链表,简称SEH
+0x050 SegFs : Uint4B
+0x054 Edi : Uint4B
+0x058 Esi : Uint4B
+0x05c Ebx : Uint4B
+0x060 Ebp : Uint4B
+0x064 ErrCode : Uint4B ; <- esp0
+0x068 Eip : Uint4B ; 调用中断门进入 _KiSystenService ,会push5个指 eip cs flags esp ss,在push之前会把esp的值替换为TSS中存储的 esp0
+0x06c SegCs : Uint4B
+0x070 EFlags : Uint4B
+0x074 HardwareEsp : Uint4B
+0x078 HardwareSegSs : Uint4B ;TSS内存 > ESP0指向的位置
+0x07c V86Es : Uint4B ;虚拟模式使用
+0x080 V86Ds : Uint4B ;虚拟模式使用
+0x084 V86Fs : Uint4B ;虚拟模式使用
+0x088 V86Gs : Uint4B ;虚拟模式使用
_KTSS
kd> dt _KTSS
nt!_KTSS
+0x000 Backlink : Uint2B
+0x002 Reserved0 : Uint2B
+0x004 Esp0 : Uint4B
+0x008 Ss0 : Uint2B
+0x00a Reserved1 : Uint2B
+0x00c NotUsed1 : [4] Uint4B
+0x01c CR3 : Uint4B
+0x020 Eip : Uint4B
+0x024 EFlags : Uint4B
+0x028 Eax : Uint4B
+0x02c Ecx : Uint4B
+0x030 Edx : Uint4B
+0x034 Ebx : Uint4B
+0x038 Esp : Uint4B
+0x03c Ebp : Uint4B
+0x040 Esi : Uint4B
+0x044 Edi : Uint4B
+0x048 Es : Uint2B
+0x04a Reserved2 : Uint2B
+0x04c Cs : Uint2B
+0x04e Reserved3 : Uint2B
+0x050 Ss : Uint2B
+0x052 Reserved4 : Uint2B
+0x054 Ds : Uint2B
+0x056 Reserved5 : Uint2B
+0x058 Fs : Uint2B
+0x05a Reserved6 : Uint2B
+0x05c Gs : Uint2B
+0x05e Reserved7 : Uint2B
+0x060 LDT : Uint2B
+0x062 Reserved8 : Uint2B
+0x064 Flags : Uint2B
+0x066 IoMapBase : Uint2B
+0x068 IoMaps : [1] _KiIoAccessMap
+0x208c IntDirectionMap : [32] UChar
_KUSER_SHARED_DATA
kd> dt _KUSER_SHARED_DATA 0xffdf0000
ntdll!_KUSER_SHARED_DATA
+0x000 TickCountLow : 0x5a12
+0x004 TickCountMultiplier : 0xa03afb7
+0x008 InterruptTime : _KSYSTEM_TIME
+0x014 SystemTime : _KSYSTEM_TIME
+0x020 TimeZoneBias : _KSYSTEM_TIME
+0x02c ImageNumberLow : 0x14c
+0x02e ImageNumberHigh : 0x14c
+0x030 NtSystemRoot : [260] 0x43
+0x238 MaxStackTraceDepth : 0
+0x23c CryptoExponent : 0
+0x240 TimeZoneId : 0
+0x244 Reserved2 : [8] 0
+0x264 NtProductType : 1 ( NtProductWinNt )
+0x268 ProductTypeIsValid : 0x1 ''
+0x26c NtMajorVersion : 5
+0x270 NtMinorVersion : 1
+0x274 ProcessorFeatures : [64] ""
+0x2b4 Reserved1 : 0x7ffeffff
+0x2b8 Reserved3 : 0x80000000
+0x2bc TimeSlip : 0
+0x2c0 AlternativeArchitecture : 0 ( StandardDesign )
+0x2c8 SystemExpirationDate : _LARGE_INTEGER 0x0
+0x2d0 SuiteMask : 0x110
+0x2d4 KdDebuggerEnabled : 0x3 ''
+0x2d5 NXSupportPolicy : 0 ''
+0x2d8 ActiveConsoleId : 0
+0x2dc DismountCount : 0
+0x2e0 ComPlusPackage : 0xffffffff
+0x2e4 LastSystemRITEventTickCount : 0x3725c
+0x2e8 NumberOfPhysicalPages : 0x7ff8c
+0x2ec SafeBootMode : 0 ''
+0x2f0 TraceLogging : 0
+0x2f8 TestRetInstruction : 0xc3
+0x300 SystemCall : 0x7c92e4f0
+0x304 SystemCallReturn : 0x7c92e4f4
+0x308 SystemCallPad : [3] 0
+0x320 TickCount : _KSYSTEM_TIME
+0x320 TickCountQuad : 0
+0x330 Cookie : 0x4790370d