Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
MemITM — 用于进行内存中间人攻击的工具 | Kitploit
工具/GitHubGitHub/amossys/memitm
动态分析 (沙盒)内存取证漏洞利用逆向工程调试器模糊测试二进制分析
GitHubamossys/memitm

MemITM

用于进行内存中间人攻击的工具

查看仓库
126277年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

MemITM工具是什么?

MemITM(内存中间人)工具的开发目的是为了轻松拦截 Windows 进程内存中的“消息”。我们开发了许多自定义的内存拦截工具,用于在加密前捕获网络消息,或拦截 IPC 消息,并能够检查或修改它们以进行模糊测试。每个工具都高度定制、不通用,用 C/ASM 实现,且不易使用、维护和适配。

MemITM 工具旨在解决这些问题,其组成包括:

  • 一个 IDA Python 脚本,生成“配置”文件,指示拦截点的位置和方式(相对地址、如何找到缓冲区及其大小、如何放置钩子等);
  • 一个 DLL 文件,将被注入到目标进程中,加载配置并放置钩子;
  • 一个 DLL 文件注入器,将 DLL 加载到目标进程中;
  • 一个 Python 脚本,与注入的 DLL/钩子通信,实时获取拦截到的缓冲区(并可修改它们),通过非常简单的回调函数即可自定义。

你可以在这里下载(源码 + 编译好的):https://github.com/Amossys/MemITM

MemITM 有多简单?(示例1:WriteFile)

假设你想拦截某个 Windows 进程中的文件写入操作(有更简单的方式,但这里只是举例)。文件写入由 WriteFile 函数完成,该函数由 kernelbase.dll 导出,遵循原型 BOOL WriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, ...)。WriteFile 是一个 __fastcall 函数:lpBuffer 由 RDX 指向,NumberOfBytesToWrite 由 R8 指向。让我们拦截这些缓冲区。

  1. 在 IDA Pro 中打开你的 kernelbase.dll 文件,加载 generate.idapython.py 脚本,然后直接运行 getHook(LocByName("WriteFile"), "rdx","r8") 后再运行 updateConfig("config.bin")。

  2. 运行一个记事本,然后执行 python memitm.py notepad.exe config.bin。

这就完成了!在 WriteFile 函数上已放置了钩子,memitm.py 的“logger”和“fuzzer”函数将接收到缓冲区的副本。

我的缓冲区不是由寄存器指向的!(示例2:NtCreateFile)

getHook 函数允许通过寄存器指定缓冲区及其大小,但在某些情况下并非如此。假设你想拦截 NtCreateFile 系统调用并获取文件名。NtCreateFile 的原型为 NTSTATUS NtCreateFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, ...),可以通过 ObjectAttributes->ObjectName->Buffer 获取文件名(大小为 ObjectAttributes->ObjectName->Length * sizeof(WCHAR))。

getHook 还允许在其 t1customOpcodes 参数中指定一段 shellcode 来代替寄存器。这段 shellcode 必须:

  • 将缓冲区指针放入 RCX 寄存器;
  • 将缓冲区的大小放入 RDX 寄存器;
  • 不能破坏堆栈。

在 NtCreateFile 的情况下,我们可以直接运行以下汇编代码来完成工作:

root@kitploit:~
mov rax, [r8+0x10]    ; rax 现在指向 ObjectAttributes->ObjectName
mov rcx, [rax + 0x10] ; rcx 现在指向 ObjectAttributes->ObjectName->Buffer
mov rdx, [rax]        ; rdx 现在为 ObjectAttributes->ObjectName->Length
and rdx, 0xFFFF       ; Length 是 USHORT 类型
shl rdx, 1            ; 必须乘以 2

对这段代码进行汇编(例如使用在线反汇编网站):498B4010488B4810488B104881E2FFFF000048D1E2。此时 getHook 的调用应为 getHook(LocByName("NtCreateFile", t1customOpcodes="498B…E2")。

我可以拦截多个调用吗?

可以!配置文件中可以嵌入多个拦截点的定义,而 getHook 函数会向文件追加内容。你可以在多个模块中设置拦截点。例如,可以同时拦截 ALPC 和 IOCTL 消息。

你可以通过它们在 Python 回调函数中的“message ID”来区分它们。

哎呀,蓝屏/系统死机了!

别担心,还有一个简单的 HTTP 服务器(logserver.py)和 httpNetSend 函数,允许你将测试用例(及其修改)实时发送到远程主机。

如何进行模糊测试?

你可以先使用 bufferBitFlip 函数来……翻转若干位。记录原始消息将允许你编写自己的解析器,并开始手动实现一个更好的模糊器 :) 。记住:你不能改变缓冲区的大小!

例如,在 WriteFile 的示例中,下面的 fuzzer 函数会将 "hello" 替换为 "world":

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

示例3:解析 ALPC 消息

例如,对于 ALPC 消息,你可以设置如下的 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
    # 跳过 PORT_MESSAGE 头部(0x18 字节)
    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

它是如何内部工作的?

IDA Pro 脚本嵌入了一个简单的“钩子”引擎,允许将若干条指令移动到一个特定区域(源自我们的 DIMCT 工具)。它必须处理许多边界情况,例如内存相对寻址指令、交叉引用等,并且如果你尝试拦截非常小的基本块(x86 二进制小于 5 字节,x64 二进制小于 12 字节)且包含多个交叉引用时,它可能会显示大量“无法在此处安装钩子”的信息。更多信息请阅读源代码 :)。

它会在配置文件中生成以下信息:

  • 模块名称;
  • 拦截点的相对地址;
  • 拦截钩子区域(又称“T1 跳板”),将缓冲区/长度放入 RCX/RDX 并调用 DLL 的日志例程;
  • 恢复钩子区域(又称“T2 跳板”),恢复上下文并执行被替换的指令,然后返回到拦截点;
  • 恢复钩子区域的重定位信息,用于那些已转换为绝对地址且需要修补的相对寻址指令。

DLL 注入器是一个简单的 DLL 注入器(使用 CreateRemoteThread/LoadLibraryA 机制)。

DLL 本身会初始化一块共享内存区域,并等待配置数据(共享内存区域包含三个通用字段:共享内存消息 ID、消息大小和消息缓冲区)。收到配置后,它解析并在内存中安装钩子,此后不允许再更新配置(要设置新钩子必须终止进程)。任何已放置的钩子都会进入 DLL 的 genericHookFunction 函数。该函数将缓冲区数据、其大小和消息 ID(设置在共享内存消息 ID 字段的高位)填入内存区域(受关键段保护)。为了通知 Python 进程,使用两个事件来指示新消息到达,并等待进程对其进行修补(超时时间为 2 秒)。如果缓冲区已被更新,原来的缓冲区也会被修改。

memitm.py 脚本运行注入器进程,并等待共享内存被创建。然后它发送配置,并等待消息事件。收到事件后,读取共享内存,并调用 logger 和 fuzzer 函数,传入缓冲区、进程 ID 和消息 ID。如果 logger 函数返回的缓冲区与原缓冲区不同且大小相等,则将其写回共享内存区域。然后触发“ACK”事件,脚本等待下一个消息。

就是这样!

我们希望这个工具能派上用场,任何贡献/审查都将受到欢迎!另外,如果你是法国人并且喜欢雷恩,我们正在招聘 :)

下载工具