Blabla malware et heaven's gate
UNE PRÉSENTATION SPONSO par les bonbons chiantos
(ça parle de malware tout ça tout ça, prenez une bière, ça va démarrer)
Whoami
- @N0fix sur Twitter
- Noflex dans la vraie vie
- Patron de la DGSE
- Henri Duflot
- OSCP
- "Orga" FCSC
- J'ai fais l'ENSIBS (surprise)
- Quand je dis NO vous dites FIX
Vous avez dit malware?
- Import par hash
- Heaven's gate / code segment
Prez en franglais, déso monsql
Imports par hash?
Imports par hash?
Tout la prez est sur windows
- example avec puts avec MessageBox
- "la folle histoire de puts" (ou "on voulait de l'argent, fait taper un croc stp")
Partie 1 : Import par hash
Imports par hash?
Vous avez déjà compilé un truc?
#include <stdio.h>
#include <stdlib.h>
int main()
{
puts("Boussole ce soir !");
return EXIT_SUCCESS;
}
Imports par hash?
Vous avez déjà compilé un truc?
Partie 1 : Import par hash
Partie 1 : Import par hash
Partie 1 : Import par hash
Partie 1 : Import par hash
Partie 1 : Import par hash
Quand on veut pas compiler avec les imports ?
Partie 1 : Import par hash
L'autre méthode du shlag
Partie 1 : Import par hash
L'autre méthode du shlag
#include <stdlib.h>
#include <Windows.h>
typedef int(WINAPI* MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
int main()
{
HMODULE h = LoadLibraryA("kernel32.dll");
MessageBoxA messageBoxA = (MessageBoxA)GetProcAddress(h, "MessageBoxA");
messageBoxA(NULL, "Text", "Title", MB_OK);
return EXIT_SUCCESS;
}
Pas fait pour les moldus à la base :
- LoadLibrary ( 2 fonctions en 1)
- GetProcAddress (1 fonction c'est tout, faut pas déconner)
Partie 1 : Import par hash
HMODULE h = LoadLibraryA("kernel32.dll"); <-----
LoadLibrary
Partie 1 : Import par hash
GetProcAddress
#include <stdlib.h>
#include <Windows.h>
typedef int(WINAPI* MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
int main()
{
HMODULE h = LoadLibraryA("kernel32.dll");
MessageBoxA messageBoxA = (MessageBoxA)GetProcAddress(h, "MessageBoxA");
messageBoxA(NULL, "Text", "Title", MB_OK);
Partie 1 : Import par hash
Pourquoi se cacher?
- Feignasse (ça lit pas le manuel)
- Les gens qui codent tout ça ont la flemme
Partie 1 : Import par hash
#include <stdlib.h>
#include <Windows.h>
int main()
{
ShellExecuteA(NULL, "open", "sc stop WinDefend", NULL, NULL, SW_RESTORE);
return EXIT_SUCCESS;
}
Pourquoi se cacher?
- Éviter les signatures
Partie 1 : Import par hash
#include <stdlib.h>
#include <Windows.h>
int main()
{
ShellExecuteA(NULL, "open", "sc stop WinDefend", NULL, NULL, SW_RESTORE);
return EXIT_SUCCESS;
}
Pourquoi se cacher?
#include <stdlib.h>
#include <Windows.h>
int main()
{
ShellExecuteA(NULL, "open", "sc stop WinDefend", NULL, NULL, SW_RESTORE);
return EXIT_SUCCESS;
}
- Activité devinable facilement
- Signature facile
- Stabilité du code questionnable (m'enfin)
Partie 1 : Import par hash
Pourquoi se cacher?
Ouais mais du coup chuis pas teuteu, je vois bien que le programme importe LoadLibrary et GetProcAddress !
Partie 1 : Import par hash
Pourquoi se cacher?
Ouais mais du coup chuis pas teuteu, je vois bien que le programme importe LoadLibrary et GetProcAddress !
Des programme légitimes utilisent exclusivement ça :
- Des packers (pratique)
- Des solutions commerciales (ahah, deadly malware inside)
- Des bouts de télémétrie (chiant)
Partie 1 : Import par hash
L'IMPORT PAR HASH
Besoins : 1) LoadLibrary & GetProcAddress
Besoins : 1 et demie) kernel32.dll
Actions : 1) Charger en mémoire kernel32.dll
Actions : 2) Trouver LoadLibrary & GetProcAddress dans kernel32.dll
Partie 1 : Import par hash
La magie du Process Environment Block
Charger et trouver kernel32.dll
https://www.vergiliusproject.com/
La magie du Process Environment Block
Charger et trouver kernel32.dll
https://www.vergiliusproject.com/
La magie du Process Environment Block
struct _PEB_LDR_DATA
{
ULONG Length; //0x0
UCHAR Initialized; //0x4
VOID* SsHandle; //0x8
struct _LIST_ENTRY InLoadOrderModuleList; // <------ //0x10
struct _LIST_ENTRY InMemoryOrderModuleList; //0x20
struct _LIST_ENTRY InInitializationOrderModuleList; //0x30
VOID* EntryInProgress; //0x40
UCHAR ShutdownInProgress; //0x48
VOID* ShutdownThreadId; //0x50
};
Charger et trouver kernel32.dll
https://www.vergiliusproject.com/
La magie du Process Environment Block
struct _PEB_LDR_DATA
{
ULONG Length; //0x0
UCHAR Initialized; //0x4
VOID* SsHandle; //0x8
struct _LIST_ENTRY InLoadOrderModuleList; // <------ //0x10
struct _LIST_ENTRY InMemoryOrderModuleList; //0x20
struct _LIST_ENTRY InInitializationOrderModuleList; //0x30
VOID* EntryInProgress; //0x40
UCHAR ShutdownInProgress; //0x48
VOID* ShutdownThreadId; //0x50
};
Les auteurs de
malware be like :
Charger et trouver kernel32.dll
https://www.vergiliusproject.com/
Charger et trouver kernel32.dll
La magie du Process Environment Block
struct _PEB_LDR_DATA
{
...
struct _LIST_ENTRY InLoadOrderModuleList; // <------ //0x10
struct _LIST_ENTRY InMemoryOrderModuleList; //0x20
struct _LIST_ENTRY InInitializationOrderModuleList; //0x30
...
struct _LDR_DATA_TABLE_ENTRY
{
struct _LIST_ENTRY InLoadOrderLinks; //0x0
struct _LIST_ENTRY InMemoryOrderLinks; //0x10
struct _LIST_ENTRY InInitializationOrderLinks; //0x20
VOID* DllBase; // <------ //0x30
VOID* EntryPoint; //0x38
ULONG SizeOfImage; //0x40
struct _UNICODE_STRING FullDllName; //0x48
// ça s'rait'i pas c'qu'il nous faut
struct _UNICODE_STRING BaseDllName; // <------ //0x58
...
Trouver LoadLibray & GetProcAddress
Le header PE, salade, tomates, oignons
struct _LDR_DATA_TABLE_ENTRY
{
struct _LIST_ENTRY InLoadOrderLinks; //0x0
struct _LIST_ENTRY InMemoryOrderLinks; //0x10
struct _LIST_ENTRY InInitializationOrderLinks; //0x20
VOID* DllBase; // <------ //0x30
VOID* EntryPoint; //0x38
ULONG SizeOfImage; //0x40
struct _UNICODE_STRING FullDllName; //0x48
// ça s'rait'i pas c'qu'il nous faut
struct _UNICODE_STRING BaseDllName; // <------ //0x58
...
C'est quoi une DLL?
- Un PE classique
- Exporte au moins une fonction
- A un point d'entrée un peu différent
Partie 1 : Import par hash
Trouver LoadLibray & GetProcAddress
Le header PE, salade, tomates, oignons
Partie 1 : Import par hash
Pour résumer
Partie 1 : Import par hash
Pour résumer
Partie 1 : Import par hash
Ok, mais le Process Environment Block (PEB)?
La PEB?
Une telle structure devrait être difficile d'accès non?
Non?
Partie 1 : Import par hash
LA PEB?
Une telle structure devrait être difficile d'accès non?
Non?
Partie 1 : Import par hash
LA PEB?
Les registres magiques de Windows
X86 | X64 |
---|---|
FS[0x30] | GS[0x60] |
_TEB | _TEB |
Partie 1 : Import par hash
Les registres magiques de Windows
X86 | X64 |
---|---|
FS[0x30] | GS[0x60] |
_TEB | _TEB |
TEB? (Thread environment block)
struct _TEB (Thread Environment Block)
{
...
struct _PEB* ProcessEnvironmentBlock;
https://www.vergiliusproject.com/
TEB? (Thread environment block)
Partie 1 : Import par hash
TEB? (Thread environment block)
Partie 1 : Import par hash
Import par hash
Partie 1 : Import par hash
"Par HASH"
Import par hash
Partie 1 : Import par hash
Import par hash
Partie 1 : Import par hash
Contremesures
- OALabs - https://github.com/OALabs/hashdb
- Script
- Debug
Heaven's gate
(ou "toujours plus de registres spéciaux un peu chelou")
CS
GS
ES
Heaven's gate
Historique - comment ça marche le 32bits
- Des modules 64bits chargés
- Pas de syscall possible
- Redirection vers ntdll.dll (system32)
- Démarre en 64bits
Heaven's gate
Historique - comment ça marche le 32bits
Heaven's gate
Historique - Pourquoi le nom
Pas de table de syscall en 32 bits
Heaven's gate
Aujourd'hui
- Principalement pour mixer 32 et 64 bits
- Ralentir l'analyse
- Anti-dbg
- Anti-disassembly
- Anti-DBI
Voir : https://anti-reversing.com/Downloads/Anti-Reversing/The_Ultimate_Anti-Reversing_Reference.pdf
Heaven's gate
(ou "toujours plus de registres spéciaux un peu chelou")
Le registre CS, toujours plus
- Détermine le mode d'exécution actuel
- 0x33 -> 64 bits
- 0x23 -> 32 bits
- Registre "processeur"
- Et plein d'autres trucs sympa
Heaven's gate
CS actuel : 0x23 (execution en 32 bits)
Heaven's gate
CS actuel : 0x23 (execution en 32 bits)
code_x86:
push 0x33
call $+5
; offset entre instruction actuelle et code_x64
add [esp+0x5C+var_5c]
retf
code_x64:
<junk>
Heaven's gate
- Possibilité de créer un mode custom a l'aide d'un syscall
- NtSetLdtEntries() (x86 API only)
Questions?
Présentation malware
By Nofix
Présentation malware
- 185