
SMB1 server for NTLMv2 hash interception, written in C.
Serveur SMB1 pour intercepter les hachages NTLMv2, écrit en C.
L'objectif du projet est d'implémenter un serveur SMB1 sous forme de machine à états qui accepte et répond correctement aux requêtes du client afin de le tromper, le conduisant à compléter une authentification NTLM et ainsi révéler son propre hachage NTLMv2 (dans un format compatible avec hashcat/john).
Outil destiné aux activités de sécurité offensive/red team et à des fins pédagogiques (étude du protocole SMB1/NTLM), à utiliser exclusivement dans des environnements autorisés que vous possédez ou avec un consentement explicite.
Le serveur se fait passer pour un serveur SMB1 légitime et guide le client à travers une machine à états en 3 phases :

| État | Transition |
|---|---|
1. NEGOTIATE | Si un SMB NEGOTIATE arrive, suite à la réponse du serveur, l'état passe à 2. CHALLENGE |
2. CHALLENGE | Si un NTLM_NEGOTIATE arrive, suite à la réponse du serveur, l'état passe à 3. AUTH |
3. AUTH | Si un NTLM_AUTH arrive, suite à la réponse du serveur, l'état revient à 1. NEGOTIATE |
Au niveau de l'implémentation, il faut tenir compte de l'« enveloppe » NetBIOS externe, composée de 4 octets, dont les 3 derniers indiquent la longueur en octets du paquet SMB.
Chaque connexion client est suivie via une structure d'état (client_t dans server.h) qui, en plus du statut de la machine à états, maintient :
rx_buf) avec sa longueur, pour mettre en mémoire tampon les données lues depuis le socket mais pas encore entièrement traitées ;tx_buf, avec l'offset tx_off) pour mettre en mémoire tampon les données à envoyer au client mais pas encore entièrement transmises ;netbios_header_recv et netbios_msg_len pour le suivi de l'en-tête NetBIOS.À la réception de données, il est vérifié qu'au moins 4 octets (en-tête NetBIOS) ont été reçus, la longueur du message SMB est déterminée, les champs d'état sont mis à jour, et enfin le message est traité, mettant à jour l'état du client pour la prochaine réception.
La boucle principale du serveur est basée sur poll() pour gérer plusieurs connexions simultanément de manière non bloquante :

Lorsque l'authentification NTLM est terminée, le serveur affiche à l'écran ([INTERCEPTED] ...) le nom d'utilisateur, le nom d'hôte, le domaine et le hachage NTLMv2 capturé, au format :
username::domain:server_challenge:ntlmv2_response:blob
prêt à être utilisé avec des outils de craquage tels que hashcat (mode -m 5600) ou john.
gcc/clang) et une chaîne d'outils POSIX (le code utilise les sockets BSD, poll(), signal(), etc., il est donc destiné aux environnements Linux/Unix-like).Un Makefile est inclus :
make # compiler le serveur principal -> ./impostor
make debug # compilation de débogage (symboles, -O0, AddressSanitizer/UBSan)
make clean # supprimer les fichiers objets et exécutables générés
make run # compiler et exécuter le serveur
Alternativement, une commande de compilation manuelle équivalente est :
gcc -o impostor server.c smb1_parser.c spnego_decoder.c asn1_parser.c ntlm_parser.c
./impostor [port]
port (optionnel) : port TCP sur lequel le serveur écoute. S'il est omis, le port par défaut défini dans server.h (SERVER_PORT, 9000) est utilisé. Il doit être une valeur comprise entre 1 et 65535.Au démarrage, le serveur affiche une bannière, la version et les informations de configuration (port, nombre maximal de clients), puis reste à l'écoute des connexions. Lorsqu'un hachage NTLMv2 est capturé, les données interceptées (nom d'utilisateur, nom d'hôte, domaine, hachage) sont affichées à l'écran. Le serveur peut être arrêté avec Ctrl+C (SIGINT), géré par intHandler.
___ ___ _ ___
|_ _|_ __ ___ _ __ / _ \ ___| |_ / _ \ _ __
| || '_ ` _ \| '_ \| | | / __| __| | | | '__|
| || | | | | | |_) | |_| \__ \ |_| |_| | |
|___|_| |_| |_| .__/ \___/|___/\__|\___/|_|
|_| (v.1.0) by Lcky
[*] Version: 1.0
[*] Author: Lcky <luca9vinci at gmail dot com>
[*] Server Info
Port: 9090
Max Clients: 50
[*] Listening on port 9090
[*] Waiting for connections...
[INTERCEPTED] Username: test
[INTERCEPTED] Hostname: KALILINUX-2023-02
[INTERCEPTED] Domain : WORKGROUP
[INTERCEPTED] Hash : test::WORKGROUP:c4ba87a265de9e09:3482d0efa64fc09a94e44faa83d2a936:01010000000000009A3DE84B6235DD01D36FD06DFF4D64BB000000000200080038004E004900490001001E00570049004E002D00310046005800340055004D005000530034005400420004003400570049004E002D00310046005800340055004D00500053003400540042002E0038004E00490049002E004C004F00430041004C000300140038004E00490049002E004C004F00430041004C000500140038004E00490049002E004C004F00430041004C0008003000300000000000000000000000000000000CAFEB574B56CB6139E261228FBFE3075B4FA9393A3B71031AF3280F4D5A27D00A0010000000000000000000000000000000000009001C0063006900660073002F003100320037002E0030002E0030002E00310000000000
^C
[*] Stopping the server...
| Fichier | Description |
|---|
server.c / server.h | Point d'entrée, configuration de l'écoute TCP, machine à états du client, boucle principale basée sur poll(), mise en mémoire tampon RX/TX, affichage des hachages interceptés |
smb1_parser.c / smb1_parser.h | Analyse/construction des paquets SMB1 (en-tête, commandes NEGOTIATE, SESSION_SETUP, flags/flags2, etc.) |
spnego_decoder.c / spnego_decoder.h | Décodage du jeton SPNEGO (négociation du mécanisme d'authentification, extraction du blob NTLMSSP) contenu dans les messages SMB |
asn1_parser.c / asn1_parser.h | Analyseur minimal ASN.1 DER, utilisé par le décodeur SPNEGO pour construire l'arbre de structure ASN.1 |
ntlm_parser.c / ntlm_parser.h | Analyse des messages NTLMSSP (NEGOTIATE, CHALLENGE, AUTHENTICATE) et extraction du nom d'utilisateur, du domaine, du nom d'hôte et de la réponse NTLMv2 |
endianness.h | Utilitaire pour la gestion de l'endianness (conversions petit/grand boutiste à l'exécution) |
test.c, test2.c | Fichiers de test/expérimentation pour les analyseurs |
docs/ | Diagrammes et matériel de support (schéma de la machine à états, boucle principale) |