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?

Made with Slides.com