Introduction à l’exploitation Windows | Théorie
/!\ Attention vous trouverez ici beaucoup d’aproximation et de fautes d’orthographes: cause (je suis nul en ortho oui mais pas que) cet article est un “troll” avec un message secret ! Essaye de le retrouver :) Bonne chance ! /!\ Bonjour à tous ! On se retrouve pour un article toujours basique. En effet aujourd’hui on va parler théorie.
Quand on commence le pwn on se tourne plutôt vers l’exploitation sous Linux et les challenges n’en manquent pas ! Ducoup on oublie souvent Windows qui est plus present sur le marché.
Les sécurité sous windows
Vous devez sans doute connaitre l’ASLR, la NX, la PIE ou le stack canary. Ces protections sont aussi presente sur Windows mais sous un autre nom et quelque petites difference.
- Le DEP: Data Execution Prevention est le NX pour Windows. Pas de difference
- L’ASLR: Adress Space Layout Randomization à le même nom sous Windows mais attention ! Trois différence: l’ASLR n’est chargé qu’au démarrage ce qui veut dire que si le programme vicitme est redémarré les addresse ne change pas. Vous pouvez donc ignorer cette protection pour un exploit local mais si vous voulez créer un exploit qui marche partout vous devrez prendre e compte cette sécurité. Deuxième particuliarité: chaque programme peut être compilé avec ou sans ASLR (l’ASLR n’est plus presente sur tout le système mais depend du binaire). Troisième particuliarité: l’ASLR windows = ASLR + PIE, non seulement la heap et la stack sont randomizé par l’ASLR Windows mais les bibliothèque sont mappé à des addresse différentes aussi.
- Le GS, c’est un stack canary qui fonctionne comme le canary sur Linux un “cookie” est placé à la fin du buffer et ont vérifie si celui ci ne change pas, s’il change le programme est arreté pour éviter l’exploitation
Délivré des format strings !
Bon, les formats strings … Comment dire que c’est juste du CTF et rien d’autre vous ne trouverez jamais un format string dans la vie réelle. Les formats strings peuvent être utile parfois: un programme avec la PIE, les format strings permettent un Memory Leak ce qui peut simplifier l’exploit sauf qu’il ne faut pas rêver cette vulnerablilité est très très peu présente. Alors revenons au sujets sous Windows les format strings n’existent tous simplement pas ! Pourquoi ? Il y’a longtemps une format string trainait sur Windows, Microsoft à juste décider qui’il ne faut pas patcher cette vulnérabilité et qu’il faut juste désactiver le formateur %n qui est obligatoir pour l’exploitation d’un format string.
Pour resumer: Sous Windows vous n’aurez jamais à exploiter cette vulnérabilité !
Note sur les shellcodes
Vous n’êtes pas sans savoir qu’un shellcode doit executer un syscall: le plus souvent execve() voici par exemple le code d’un shellcode Linux pioché sur zeste du savoir:
bits 32
shellcode:
; On réinitialise les registres
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
; Appel système 11
mov al, 11
; ebx doit contenir un pointeur vers //bin/sh
; donc on construit la chaîne sur la pile
push ebx ; ebx = 0, donc on a notre null-byte
push `n/sh`
push `//bi`
; A ce moment là, esp pointe sur `//bin/sh\0`
mov ebx, esp ; on met dans ebx l'adresse de notre chaîne.
; ecx et edx valent déjà zéro (NULL)
; donc nous sommes tranquilles :)
; On exécute l'appel système
int 0x80
; Et on quitte proprement
; (cf. shellcode Hello World)
mov al, 1
xor ebx, ebx
int 0x80
Et Windows dans tout ça ? vous voyez le int 0x80 (cette instruction execute le syscall dont le numéro est eax (al ici pour éviter les nullbyte) le numero de execve est 11 en x86. Eh bien sur Windows ont pas les syscalls: de base ont ne peut pas créer de programme executant des syscalls directement, on doit passer par l’API WinAPI pour nos drivers ect ..
Petite parenthèse importante sur la WinAPI: Pour faire simple cette API appele des focntion interne de la NtAPI (qui n’est pas documenté) qui fait les appels système. NtAPI est implémenté dans un libraire dll (on reviendra sur ça dans la suite) ntdll.dll. Les fonction documenté de WinAPI se trouvent majortairement dans kernel32.dll. Vous comprendrez par la suite l’importance de kernel32.dll, sachez juste qu’il est utilisé par tout les executable windows (PE) même un simple Hello World. On va finir cette partie sur cela: coder des shellcodes sur Windows est plus compliqué que sur linux. En effet il faut passer par WinAPI ou NtAPI (non documenté) pour le faire.
PE et DLL
D’abord voyons ce que signifie ces deux sigles: -PE: Portable Executable -DLL: Dinamyc Linked Library
Continuons sur les Portable Executable: Ce sont des fichier executable (.exe) dérivé du format COFF (Mais si ! Common Object File Format ! Le premier format de fichier executable pour Unix System V) Comment se structure le format ? Vous savez sans doute qu’un ELF est constituer de differents segment .text .rodata .bss ect … Bah maitenant on va voir comment ça se passe pour les PE:
- En tête MZ-DOS ou en tête RealMode : C’est cette partie du PE qui indique justement que le fihcier est un PE, souvent pour les executable windows ou voit “This program cannot be run in DOS mode” dans cette en tête.
- Segment DOS
- Entête PE
- Table des segments
- Et la on a les differentes sections.
Bon revenons sur les DLL, ou Dynamic Link Library En fait c’est tout simple, vous vous rappelez libc.so.6 que vous avez surement dû rencontrer pour le developpemetnt d’une rop chain ou autre … Peut-être savez vous que quand vous faites printf(“Hello World \n”); en C vous executer une fonction de libc.so.6. Sous Linux les libraire ont une extension .so eh bien sous Windows c’est .dll.
Peut être que vous avez dejas coder un programme en reseau sous Windows par exemple ? Au debut vous avez dû inclure winsock2 nan ?
#include <winsock2.h>
Eh bien vous avez donc utiliser winsock32.dll ! Voila pour les PE et le DLL
Et si on codait un peu avec WinAPI ?
Peut-être avez vous remarquer des code sur github qui commence par:
#include <windows.h>
Que peut donc bien être ce windows.h ? C’est juste la WinAPI ! Alors commençons on va juste voir les bases !
Attention à être boulversé vous vous rappelez du main qui vous suis depuis si longtemps ? Eh bien il va maintenant disparaitre. Voici le code minimal pour un programme WinAPI
#include <windows.h>
int WinMain (
HINSTANCE cetteInstance,
HINSTANCE precedenteInstance,
LPSTR lignesDeCommande,
int modeDAffichage)
{
return 0;
}
Vous devrez mettre votre code entre entre le {
et return 0; }
Mais d’abord analysons notre code (et ça sera tout pour cet article, je continuerai pour la WinAPI si les votes des lecteurs le veulent sur le discord.)
On voit que main est remplacé par WinMain qui est toujours un int, maintenant ce qui peut semblerbizarre c’est les arguments:
- HINSTANCE cetteInstance : ça c’est votre instance, fin l’instance de votre programme plutôt c’est à dire une sorte de quelque chose qui regroupe les information sur votre programme.
-
HINSTANCE precedenteInstance: La bah c’est juste l’instance précédente
-
LPSTR lignesDeCommande: Ici vous avez le argv vous vous rappelez celui par laquelle l’utilisateur peut passer des arguments a votre programme, c’est un peu plus compliqué tout du moins, je vous expliquerai plus tard
- int modeDAffichage: Comme vous l’avez deviné si vous êtes perspicace c’est le mode d’affichage
Sur ce, à la prochaine !