📄 sysenter.txt
字号:
作者:wowocock
;众所周知微软自XP后引进了FASTCALL SYSENTER,SYSEXIT来代替WIN2K下INT2E系统服务调用
;其优点是快速而且没有保留堆栈的开销,为了便于大家理解我写下面一个在WIN98下的例子
;来说明一下这2条指令的用法。ITNEL的手册上关于他们介绍的很详细,我简要说明一下
;SYSENTER是INTEL自P2后引进的快速从RING3~RING0的FASTCALL,从FAMILY 6,MODEL 3,
;STEP 3也就是从PII300以后引进的,这也是为什么WINXP需要PII300以上的原因。在使用SYSENTER
;之前必须定义好RING0 CS EIP ESP,通过设置相应MSR寄存器,由WRMSR指令来设定(必须在RING0层执行);
;通过将相应的寄存器地址号放入ECX中,WRMSR可以设置这些MSR寄存器,对应关系如下
;SYSENTER_CS_MSR 174H SYSENTER_ESP_MSR 175H SYSENTER_EIP_MSR 176H
;执行SYSENTER指令的系统必须满足 1:转换后的RING0代码段必须是FLAT,4GB的可读可执行
;的非一致代码段.2:转换后的RING0堆栈段必须是FLAT,4GB的可读可写向上扩展的数据段
;由于FASTCALL不保存任何返回的地址,所以在调用前你必须自己设定好,RING0代码段SELECTOR
;RING0堆栈段SELECTOR,RING3代码段SELECTOR,RING3堆栈段SELECTOR,必须在GDT中连续的排列
;所以在XP下相应的SELECTOR,必然是8H,10H,1BH,23H,必须将返回至RING3 EIP,ESP通过寄存器
;传递进RING0以便SYSEXIT返回使用,在SYSEXIT返回之前,EDX为RING3 EIP,ECX为RING3 ESP
;而相应的CS,SS,则由RING0 CS加上10H,18H来返回
;RING3~RING0
;1. 装载SYSENTER_CS_MSR 到CS 寄存器.
;2. 装载SYSENTER_EIP_MSR到 EIP寄存器。
;3. SYSENTER_CS_MSR+8 装载到SS寄存器
;4.装载SYSENTER_ESP_MSR 到ESP寄存器。
;5. 切换RING0.
;6. 清除 EFLAGS的 VM标志
;7. 执行RING0例程
;RING0~RING3
;1。SYSENTER_CS_MSR+16装载到 CS寄存器
;2. 将EDX的值送入EIP
;3. SYSENTER_CS_MSR+24 装载到SS寄存器
;4. 将ECX的值送入ESP
;5.切换回RING3
;6. 执行EIP处的RING3指令
;下面的例子在示范的基础上加了个小TRICK,就是在通过CALLGATE进RING0设置MSR寄存器的同时
;关掉了你机器上的缓存,然后你可以看看在没有缓存的情况下你的感觉如何,然后点击一下
;对话框,则经由SYSENTER指令进入RING0设定好的地址处恢复你CPU缓存,所以别担心,还有
;没有缓存的时候你的动作最好慢一点,不然会让你等的发疯的,呵呵。
.686p
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
sysenter macro
db 0fh,34h
endm
sysexit macro
db 0fh,35h
endm
CR0_CD EQU 040000000h ; Cache Disable bit of CR0
CR0_NW EQU 020000000h ; Not Write-through bit of CR0
.data
Ring0Cs dw 0ffffh,0,09b00h,0cfh
Ring0Ss dw 0ffffh,0,09300h,0cfh
Ring3Cs dw 0ffffh,0,0fb00h,0cfh
Ring3Ss dw 0ffffh,0,0f300h,0cfh
trR dw ?
tssRing0Esp dd ?
GdtLimit dw ?
GdtAddr dd ?
Callgt dq 0 ;call gate's sel:off
tmpCs dw ?
szTitle db "CPU info",0
msg db 100 dup (?)
Nightmare db "切换到其他窗口,尝尝没CACHE的滋味!",0
.code
Start:
mov ax,ds
test ax,4
jz Exit;winnt
xor eax,eax
cpuid
lea edi,msg
xchg eax,ebx
stosd
xchg eax,edx
stosd
xchg eax,ecx
stosd
invoke MessageBoxA,0,addr msg,addr szTitle,0
mov eax,1
cpuid
test edx,800h
jz Exit
mov eax,2
cpuid
SetSel:
sgdt GdtLimit
str word ptr trR
;-----------------------
; get the tr mes
;-----------------------
movzx esi,trR
add esi,GdtAddr
mov eax,[esi+2]
and eax,0ffffffh
mov ebx,[esi+4]
and ebx,0ff000000h
or eax,ebx
push dword ptr[eax+4]
pop dword ptr [tssRing0Esp]
movzx eax,GdtLimit
test al,1
jz @f
inc eax
@@:
sub eax,4*8
mov tmpCs,ax
add eax,GdtAddr
lea esi,Ring0Cs
mov edi,eax
mov ecx,4*8
rep movsb
SetMsr:
;-------------------------------------
; 在GDT中寻找空白表项来制造调用门
;-------------------------------------
mov esi,GdtAddr
movzx eax,GdtLimit
call Search_XDT
;esi==gdt Base
mov esi,dword ptr GdtAddr
push offset Ring0_SetMsr
pop word ptr [esi+eax+0]
pop word ptr [esi+eax+6] ;Offset
mov word ptr [esi+eax+2],28h
mov word ptr [esi+eax+4],0EC00h ;sel=28h and attribute ->386 call gate!
and dword ptr Callgt,0
mov word ptr [Callgt+4],ax
pushad
call fword ptr [Callgt] ;Ring0!
popad
mov dword ptr [esi+eax+0],0
mov dword ptr [esi+eax+4],0
invoke MessageBoxA,0,addr Nightmare,addr Nightmare,0
lea edx,Exit
mov ecx,esp
sysenter
Exit:
push 00000000h ; Exit program
call ExitProcess
Ring0_SetMsr:
mov ecx,174h
movzx eax,tmpCs
wrmsr
inc ecx
mov eax,tssRing0Esp
wrmsr
inc ecx
lea eax,Ring0Ip
wrmsr
mov eax,cr0 ; read CR0
or eax,CR0_CD ; set CD but not NW bit of CR0
mov cr0,eax ; cache is now disabled
wbinvd ; flush and invalidate cache
; the cache is effectively disabled at this point, but memory
; consistency will be maintained. To completely disable cache,
; the following two lines may used as well:
or eax,CR0_NW ; now set the NW bit
mov cr0,eax ; turn off the cache entirely
retf
Ring0Ip:
pushad
pushf ; save the flags
cli ; disable interrupts while we do this
mov eax,cr0 ; read CR0
and eax,0dfffffffh ; now set the NW bit
mov cr0,eax ; turn on the cache entirely
and eax,0bfffffffh ; set CD but not NW bit of CR0
mov cr0,eax ; cache is now Ensabled
popf ; restore the flags
mov eax,cr0
mov [esp+4*7],eax
popad
sysexit
Search_XDT proc near ;entry esi==Base of Ldt or GDT
;Eax==Limit
pushad
mov ebx,eax
mov eax,8 ; skipping null selector
@@1:
cmp dword ptr [esi+eax+0],0
jnz @@2
cmp dword ptr [esi+eax+4],0
jz @@3
@@2:
add eax,8
cmp eax,ebx
jb @@1 ;if we haven't found any free GDT entry,
;lets use the last two entries
mov eax,ebx
sub eax,7
@@3:
mov [esp+4*7],eax ; return off in eax
popad
ret
Search_XDT endp
end Start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -