阅读:1677回复:0
看wowocock的技术文章
SYSENTER简介及相关例子
by wowocock1/CVC.GB ;众所周知微软自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 |
|
|