SMEP bypass on Win7

Supervisor Mode Execution Protection KERNEL_AREA_EXEC != USER_ARE_SHELLCODE

Intel manual
SMEP-Enable Bit (bit 20 of CR4) — Enables supervisor-mode execution prevention (SMEP) when set. See Section 4.6, “Access Rights”.

For accesses in supervisor mode (CPL < 3):
Instruction fetches.
• For 32-bit paging or if IA32_EFER.NXE = 0, access rights depend on the value of CR4.SMEP:
— If CR4.SMEP = 0, instructions may be fetched from any linear address with a valid translation.
— If CR4.SMEP = 1, instructions may be fetched from any linear address with a valid translation for which the U/S flag (bit 2) is 0 in at least one of the paging-structure entries controlling the translation.
• For PAE paging or IA-32e paging with IA32_EFER.NXE = 1, access rights depend on the value of CR4.SMEP:
— If CR4.SMEP = 0, instructions may be fetched from any linear address with a valid translation for which the =XD= flag (bit 63) is 0 in every paging-structure entry controlling the translation.
— If CR4.SMEP = 1, instructions may be fetched from any linear address with a valid translation for which (1) the U/S flag is 0 in at least one of the paging-structure entries controlling the translation; and (2) the =XD= flag is 0 in every paging-structure entry controlling the translation.

For accesses in user mode (CPL = 3):
Instruction fetches.
• For 32-bit paging or if IA32_EFER.NXE = 0, instructions may be fetched from any linear address with a valid translation for which the U/S flag is 1 in every paging-structure entry controlling the translation.
• For PAE paging or IA-32e paging with IA32_EFER.NXE = 1, instructions may be fetched from any linear address with a valid translation for which the U/S flag is 1 and the =XD= flag is 0 in every paging-structure entry controlling the translation.

PTE flags:

Bit 0 (P) is the Present flag.
Bit 1 (R/W) is the Read/Write flag.
Bit 2 (U/S) is the User/Supervisor flag.

#################first method(I’m not sure :P)###################
Nevertheless there are Intel Instruction set documentation, STAC instruction
Set AC Flag in EFLAGS Register

Description
Sets the AC flag bit in EFLAGS register. This may enable alignment checking of user-mode data accesses. This allows explicit supervisor-mode data accesses to user-mode pages even if the SMAP bit is set in the CR4 register. WTF????

##secondary method
ROP (Return oriented programming)

nt!KiLoadMTRR+0x120:
8312ebae 0f09 wbinvd
8312ebb0 837c241400 cmp dword ptr [esp+14h],0
8312ebb5 0f20d8 mov eax,cr3
8312ebb8 0f22d8 mov cr3,eax
8312ebbb 8b442418 mov eax,dword ptr [esp+18h]
8312ebbf 0f22c0 mov cr0,eax
8312ebc2 7407 je nt!KiLoadMTRR+0x13d (8312ebcb)

nt!KiLoadMTRR+0x136:
8312ebc4 8b44241c mov eax,dword ptr [esp+1Ch] &amp;amp;lt;=========== 
8312ebc8 0f22e0 mov cr4,eax &amp;amp;lt;=========== 

nt!KiLoadMTRR+0x13d:
8312ebcb 853548e9f782 test dword ptr [nt!KeFeatureBits (82f7e948)],esi
8312ebd1 7508 jne nt!KiLoadMTRR+0x14d (8312ebdb)

nt!KiLoadMTRR+0x145:
8312ebd3 8d4738 lea eax,[edi+38h]
8312ebd6 e815000000 call nt!KiLockStepExecution (8312ebf0)

nt!KiLoadMTRR+0x14d:
8312ebdb 807c240b00 cmp byte ptr [esp+0Bh],0
8312ebe0 7401 je nt!KiLoadMTRR+0x155 (8312ebe3)

nt!KiLoadMTRR+0x154:
0: kd> !pte 0x8312ebc8
                    VA 8312ebc8
PDE at C06020C0            PTE at C0418970
contains 00000000030009E3  contains 0000000000000000
pfn 3000      -GLDA--KWEV <=== kernel space  LARGE PAGE pfn 312e
Advertisements

System Service Dispatching

System Service Dispatch ∨ (sysCALL) OS tərəfindən təyin olunmuş kernel əsaslı funksiyaları işə salır (triggered)

(pentium II əvvəlindəki x86 prosesorlar int 0x2e təlimatı əsasında trap handler işə salırdı)

Windows Based

Trap Handler – Trap – interrupt və yaxud exception yarandıqda icrada olan threadi nəzarətə götürür və sabit bir yerə (routine və s.) kontrolun köçürülməsi əməliyyatını yerinə yetirir.

Hardware/Software Interrupts --- > trap handler kontrolu INTERRUPT Service Routines (ISR)-ə transfer edir.
Hardware/Software Exceptions --- > trap handler kontrolu Exception Dispatchers (ED)-ə transfer edir.
System service calls --- > trap handler kontrolu system service function (SSF)-ə transfer edir.
Trap handler

Interrupt ————— > INTERRUPT SERVICE ROUTINE

System service call ————— > SYSTEM SERVICES

Hardware exceptions|Software Exceptions –> EXCEPTION dispatcher —> Exception handlers

Virtual addr exceptions —- > Virtual memory manager’s pager

Hardware və software exception və interrupt generasiya edə bilir. Misal üçün: ‘Bus error exception’ hardware probleminƏ görə yaranır. ‘divide-by-zero exception’ isə sofware probleminə görə yaranır. Həmçinin I/O cihazları interrupt generasiya edə bilər. Kernel özü də bir software interrupt verə bilər.

Yuxarıdakı schema-da kernel trap işləyicileri interrupts,exceptions və system service çağırışlarını göndərir. System service dispatch, System service dispatchingdə təyin olunmuş təlimatının(instruction) icrası nəticəsində işə düşür.

System Service Dispatching

x86 prosessorlarında Pentium II-dən əvvəl Windows int 0x2e (46 onluq) təlimatı (instruction) istifadə edirdi. Bu interrupt vektoru trap ilə nəticələnir. Windows IDT-da (Interrupt Descriptor Table) 46cı entry SSD-ni(System Service dispatcher) göstərir.

Fig 1.0

lkd> !idt 2e

Dumping IDT: 80b95400

898023cf0000002e:    82e9822e nt!KiSystemService

Trap icrada olan thread-in kernel mode keçidinə və system service dispatcher-a daxil olmasına səbəb olur. EAX prosessor registerinə daxil edilmiş rəqəmli arqument istənilən system servis nömrəsini göstərir. İstifadəçi moduna geri dönmək üçün, system service dispatcher iret (interrupt return instruction) istifadə edir.

x86 Pentium II və yüksək prosessorlarda, Windows systen təlimatı(instruction) istifadə edir, İntel bunu xüsusi olaraq daha sürətli system service dispatch üçün təyin edib. Windows boot zamanı kernel system service dispatch routine adresini MSR (Machine specific register-da saxlayır. System servis nömrəsi EAX prosessor registerində qeyd edilir. Bu təlimatın icrasın kernel moda keçişə və system service dispatcher işə düşməsinə səbəb olur. User moda qayitmaq üçün isə sysexit təlimatı istifadə olunur.

  1. Fig 1.0 göstərildiyi kimi 32 bit kernel debugger-da sistemlərdə system call dispatcher handler !idt 2eilə göstərilə bilir.
  2. Handler-in sysenter versiyasına baxmaq üçün rdmsr təlimatından istifadə edərək MSR 0x176 registerindən oxumaq mümkündür.
lkd> rdmsr 176
msr[176] = 00000000`82e5b300
lkd> ln 00000000`82e5b300
(82e5b300)   nt!KiFastCallEntry

SharedUserData strukturunda doğru kod üçün bir pointer saxlanaraq istifadə etmək üçün uyğun system call kodunu təyin edər. User modda NtReadFile üçün system service code buna bənzəyir.

lkd> u ntdll!NtReadFile
ntdll!NtReadFile:
77125700 b811010000      mov     eax,111h
77125705 ba0003fe7f      mov     edx,offset SharedUserData!SystemCallStub (7ffe0300)
7712570a ff12            call    dword ptr [edx]
7712570c c22400          ret     24h

System service number 0x111-dir(273 onluq), və kernel tərəfindən təyin edilmiş system dispatch code call təlimatı icra edir, onun pointeri 0x7ffe0300 adresindədir. (Bu KUSER_SHARED_DATA strukturununSystemCallStub member-nə qarşılıq gəlir, bu da 0x7FFE0000 adresindən başlayır)

#define MM_SHARED_USER_DATA_VA      0x7FFE0000

#define USER_SHARED_DATA ((KUSER_SHARED_DATA * const)MM_SHARED_USER_DATA_VA)
lkd> u 771264f0
ntdll!KiFastSystemCall:
771264f0 8bd4            mov     edx,esp
771264f2 0f34            sysenter

E.g 1.0-da göstərildiyi kimi, kernel system service dispatch table system service (servis) məlumatlarını tapmaq üçün system call number istifadə edir.

E.g 1.0:

User Mode ————-> system call —-(transition to kernel mode)—- > kernel mode

kernel mode: System service dispatcher (2) ——> System service dispatch table (2):

0 System service 0
1 System service 1
2 System service 2

Bu table Interrupt dispatch table bənzəyir ancaq hər giriş system service əvəzinə interrupt-handling routine göstərir.

System service dispatcher KiSystemService, işə salanın argumentlərini user mod stack-dən kernel stack-ə moda copy edir daha sonra system service icra edilir. Kernel nə qədər stack byte olduğunu bilmək üçün second table istifadə edərək kopyalama tələb edir, bu table argument table adlanır.

typedef struct _SYSTEM_SERVICE_TABLE {
    PVOID *ServiceTable; //System Service Dispatch Table
    PVOID *CounterTable; //istifadə edilmir
    ULONG ServiceLimit; // SSDT table dəyərlərinin sayı
    PUCHAR ArgumentTable; // Dispatch table içindəki ki routine-lər üçün argumentləri saxlayır.
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;

reference kimi bir şəkildə verirəm:

(ServiceTable this the array of function pointers to kernel routines)

lkd> dps !KeServiceDescriptorTable
82f809c0  82e876f0 nt!KiServiceTable
82f809c4  00000000 //not used
82f809c8  00000191 //servicelimit
82f809cc  82e87d38 nt!KiArgumentTable

Sistem servisinə daxil edilmiş arqumentlər istifadəçi sahəsindəki buferdədirsə. Kernel-moda kod kopyalamadan öncə giriş imkanı üçün bu bufer problanmalıdır (yoxlanılmalıdır). Bu problama yalnız threadin previous modu user mode təyin edildikdə həyata keçirilir. Previous mode kernelin thread üzərində trap handler icra edildiyində və daxil olan istisnanın,trap,və yaxud syscall (sistem çağırışının) imtiyaz səviyyəsini müəyyən etmək üçün saxladığı bir dəyərdir (kernel və yaxud user). Optimallaşdırma üçün isə system çağırışının driver və yaxud kernel modun özündən gəldiyi halda probing (yoxlama) və capturing parametrləri nəzərə alınmır və bütün parametrlər etibarlı kernel mod buferlərinə işarə edilir. Kernel mode-da system çağırışları edə bilir. Hər sistem çağırışı üçün kod kernel modda olduğundan və caller kernel modda olduğu üçün siz burada interruptsysenter əmıliyyatlarına ehtiyyac olmadığını görə bilərsiniz. Driver və yaxud kernel yalnız tələb olunan funksiyanı birbaşa işə sala bilər.