Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
MemITM — Ferramenta para fazer man-in-the-middle em memória | Kitploit
Ferramentas/GitHubGitHub/amossys/memitm
Análise Dinâmica (Sandboxing)Forensia de MemóriaExploraçãoEngenharia ReversaDepuradoresFuzzingAnálise de Binários
GitHubamossys/memitm

MemITM

Ferramenta para fazer man-in-the-middle em memória

Ver Repositório
12627há 7 anosRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

O que é a ferramenta MemITM?

A ferramenta MemITM (Mem In The Middle) foi desenvolvida para intercetar facilmente "mensagens" na memória de processos Windows. Desenvolvemos muitas ferramentas de interceção de memória personalizadas para capturar mensagens de rede antes da encriptação, ou mensagens IPC, e para poder inspecioná-las ou alterá-las para fazer fuzzing. Cada ferramenta era muito personalizada, não genérica, implementada em C/ASM e não era fácil de usar/manter/adaptar.

A ferramenta MemITM foi desenvolvida para resolver estes problemas e consiste em:

  • um script IDA Python, que gera um ficheiro de "config", indicando onde e como os pontos de interceção devem ser colocados (endereço relativo, como encontrar o buffer e o seu tamanho, como colocar o hook, etc.);
  • o ficheiro DLL, que será injetado no processo alvo e carrega a config e coloca os hooks;
  • um injetor de ficheiros DLL, que carrega a DLL no processo alvo;
  • um script python, que comunica com a DLL/hooks injetados e obtém em tempo real os buffers intercetados (e pode alterá-los) em callbacks realmente simples que podes modificar como quiseres.

Podes descarregá-lo (fontes + compilado) aqui: https://github.com/Amossys/MemITM

Quão simples é o MemITM? (Exemplo1: WriteFile)

Digamos que queres intercetar escritas em ficheiros (há formas mais simples de o fazer, mas é para o exemplo) num processo Windows específico. As escritas em ficheiros são realizadas pela função WriteFile, que é exportada por kernelbase.dll, e segue o esquema BOOL WriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, ...). WriteFile é uma função __fastcall: lpBuffer é apontado por RDX e NumberOfBytesToWrite por R8. Vamos intercetar estes buffers.

  1. abre o teu ficheiro "kernelbase.dll" no IDA Pro, carrega o script generate.idapython.py, e simplesmente executa getHook(LocByName("WriteFile"), "rdx","r8") seguido de updateConfig("config.bin").

  2. executa um notepad e depois, python memitm.py notepad.exe config.bin.

É isso! Um hook foi colocado na função WriteFile, e as funções "logger" e "fuzzer" do memitm.py receberão uma cópia do buffer.

O meu buffer não é apontado por um registo! (Exemplo2: NtCreateFile)

A função getHook permite especificar registos para o buffer e o seu tamanho, mas em alguns casos pode não ser esse o caso. Digamos que queres intercetar syscalls NtCreateFile e obter o nome do ficheiro. NtCreateFile segue o esquema NTSTATUS NtCreateFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, ...), e o nome do ficheiro pode ser obtido por ObjectAttributes->ObjectName->Buffer (o tamanho é ObjectAttributes->ObjectName->Length * sizeof(WCHAR)).

getHook também permite especificar um shellcode no seu parâmetro t1customOpcodes em vez de registos. Este shellcode deve:

  • colocar o ponteiro do buffer no registo RCX;
  • colocar o tamanho do buffer no registo RDX;
  • não estragar a pilha.

No caso do NtCreateFile, podemos simplesmente executar este código ASM para fazer o trabalho:

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

Vamos montar isto (usando, por exemplo, o website de desmontagem online) : 498B4010488B4810488B104881E2FFFF000048D1E2. A nossa chamada getHook deve agora ser getHook(LocByName("NtCreateFile", t1customOpcodes="498B…E2").

Posso intercetar múltiplas chamadas?

Sim! O ficheiro de config pode incorporar várias definições de pontos de interceção, e a função getHook anexa o ficheiro. Podes definir pontos de interceção em múltiplos módulos. Por exemplo, podes intercetar mensagens ALPC e IOCTL ao mesmo tempo.

Poderás diferenciá-los pelo seu "ID de mensagem" nos callbacks python.

Oops, BSOD/congelamento do sistema!

Não te preocupes, há também um simples servidor HTTP (logserver.py) e a função httpNetSend que te permitem enviar os teus casos de teste (e modificações) para um host remoto em tempo real.

Como faço fuzzing?

Bem, podes começar por usar a função bufferBitFlip para... inverter vários bits. Registar mensagens brutas permitir-te-á escrever o teu próprio dissector e começar a implementar manualmente um melhor fuzzer :). Lembra-te: não podes alterar o tamanho do buffer!

Por exemplo, no nosso exemplo WriteFile, a seguinte função fuzzer substituirá "hello" por "world":

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

Exemplo3: dissecando mensagens ALPC

Por exemplo, para mensagens ALPC, podes ter a seguinte configuração 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

Como funciona internamente?

O script IDA Pro incorpora um motor de "hooking" simples, que permite mover várias instruções para uma área específica (derivado da nossa ferramenta DIMCT). Deve lidar com muitos casos extremos, como instruções relativas à memória, referências cruzadas, etc., e provavelmente mostrará muitos "can't install hook here" se tentares intercetar blocos básicos realmente pequenos (<5 bytes para binários x86, <12 bytes para x64) que contêm múltiplas referências cruzadas. Para mais informações, basta ler o código-fonte :).

Gera a seguinte informação no ficheiro de config:

  • o nome do módulo;
  • o endereço relativo do ponto de interceção;
  • a área do hook de interceção (também conhecida como "T1 trampoline"), que coloca o buffer/tamanho em RCX/RDX e chama a rotina de log da DLL;
  • a área do hook de restauro (também conhecida como "T2 trampoline"), que restaura o contexto e executa as instruções substituídas antes de retornar ao ponto de interceção;
  • as realocações da área do hook de restauro, para instruções relativas que foram convertidas em absolutas e devem ser corrigidas.

O injetor DLL é um simples injetor DLL (coisas CreateRemoteThread/LoadLibraryA).

A própria DLL inicia uma área de memória partilhada e aguarda pelos dados da config (a área de memória partilhada tem 3 campos genéricos: o ID da mensagem da memória partilhada, o tamanho da mensagem e o buffer da mensagem). Uma vez recebida, analisa e instala os hooks na memória, e nenhuma atualização da config será permitida depois disso (deves matar o processo se quiseres configurar novos hooks). Qualquer hook colocado irá parar na função DLL genericHookFunction. Esta função apenas preenche a área de memória (protegida com secções críticas) com os dados do buffer, o seu tamanho e o ID da mensagem (definido nos bits mais altos do campo ID da mensagem da memória partilhada). Para notificar o processo python, são usados 2 eventos para sinalizar novas mensagens e para aguardar que o processo as corrija (timeout de 2 segundos). Se o buffer foi atualizado, o buffer original também é modificado.

O script memitm.py executa o processo injetor e aguarda que a memória partilhada seja criada. Depois envia a configuração e aguarda o evento de mensagem. Quando recebido, a memória partilhada é lida e as funções logger e fuzzer são chamadas com o buffer, o ID do processo e o ID da mensagem. Se a função logger retornar um buffer diferente do original e o seu tamanho for igual, é escrito na área de memória partilhada. O evento "ACK" é então sinalizado, e o script aguarda uma nova mensagem.

É isso!

Esperamos que esta ferramenta seja útil, quaisquer contribuições/revisões serão apreciadas! Além disso, se és francês e gostas de Rennes, estamos a contratar :)

Baixar ferramenta