
Winstrument is a framework of modular scripts to aid in instrumenting Windows software using Frida for reverse engineering and attack surface analysis.
Winstrument 是一个模块化脚本框架,用于借助 Frida 对 Windows 软件进行插桩,以支持逆向工程和攻击面分析。
本项目支持 python 3.7。 假设您已经安装了 Python 和 pip,只需:
pip install winstrument
然后执行程序,运行:
winstrument
请注意,该工具目前处于实验阶段,有时可能会冻结或出现其他稳定性问题。
在某些情况下,例如全新安装的 Windows 10,您在通过 pip 安装 Frida 时可能会遇到 SSL 错误。如果发生这种情况,请参阅下面的故障排除。
要运行 winstrument REPL,只需运行 winstrument。
下面是一个使用 registry 模块对 notepad.exe 进行插桩的快速示例。有关可用 CLI 命令的完整信息,请参阅下方的 CLI 部分。
PS C:\winstrument> winstrument
> set target C:\Windows\System32\notepad.exe
> use registry
> run
Spawned 1144
instrumented process with pid: 1144 and path: C:\Windows\System32\notepad.exe
<User closes notepad from GUI>
detached from 1144 for reason process-terminated
> show registry
module time target function hkey subkey value
-------- ----------------- ------------------------------- ---------------- ------------------ --------------------------------------------------------------------------- ---------------------------------
registry 2019-08-19 07:03:07 C:\Windows\System32\notepad.exe RegGetValueW 0x2f4 SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize AppsUseLightTheme
<...>
在上面的示例中,用户指定目标进程,即 notepad.exe。然后他们表示要使用 registry 模块,该模块会枚举程序发出的与注册表相关的系统调用。进程结束后(用户关闭记事本),可以使用 show registry 查看存储的输出。
主要的 Python 文件 winstrument.py 初始化 Frida 设备并生成目标进程的一个实例。
cmdline.py 使用 cmd2 提供命令行界面。当 Winstrument 直接从命令行运行时,这是主脚本入口点。相关命令在下方说明。
然后,它会遍历每个已启用的模块,实例化该模块,并调用该模块的 load_scripts() 方法来对进程进行插桩。
最后,当从目标进程脱离时,它会对每个模块调用 get_output() 和 on_finish()。
模块位于 modules/ 目录下的 .py 文件中。一个模块由 base_module.BaseInstrumentation 的子类组成,该子类定义了要注入的代码、针对注入代码的消息处理以及输出。
模块 API 将在下面的“模块”部分进一步定义。
每个模块都会存储元数据,例如其描述 modules/metadata.toml。该小节应以模块名称(不区分大小写)作为标题。
例如,以下是与 dlls 模块对应的小节:
[DLLS]
description = """Hooks LoadLibrary-family system calls and outputs DLL loads where part of the search path might be
writable by the current user or a low-privileged user group."""
程序将设置存储在 %APPDATA%/winstrument 目录下的 settings.toml 中。
由于大多数(即便不是全部)模块都会向目标进程注入 Javascript,modules/js/ 目录中包含了由模块加载并注入的 Frida Javascript 代码片段。
这些文件应与模块同名,例如模块 dlls.py 将使用 js/dlls.js 中的 JS。
如上所述,每个模块都继承自 base_module.py 中的 BaseInstrumentation。
每个模块都应将其名称(不带扩展名的 python 和 js 文件名)定义为名为 modulename 的静态类属性。
模块可以使用或重写 BaseInstrumentation 中的以下方法:
__init__(self,*args,**kwargs) - 除了任何特定于模块的初始化代码外,此构造函数还应调用 super().__init__(*args,**kwargs)。load_script(self) - 此方法通常无需重写,因为 BaseInstrumentation 中的实现对于大多数用例来说已经足够。要挂钩 Frida 事件,请改为重写 register_callbacks()。load_script 应用于加载要插桩的 javascript 文件,调用 Frida 的 session.create_script,添加所需的回调,然后调用脚本对象的 load() 方法来执行插桩。register_callbacks(self) - 由 BaseInstrumentation.load_script 在将脚本加载到目标进程之前调用。用于注册诸如 _session.on('message') 等事件。BaseInstrumentation 版本默认会为 on_message 添加一个钩子。write_message(message) 接收一个类似 JSON 的 dict 消息,将其写入 sqlite 数据库,并保存以供稍后输出。Winstrument shell 提供以下命令:
list - 显示所有可用和已加载的模块load <modulename>/use <modulename> - 启用具有给定名称的模块unload <modulename> - 禁用具有给定名称的模块set [setting [value]] - 不带参数时,显示所有设置及其值。带一个参数时,显示 setting 的值。带两个参数时,将 setting 设为 value。设置会跨多次运行持续保留。show [modulename [format]] - 以指定的 format 显示来自 modulename 的已存储输入。不带参数运行可查看格式化程序列表。info <modulename> - 打印具有给定名称的模块的描述。run - 开始插桩。q// - 退出 CLI(显然)。这种情况似乎主要发生在全新安装的 Windows 上。Frida 的 setup.py 会尝试从 https://files.pythonhosted.org 拉取一个 .egg 文件。在某些情况下,这会因该域的 SSL 证书无法验证而失败。这似乎是 Windows 加载根 CA 的方式带来的副作用。Windows 在默认安装中似乎并未附带所有根 CA,而是更倾向于在访问网站时按需拉取它们。因此,为 files.pythonhosted.org 的 SSL 证书签名的根 CA 可能不在系统信任存储中。
要解决此问题,请在 Edge 或 Chrome 中手动访问 https://files.pythonhosted.org,让 Windows 将根 CA 添加到其信任存储中,然后重试 pip install。
请注意,在 Firefox 中访问该页面不会起作用,因为 Firefox 使用自己的信任存储,而不是系统存储。
Winstrument 采用 GPLv3 许可。有关更多详细信息,请参阅 LICENSE 文件。
post_load(self) 由 BaseInstrumentation.load_script 在脚本加载到目标进程内之后调用。例如,这可用于调用脚本导出的 rpc 方法。get_output(self) - 当目标进程脱离时由主脚本调用。此方法应返回一个列表,其中每个条目是一个 MoudleMessage 对象(来自 data/module_message.py)。通常无需重写。on_message(self,message,data) - 用于处理 frida message 事件的回调,该事件由注入的 JS 中的 send 触发。on_finish(self) - 当目标进程脱离时由主脚本调用的回调。在此执行所需的任何清理操作。quitexit