Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Strumenti/GitHubGitHub/amossys/memitm
Analisi Dinamica (Sandboxing)Memory ForensicsExploitReverse EngineeringDebuggerFuzzingAnalisi di Binari
GitHubamossys/memitm

MemITM

Strumento per effettuare un attacco man in the middle in memoria

Vedi Repository
126277 anni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Cos'è lo strumento MemITM?

Lo strumento MemITM (Mem In The Middle) è stato sviluppato per intercettare facilmente i "messaggi" nella memoria dei processi Windows. Abbiamo sviluppato molti strumenti di intercettazione personalizzati della memoria per catturare messaggi di rete prima della crittografia, o messaggi IPC, e per poterli ispezionare o alterare per eseguire del fuzzing. Ogni strumento era molto specifico, non generico, implementato in C/ASM e non era facile da usare/mantenere/adattare.

Lo strumento MemITM è stato sviluppato per risolvere questi problemi e consiste in:

  • uno script IDA Python, che genera un file di "config", indicando dove e come devono essere posizionati i punti di intercettazione (indirizzo relativo, come trovare il buffer e la sua dimensione, come posizionare l'hook, ecc.);
  • il file DLL, che verrà iniettato nel processo target e caricherà la config e posizionerà gli hook;
  • un iniettore di file DLL, che caricherà la DLL nel processo target;
  • uno script Python, che comunica con la DLL/gli hook iniettati, e riceve in tempo reale i buffer intercettati (e può alterarli) in callback molto semplici che puoi modificare come desideri.

Puoi scaricarlo (sorgenti + compilato) qui: https://github.com/Amossys/MemITM

Quanto è semplice MemITM? (Esempio1: WriteFile)

Supponiamo di voler intercettare le scritture su file (ci sono modi più semplici per farlo, ma è per l'esempio) in un processo Windows specifico. Le scritture su file vengono eseguite dalla funzione WriteFile, esportata da kernelbase.dll, e segue lo schema BOOL WriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, ...). WriteFile è una funzione __fastcall: lpBuffer è puntato da RDX e NumberOfBytesToWrite da R8. Intercettiamo questi buffer.

  1. apri il tuo file "kernelbase.dll" in IDA Pro, carica lo script generate.idapython.py, e esegui semplicemente getHook(LocByName("WriteFile"), "rdx","r8") seguito da updateConfig("config.bin").

  2. esegui un notepad e poi python memitm.py notepad.exe config.bin.

Questo è tutto! È stato posizionato un hook sulla funzione WriteFile, e le funzioni "logger" e "fuzzer" di memitm.py riceveranno una copia del buffer.

Il mio buffer non è puntato da un registro! (Esempio2: NtCreateFile)

La funzione getHook permette di specificare i registri per il buffer e la sua dimensione, ma in alcuni casi potrebbe non essere così. Supponiamo di voler intercettare le syscall NtCreateFile e ottenere il nome del file. NtCreateFile segue lo schema NTSTATUS NtCreateFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, ...), e il nome del file può essere ottenuto tramite ObjectAttributes->ObjectName->Buffer (la dimensione è ObjectAttributes->ObjectName->Length * sizeof(WCHAR)).

getHook permette anche di specificare uno shellcode nel suo parametro t1customOpcodes invece dei registri. Questo shellcode deve:

  • posizionare il puntatore al buffer nel registro RCX;
  • posizionare la dimensione del buffer nel registro RDX;
  • non alterare lo stack.

Nel caso di NtCreateFile, possiamo eseguire questo codice ASM per fare il lavoro:

root@kitploit:~
mov rax, [r8+0x10]    ; rax ora è ObjectAttributes->ObjectName
mov rcx, [rax + 0x10] ; rcx ora è ObjectAttributes->ObjectName->Buffer
mov rdx, [rax]        ; rdx ora è ObjectAttributes->ObjectName->Length
and rdx, 0xFFFF       ; Length è un USHORT 
shl rdx, 1            ; e deve essere *2

Assembliamolo (usando per esempio il sito web di disassemblaggio online): 498B4010488B4810488B104881E2FFFF000048D1E2. Ora la nostra chiamata getHook dovrebbe essere getHook(LocByName("NtCreateFile", t1customOpcodes="498B…E2").

Posso intercettare più chiamate?

Sì! Il file di config può contenere più definizioni di punti di intercettazione, e la funzione getHook aggiunge al file. Puoi impostare punti di intercettazione in più moduli. Ad esempio, puoi intercettare messaggi ALPC e IOCTL contemporaneamente.

Potrai differenziarli tramite il loro "ID messaggio" nei callback Python.

Oops, BSOD/blocco del sistema!

Non preoccuparti, c'è anche un semplice server HTTP (logserver.py) e la funzione httpNetSend che ti permettono di inviare i tuoi casi di test (e le modifiche) a un host remoto in tempo reale.

Come faccio a fare fuzzing?

Beh, puoi iniziare usando la funzione bufferBitFlip per... capovolgere alcuni bit. La registrazione dei messaggi grezzi ti permetterà di scrivere il tuo dissector e iniziare a implementare manualmente un fuzzer migliore :). Ricorda: non puoi cambiare la dimensione del buffer!

Ad esempio, nel nostro esempio WriteFile, la seguente funzione fuzzer sostituirà "hello" con "world":

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

Esempio3: dissezionare messaggi ALPC

Ad esempio, per i messaggi ALPC, potresti avere la seguente configurazione memitm.py:

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

Come funziona internamente?

Lo script IDA Pro incorpora un semplice motore di "hooking", che permette di spostare diverse istruzioni in un'area specifica (derivato dal nostro strumento DIMCT). Deve gestire molti casi particolari, come istruzioni relative alla memoria, riferimenti incrociati, ecc. e probabilmente mostrerà molti "can't install hook here" se provi a intercettare blocchi di base molto piccoli (<5 byte per binari x86, <12 byte per x64) che contengono molteplici riferimenti incrociati. Per maggiori informazioni, leggi il codice sorgente :).

Genera le seguenti informazioni nel file di config:

  • il nome del modulo;
  • l'indirizzo relativo del punto di intercettazione;
  • l'area dell'hook di intercettazione (nota come "T1 trampoline"), che posiziona il buffer/lunghezza in RCX/RDX e chiama la routine di log della DLL;
  • l'area dell'hook di ripristino (nota come "T2 trampoline"), che ripristina il contesto ed esegue le istruzioni sostituite prima di tornare al punto di intercettazione;
  • le rilocazioni dell'area dell'hook di ripristino, per le istruzioni relative che sono state convertite in assolute e devono essere patchate.

L'iniettore DLL è un semplice iniettore DLL (roba CreateRemoteThread/LoadLibraryA).

La DLL stessa inizializza un'area di memoria condivisa e aspetta i dati di config (l'area di memoria condivisa ha 3 campi generici: l'ID del messaggio della memoria condivisa, la dimensione del messaggio e il buffer del messaggio). Una volta ricevuti, li analizza e installa gli hook in memoria, e non sarà permesso alcun aggiornamento della config dopo questo (devi uccidere il processo se vuoi impostare nuovi hook). Qualsiasi hook posizionato finirà nella funzione DLL genericHookFunction. Questa funzione riempie semplicemente l'area di memoria (protetta con sezioni critiche) con i dati del buffer, la sua dimensione e l'ID del messaggio (impostato nei bit alti del campo ID del messaggio della memoria condivisa). Per notificare il processo Python, vengono utilizzati 2 eventi per segnalare nuovi messaggi e per attendere che il processo li patch (timeout di 2 secondi). Se il buffer è stato aggiornato, anche il buffer originale viene modificato.

Lo script memitm.py esegue il processo di iniezione e attende la creazione della memoria condivisa. Invia quindi la configurazione e attende l'evento del messaggio. Quando ricevuto, la memoria condivisa viene letta e le funzioni logger e fuzzer vengono chiamate con il buffer, il PID del processo e l'ID del messaggio. Se la funzione logger restituisce un buffer diverso da quello originale e la sua dimensione è uguale, viene scritto nell'area di memoria condivisa. L'evento "ACK" viene quindi segnalato, e lo script attende un nuovo messaggio.

Questo è tutto!

Speriamo che questo strumento sia utile, qualsiasi contributo/revisione sarà apprezzata! Inoltre, se sei francese e ti piace Rennes, stiamo assumendo :)

Scarica lo strumento