?? sysenter.txt
字號(hào):
作者:wowocock
;眾所周知微軟自XP后引進(jìn)了FASTCALL SYSENTER,SYSEXIT來代替WIN2K下INT2E系統(tǒng)服務(wù)調(diào)用
;其優(yōu)點(diǎn)是快速而且沒有保留堆棧的開銷,為了便于大家理解我寫下面一個(gè)在WIN98下的例子
;來說明一下這2條指令的用法。ITNEL的手冊(cè)上關(guān)于他們介紹的很詳細(xì),我簡(jiǎn)要說明一下
;SYSENTER是INTEL自P2后引進(jìn)的快速從RING3~RING0的FASTCALL,從FAMILY 6,MODEL 3,
;STEP 3也就是從PII300以后引進(jìn)的,這也是為什么WINXP需要PII300以上的原因。在使用SYSENTER
;之前必須定義好RING0 CS EIP ESP,通過設(shè)置相應(yīng)MSR寄存器,由WRMSR指令來設(shè)定(必須在RING0層執(zhí)行);
;通過將相應(yīng)的寄存器地址號(hào)放入ECX中,WRMSR可以設(shè)置這些MSR寄存器,對(duì)應(yīng)關(guān)系如下
;SYSENTER_CS_MSR 174H SYSENTER_ESP_MSR 175H SYSENTER_EIP_MSR 176H
;執(zhí)行SYSENTER指令的系統(tǒng)必須滿足 1:轉(zhuǎn)換后的RING0代碼段必須是FLAT,4GB的可讀可執(zhí)行
;的非一致代碼段.2:轉(zhuǎn)換后的RING0堆棧段必須是FLAT,4GB的可讀可寫向上擴(kuò)展的數(shù)據(jù)段
;由于FASTCALL不保存任何返回的地址,所以在調(diào)用前你必須自己設(shè)定好,RING0代碼段SELECTOR
;RING0堆棧段SELECTOR,RING3代碼段SELECTOR,RING3堆棧段SELECTOR,必須在GDT中連續(xù)的排列
;所以在XP下相應(yīng)的SELECTOR,必然是8H,10H,1BH,23H,必須將返回至RING3 EIP,ESP通過寄存器
;傳遞進(jìn)RING0以便SYSEXIT返回使用,在SYSEXIT返回之前,EDX為RING3 EIP,ECX為RING3 ESP
;而相應(yīng)的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標(biāo)志
;7. 執(zhí)行RING0例程
;RING0~RING3
;1。SYSENTER_CS_MSR+16裝載到 CS寄存器
;2. 將EDX的值送入EIP
;3. SYSENTER_CS_MSR+24 裝載到SS寄存器
;4. 將ECX的值送入ESP
;5.切換回RING3
;6. 執(zhí)行EIP處的RING3指令
;下面的例子在示范的基礎(chǔ)上加了個(gè)小TRICK,就是在通過CALLGATE進(jìn)RING0設(shè)置MSR寄存器的同時(shí)
;關(guān)掉了你機(jī)器上的緩存,然后你可以看看在沒有緩存的情況下你的感覺如何,然后點(diǎn)擊一下
;對(duì)話框,則經(jīng)由SYSENTER指令進(jìn)入RING0設(shè)定好的地址處恢復(fù)你CPU緩存,所以別擔(dān)心,還有
;沒有緩存的時(shí)候你的動(dòng)作最好慢一點(diǎn),不然會(huì)讓你等的發(fā)瘋的,呵呵。
.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中尋找空白表項(xiàng)來制造調(diào)用門
;-------------------------------------
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
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -