sysenter & int 2e

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)操作系统没有使用12环
                 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 0xffdf00000x7ffe0000)的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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值