Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
MemITM — Outil pour réaliser un homme du milieu en mémoire | Kitploit
Outils/GitHubGitHub/amossys/memitm
Analyse Dynamique (Sandboxing)Criminalistique MémoireExploitationRétro-ingénierieDébogueursFuzzingAnalyse de Binaires
GitHubamossys/memitm

MemITM

Outil pour réaliser un homme du milieu en mémoire

Voir le dépôt
12627il y a 7 ansVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Qu'est-ce que l'outil MemITM ?

L'outil MemITM (Mem In The Middle) a été développé pour intercepter facilement les "messages" dans la mémoire des processus Windows. Nous avons développé de nombreux outils d'interception mémoire personnalisés pour capturer les messages réseau avant chiffrement, ou les messages IPC, et pouvoir les inspecter ou les modifier pour faire du fuzzing. Chaque outil était vraiment spécifique, non générique, implémenté en C/ASM et n'était pas facile à utiliser/maintenir/ adapter.

L'outil MemITM a été développé pour résoudre ces problèmes et se compose de :

  • un script IDA Python, qui génère un fichier de "configuration", indiquant où et comment les points d'interception doivent être placés (adresse relative, comment trouver le buffer et sa taille, comment placer le hook, etc.) ;
  • le fichier DLL, qui sera injecté dans le processus cible, charge la configuration et place les hooks ;
  • un injecteur de fichier DLL, qui charge la DLL dans le processus cible ;
  • un script python, qui communique avec la DLL/les hooks injectés, et récupère en temps réel les buffers interceptés (et peut les modifier) dans des callbacks très simples que vous pouvez modifier comme vous le souhaitez.

Vous pouvez le télécharger (sources + compilé) ici : https://github.com/Amossys/MemITM

À quel point MemITM est-il simple ? (Exemple1 : WriteFile)

Disons que vous souhaitez intercepter les écritures de fichiers (il existe des moyens plus simples de le faire, mais c'est pour l'exemple) dans un processus Windows spécifique. Les écritures de fichiers sont effectuées par la fonction WriteFile, qui est exportée par kernelbase.dll, et suit le schéma BOOL WriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, ...). WriteFile est une fonction __fastcall : lpBuffer est pointé par RDX et NumberOfBytesToWrite par R8. Interceptons ces buffers.

  1. ouvrez votre fichier "kernelbase.dll" dans IDA Pro, chargez le script generate.idapython.py, et exécutez simplement getHook(LocByName("WriteFile"), "rdx","r8") suivi de updateConfig("config.bin").

  2. lancez un bloc-notes, puis python memitm.py notepad.exe config.bin.

C'est tout ! Un hook a été placé sur la fonction WriteFile, et les fonctions "logger" et "fuzzer" de memitm.py recevront une copie du buffer.

Mon buffer n'est pas pointé par un registre ! (Exemple2 : NtCreateFile)

La fonction getHook permet de spécifier des registres pour le buffer et sa taille, mais dans certains cas, ce n'est pas possible. Disons que vous souhaitez intercepter les appels système NtCreateFile et récupérer le nom de fichier. NtCreateFile suit le schéma NTSTATUS NtCreateFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, ...), et le nom du fichier peut être obtenu par ObjectAttributes->ObjectName->Buffer (la taille est ObjectAttributes->ObjectName->Length * sizeof(WCHAR)).

getHook permet également de spécifier un shellcode dans son paramètre t1customOpcodes au lieu de registres. Ce shellcode doit :

  • placer le pointeur du buffer dans le registre RCX ;
  • placer la taille du buffer dans le registre RDX ;
  • ne pas perturber la pile.

Dans le cas de NtCreateFile, on peut simplement exécuter ce code ASM pour faire le travail :

root@kitploit:~
mov rax, [r8+0x10]    ; rax est maintenant ObjectAttributes->ObjectName
mov rcx, [rax + 0x10] ; rcx est maintenant ObjectAttributes->ObjectName->Buffer
mov rdx, [rax]        ; rdx est maintenant ObjectAttributes->ObjectName->Length
and rdx, 0xFFFF       ; Length est un USHORT 
shl rdx, 1            ; et doit être multiplié par 2

Assemblons cela (en utilisant par exemple le site web de désassemblage en ligne) : 498B4010488B4810488B104881E2FFFF000048D1E2. Notre appel à getHook devrait maintenant être : getHook(LocByName("NtCreateFile", t1customOpcodes="498B…E2").

Puis-je intercepter plusieurs appels ?

Oui ! Le fichier de configuration peut embarquer plusieurs définitions de points d'interception, et la fonction getHook ajoute au fichier. Vous pouvez définir des points d'interception dans plusieurs modules. Par exemple, vous pouvez intercepter les messages ALPC et IOCTL en même temps.

Vous pourrez les différencier par leur "ID de message" dans les callbacks python.

Oups, BSOD/gel du système !

Ne vous inquiétez pas, il y a aussi un simple serveur HTTP (logserver.py) et la fonction httpNetSend qui vous permettent d'envoyer vos cas de test (et modifications) vers un hôte distant en temps réel.

Comment faire du fuzzing ?

Eh bien, vous pouvez commencer par utiliser la fonction bufferBitFlip pour... inverser plusieurs bits. La journalisation des messages bruts vous permettra d'écrire votre propre dissecteur et de commencer à implémenter manuellement un meilleur fuzzer :). Rappelez-vous : vous ne pouvez pas changer la taille du buffer !

Par exemple, dans notre exemple WriteFile, la fonction fuzzer suivante remplacera "hello" par "world":

root@kitploit:~
def fuzzer(data, msgID=None, pid = 0):
   return data.replace("hello","world")

Exemple3 : disséquer les messages ALPC

Par exemple, pour les messages ALPC, vous pouvez avoir la configuration memitm.py suivante :

root@kitploit:~
def logger(data, msgID=None, pid=0):
    totalLen = 0
    dataLen = 0
    typ = 0
    dataInfoOffset = 0
    cid = 0
    tid = 0
    messageID = 0
    clientViewSize = 0
    # skip the PORT_MESSAGE header (0x18 bytes)
    if len(data) > 0x18:
        totalLen = struct.unpack("<H",data[:2])[0]
        dataLen = struct.unpack("<H",data[2:4])[0]
        typ = struct.unpack("<H",data[4:6])[0]
        dataInfoOffset = struct.unpack("<H",data[6:8])[0]
        zeroInit = struct.unpack("<L",data[4:8])[0]
        cid = struct.unpack("<L",data[8:0xC])[0]
        tid = struct.unpack("<L",data[0xC:0x10])[0]
        messageID = struct.unpack("<L",data[0x10:0x14])[0]
        clientViewSize = struct.unpack("<L",data[0x14:0x18])[0]
    logMessage = "ALPC message : %x:%x - %x:%x - %d:%d - %x - %x" % (totalLen, dataLen, typ, dataInfoOffset, cid, tid, messageID, clientViewSize)
    print logMessage
    return

Comment cela fonctionne-t-il en interne ?

Le script IDA Pro intègre un simple moteur de "hooking", qui permet de déplacer plusieurs instructions vers une zone spécifique (dérivé de notre outil DIMCT). Il doit gérer de nombreux cas particuliers, comme les instructions relatives à la mémoire, les références croisées, etc., et affichera probablement beaucoup de "can't install hook here" si vous essayez d'intercepter de très petits blocs de base (<5 octets pour les binaires x86, <12 octets pour les binaires x64) qui contiennent plusieurs références croisées. Pour plus d'informations, lisez simplement le code source :).

Il génère les informations suivantes dans le fichier de configuration :

  • le nom du module ;
  • l'adresse relative du point d'interception ;
  • la zone de hook d'interception (alias "T1 trampoline"), qui place le buffer/longueur dans RCX/RDX et appelle la routine de journalisation de la DLL ;
  • la zone de hook de restauration (alias "T2 trampoline"), qui restaure le contexte et exécute les instructions remplacées avant de revenir au point d'interception ;
  • les relocalisations de la zone de hook de restauration, pour les instructions relatives qui ont été converties en instructions absolues et doivent être patchées.

L'injecteur DLL est un simple injecteur DLL (truc CreateRemoteThread/LoadLibraryA).

La DLL elle-même initie une zone de mémoire partagée et attend les données de configuration (la zone de mémoire partagée a 3 champs génériques : l'ID de message de la mémoire partagée, la taille du message et le buffer du message). Une fois reçu, elle analyse et installe les hooks en mémoire, et aucune mise à jour de configuration ne sera autorisée après cela (vous devez tuer le processus si vous voulez mettre en place de nouveaux hooks). Tout hook placé aboutira à la fonction DLL genericHookFunction. Cette fonction remplit simplement la zone mémoire (protégée par des sections critiques) avec les données du buffer, sa taille et l'ID de message (défini dans les bits de poids fort du champ ID de message de la mémoire partagée). Afin de notifier le processus python, 2 événements sont utilisés pour signaler de nouveaux messages et pour attendre que le processus les patche (timeout de 2 secondes). Si le buffer a été mis à jour, le buffer original est également modifié.

Le script memitm.py exécute le processus d'injection et attend que la mémoire partagée soit créée. Il envoie ensuite la configuration et attend l'événement de message. Lorsqu'il est reçu, la mémoire partagée est lue et les fonctions logger et fuzzer sont appelées avec le buffer, l'ID du processus et l'ID du message. Si la fonction logger renvoie un buffer différent de l'original et que sa taille est égale, il est écrit dans la zone de mémoire partagée. L'événement "ACK" est alors signalé, et le script attend un nouveau message.

C'est tout !

Nous espérons que cet outil sera utile, toute contribution/relecture sera appréciée ! Aussi, si vous êtes français et aimez Rennes, nous recrutons :)

Télécharger l’outil