sysenter & int 2e

MSR register

sysenter enters the 0 ring and directly obtains the value of the register from the MSR register
The interrupt gate enters the 0 ring and needs to check the memory (TSS\IDT) to obtain the value of the register

MSR address
IA32_SYSENTER_CS 174H
IA32_SYSENTER_ESP 175H
IA32_SYSENTER_EIP 176H

Can read and write through RDMSR/WRMSR

rdmsr 174 //View cs
rdmsr 175 //View esp
rdmsr 176 //View eip

ss = cs + 0x8

_KiSystemService

How to find this function

Interrupt gate entry, the interrupt number is 0x2e

kd> dq 8003f400 + 2e*8
8003f570 804dee00`0008f631 804e8e00`0008297c
8003f580 806f8e00`00085d54 89938e00`0008371c
8003f590 804d8e00`0008ed04 804d8e00`0008ed0e

The address where we found the EIP is: 804df631
Find out what module the function is in:

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\\
toskrnl.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


You can see that the function address 804df631 is in this module ntoskrnl.exe 0x804df631 - 0x804d8000 = 0x7631
Add its imagebase and you can locate it

Reverse analysis

.text:00407631 _KiSystemService: ; DATA XREF: INIT:005DD660↓o
.text:00407631 push 0 ; Error code, if an exception occurs, the CPU will automatically fill it, if not, you need to fill it with 0
.text:00407633 push ebp
                push ebx
                push esi
                push edi
                push fs
                mov ebx, 30h
                mov fs, ebx ; GDT table 0x30 segment descriptor loaded into fs register
                assume fs:nothing


                 push dword ptr ds:0FFDFF000h ; NT_TIB (ExceptionList) exception handling linked list
                 mov dword ptr ds:0FFDFF000h, 0FFFFFFFFh ; set the ExceptionList of KPCR to -1
                 mov esi, ds:0FFDFF124h ; esi = get the address of CurrentThread from KPCR
                 push dword ptr [esi + 140h] ; Get PreviousMode from the current thread and put it in _KTrap_Frame
                 sub esp, 48h ;Promote the stack, this time esp => _KTrap_Frame
                 mov ebx, [esp + 6Ch] ; the CS value of ring 3
                 and ebx, 1 ;cs and 1 => judgment (ring 3 = 1) (ring 0 = 0) the operating system does not use rings 1 and 2
                 mov [esi + 140h], bl ; set the previous mode of the current thread ETHREAD
                 mov ebp, esp ; ebp = esp = _KTrap_Frame
                 mov ebx, [esi + 134h] ; The address of the _KTrap_Frame structure of THREAD
                 mov [ebp + 3Ch], ebx ; store the old _KTrap_Frame into the Edx of the new _KTrap_Frame
                 mov [esi + 134h], ebp ; store the address of the current _KTrap_Frame in the _KTrap_Frame attribute of ETHREAD

                 cld
                 mov ebx, [ebp + 60h] ;3-ring ebp
                 mov edi, [ebp + 68h] ; eip of ring 3
                 mov [ebp + 0Ch], edx ; 3 ring parameter pointers

                 mov dword ptr [ebp + 8], 0BADB0D00h ; this is not clear, you can leave a message in the comment area if you know it
                 mov [ebp + 0], ebx ; backed up a 3-ring ebp
                 mov [ebp + 4], edi ; backup a 3-ring eip

                 test byte ptr [esi + 2Ch], 0FFh ; DebugActive to judge whether the current thread is in debugging state
                 jnz loc_40752C ;Jump if not equal If it is in the debugging state, it will enter and save the registers related to the debugging

.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 ;Get the function number
.text:00407783 shr edi, 8 ;
.text:00407786 and edi, 30h ; edi = 0 (gui function = 0x10)
.text:00407789 mov ecx, edi ; ecx = 0 (gui function = 0x10)
.text:0040778B add edi, [esi + 0E0h] ; ServiceTable points to the base address of the system service table
.text:00407791 mov ebx, eax ; ebx = function number
.text:00407793 and eax, 0FFFh ; Only the last 12 digits of the system call number are reserved
.text:00407798 cmp eax, [edi + 8] ; compare limit with eax, whether it exceeds the range
.text:0040779B jnb loc_4074E2 ;Jump if greater than or equal to, generally it will not exceed
.text:004077A1 cmp ecx, 10h ; determine what function
.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 plus one
.text:004077C6 mov esi, edx ;edx is the address of the parameter of the function
.text:004077C8 mov ebx, [edi + 0Ch] ;ebx = the address of the parameter number table of the function
.text:004077CB xor ecx, ecx ;ecx = 0
.text:004077CD mov cl, [eax + ebx] ; At this time, cl obtains the number of parameters
.text:004077D0 mov edi, [edi] ;edi = the address of the function address table
.text:004077D2 mov ebx, [edi + eax*4] ;ebx = function address, eax is index
.text:004077D5 sub esp, ecx ;Upgrade the stack, which is the size of the parameter
.text:004077D7 shr ecx, 2 ; ecx = ecx / 4 the number of cycles
.text:004077DA mov edi, esp ; edi = stack top, startAddress of parameter copy
.text:004077DC cmp esi, ds:MmUserProbeAddress ; Determine whether the address range of the parameters of the third ring is out of bounds
.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 ; Copy parameters to ring 0 environment
.text:004077EA call ebx ; call function
-------------------------------------------------- -------------------------------------------------- ------
loc_407990:
; CODE XREF: sub_407631 + 1B1↑j
.text:00407990 test byte ptr [ebp + 6Ch], 1
.text:00407994 jz loc_4077E8 ; Jump if it is ring 0
.text:0040799A mov eax, 0C0000005h
.text:0040799F jmp loc_4077EC


KiFastCallEntry

sysenter enters the 0 ring
rdmsr 176 can view the EIP to be executed

.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] ; This is the data area shared by ring 0 and ring 3: dt _KUSER_SHARED_DATA 0xffdf0000 (0x7ffe0000) SystemCall value
.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
;Quick call, don't go to tss to find the value of esp0, but directly go to the msr register to get cs, esp, eip
-------------------------------------------------- -------------------------------------------------- ------

; eip points to the following code
; The previous code requires us to assign multiple
; Calling the system service table later is the same operation as above

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 ; Check the segment descriptor of GDT table 0x30 ffc093df`f0000001
; Data segment, readable and writable
; fs.Base = ffdff000
; fs.Limit= 1 (unit 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 = Esp0 of TSS
.text:00407706 push 23h ; SS of ring 3
.text:00407708 push edx ; edx is 3-ring esp
.text:00407709 pushf ; eflags for ring 3
.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 ;CS of ring 3
.text:00407717 push dword ptr ds:0FFDF0304h ;EIP of ring 3
.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

View how many cores are currently available

dt KeNumberProcessors

View KPCR list

 dd KiProcessorBlock

Subtracting 0x120 is the address of KPCR
 

_KTrap_Frame

When you come in, go here
There is only one core in TSS. When switching threads, it needs to change TSS to ensure that when the current thread enters ring 0, it can find the correct _KTrap_Frame structure of the current thread
One thread one _KTrap_Frame

kd> dt _KTrap_Frame
ntdll!_KTRAP_FRAME
    + 0x000 DbgEbp : Uint4B
    + 0x004 DbgEip : Uint4B
    + 0x008 DbgArgMark : Uint4B
    + 0x00c DbgArgPointer : Uint4B ; 3 ring parameter pointers
    + 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 ; Previous mode, indicating whether the program is called by ring 0 or ring 3
    + 0x04c ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD ; store the current thread kernel exception list, referred to as SEH
    + 0x050 SegFs : Uint4B
    + 0x054 Edi : Uint4B
    + 0x058 Esi : Uint4B
    + 0x05c Ebx : Uint4B
    + 0x060 Ebp : Uint4B
    + 0x064 ErrCode : Uint4B ; <- esp0
    + 0x068 Eip : Uint4B ; Call the interrupt gate to enter _KiSystenService , it will push 5 pointers eip cs flags esp ss, before pushing, the value of esp will be replaced with esp0 stored in TSS
    + 0x06c SegCs : Uint4B
    + 0x070 EFlags : Uint4B
    + 0x074 HardwareEsp : Uint4B
    + 0x078 HardwareSegSs : Uint4B ; TSS memory > location pointed to by ESP0
    + 0x07c V86Es : Uint4B ; used in virtual mode
    + 0x080 V86Ds : Uint4B ; virtual mode use
    + 0x084 V86Fs : Uint4B ; used in virtual mode
    + 0x088 V86Gs : Uint4B ; used in virtual mode

_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