连接到 Firefox 内存

信息安全 tls openssl 操作系统 火狐 tls-拦截
2021-08-21 01:06:27

我正在尝试学习如何连接到浏览器内存。Frida 工具是一个好的开始我的目标是提取在 TLS 握手结束时建立的客户端随机、服务器随机和对称会话密钥。通过设置SSLKEYLOGFILE环境,我可以提取客户端随机密钥和主密钥,但它不会输出服务器随机密钥。

static void ssl3_RecordKeyLog(sslSocket *ss)在浏览了 Firefox 的源代码后,可以通过在函数中打印出服务器随机密钥来轻松解决此问题<firefox src/security/nss/lib/ssl/ssl3conn.c>

然而,这在我的项目中不是一个可行的解决方案,因为它使部署能力变差,即每次有新更新时编译 Firefox 通常不是更改浏览器代码并重新分发它的好习惯。

有一个更好的方法吗?更具体地说,这两种选择是否可行?我对浏览器的体系结构了解不多。

  • A. 在 Firefox 扩展中使用本机 C++ 调用来调用此函数/文件中的任何函数src/security/nss/lib/ssl/ssl3conn.c

  • B. 每次在浏览器中调用此函数时,使用浏览器挂钩调用我自己的代码。

上下文:使用服务器随机、客户端随机和主密钥这三个值,我想生成密钥块,该密钥块进一步用于生成 TLS 会话中使用的加密密钥。

我知道wireshark有这个功能,我可以用最小的改变输出密钥,但我不想使用wireshark,因为它会消耗主机上的更多资源来完成一个简单的过程,比如密钥生成。

我可以编写自己的 libpcap 代码来解析流量,但我想将此作为最后一个选项。

1个回答

你可能想用 frida 试试这个:

import frida
import sys

session = frida.attach("firefox.exe")
script = session.create_script("""
"use strict";
const PR_Read = Module.findExportByName("nss3.dll", "PR_Read");

Interceptor.attach(PR_Read, {
    onEnter: function (args) {
        let length = args[2].toInt32();
        let buffer = Memory.readByteArray(args[1], length - 1);
        console.log(buffer);
    }
});
""")

script.load()
sys.stdin.read()

请注意,我没有尝试过这段代码,但是由于您似乎已经设法使用 PR_Write (这是 firefox 输出)获得客户端随机数和主密钥,您可能会使用 PR_Read (即服务器响应什么)。

资料来源:


我是如何发现的:

  • 查看了您链接的页面。
  • 发现获取firefox输出的方法是使用PR_Write
  • 看了MDN上的功能是什么
  • 猜测如果有写,可能会有读
  • 在 MDN 上搜索 PR_Read
  • 发现它与 PR_Write 具有相同的签名
  • 将 PR_Write 替换为 PR_Read
  • 如果签名不同,我可能不得不改变一些周围的东西(比如 args[])