Archive for février 4th, 2007

SYSENTER, stepping into da ring0

Vous avez sans doute déjà rencontré cette instruction en tracant sous Olly sans vraiment trop vous y intéressé et pourtant c’est une des plus importante de votre OS. Que peut-elle bien faire pour être si importante et pourquoi elle semble ne rien faire. Ivanlef0u votre détective préféré s’est penché sur cette affaire.

Dans un call à une API native comme par exemple ZwCreateFile on peut voir :

7C91D682 >  B8 25000000     MOV EAX,25
7C91D687    BA 0003FE7F     MOV EDX,7FFE0300
7C91D68C    FF12            CALL NEAR DWORD PTR DS:[EDX] //EDX pointe sur 0x7C91EB8B
7C91D68E    C2 2C00         RET 2C

On arrive ici avec le call
7C91EB8B >  8BD4            MOV EDX,ESP
7C91EB8D    0F34            SYSENTER
7C91EB8F    90              NOP
7C91EB90    90              NOP
7C91EB91    90              NOP
7C91EB92    90              NOP
7C91EB93    90              NOP
7C91EB94 >  C3              RET

En fait l’instruction SYSINTER à pour rôle de de faire un appel système. Dans notre exemple le code qui sera lancé sera celui de NtCreateFile de ntoskrnl.exe. Bon c’est cool tout ca mais comment on sait qu’on appel NtCreateFile, hé bien vous voyez le « mov eax, 0×25″, 0×25 correspond à l’indice de la fonction dans la SSDT (System Service Descriptor Table), une sorte de table d’exportation pour les fonctions systèmes.

Par contre l’appel à la SSDT n’est pas fait directement par SYSENTER, une routine du noyau (KiSystemService) se charge de retrouver l’adresse de la fonction dans la SSDT. Alors comment fait donc SYSENTER pour jumper sur KiSystemService ? En fait elle utilise les MSR (Model Specific Register), ceux-ci servent à des opérations spéciales sur le processeur. L’intruction SYSENTER utilise les 3 suivants :
- MSR_SYSENTER_CS 0×00000174
- MSR_SYSENTER_ESP 0×00000175
- MSR_SYSENTER_EIP 0×00000176
Voir le manuel « Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2B Instruction Set Reference, N-Z »
Le MSR_SYSENTER_EIP contient l’adresse de la fonction KiSystemService (0x0804de6f0 chez moi), on trouve dans le MSR_SYSENTER_ESP l’adresse de notre nouvelle Kernel stack (0x0f88ab000 chez moi) enfin le nouveau segment de code MSR_SYSENTER_CS celui-ci n’a pas vraiment d’utilité.

Avant les appels systèmes étaient effectué avec l’interruption int 0x2E, SYSENTER la remplacé pour des raisons de rapididé.

Alors imaginons qu’on puisse modifier ces fameux MSR :), on pourrait donc faire exécuter notre code en ring0 !
He bien cela est possible ! Avec l’API natice NtSystemDebugControl on peut lire et écrire les MSR.
On lui donne une petite structure :

typedef struct _MSR_STRUCT {
DWORD MsrNum;            // MSR number
DWORD NotUsed;            // Never accessed by the kernel
DWORD MsrLo;            // IN (write) or OUT (read): Low 32 bits of MSR
DWORD MsrHi;            // IN (write) or OUT (read): High 32 bits of MSR
} MSR_STRUCT, *PMSR_STRUCT;

Structure formée par Reversing du ntoskrnl evidemment …

Apràs il suffit de sauvegarder le MSR_SYSENTER_EIP courant puis on lui dit de pointer sur le morceaux de code que l’on veut lancer en ring0, on appel SYSENTER et hop ! Pour quitter on n’oublie pas de le restaurer bien sur !!!!

Bon clairement il faut codé un shellcode ring0, le mien ne fait que retrouver l’adresse de la structure ETHREAD courante mais au final on peut faire ce qu’on veut dans notre noyau, suffit de s’y mettre :}

Voici le code avec pas mal d’infos dedans et le binaire.
http://ivanlef0u.fr/repo/MSR.rar
Have fun.

4 comments février 4th, 2007


Calendar

février 2007
L Ma Me J V S D
« jan   mar »
 1234
567891011
12131415161718
19202122232425
262728  

Posts by Month

Posts by Category