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

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

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

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

工具目录

分类

查看所有分类
Loading categories
peafl64 — 用于Windows x64可执行文件的静态二进制插桩工具 | Kitploit
工具/GitHubGitHub/sentinel-one/peafl64
漏洞分析动态代码分析 (DAST)逆向工程模糊测试二进制分析Archived
GitHubsentinel-one/peafl64

peafl64

用于Windows x64可执行文件的静态二进制插桩工具

查看仓库
2062610个月前Kitploit 审核通过

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

概述

peafl64 是一款用于 Windows 中 x64 PE 的静态插桩工具。
静态插桩是指编辑可执行文件并在其中特定位置添加代码的做法。
该插桩会在二进制文件的每个基本块开头添加代码,以 AFL 兼容的方式记录执行流程。
它使我们能够在无需访问源代码的情况下,对用户模式(使用 WinAFL)和内核模式(使用 kAFL)下的二进制文件进行模糊测试。

还有其他模糊测试 Windows 二进制文件的方法;在本项目中,我们选择专注于静态插桩,因为它是最快的方法。

本项目基于 wmliang 的 pe-afl 工具构建,并增加了 x64 支持。

功能特性

  • 完整支持 Windows x64 二进制文件
  • 高性能
  • 支持按进程 ID 或线程 ID 过滤进行插桩
  • 处理重定位、异常表、相对寻址指令、跳转表、导入表、导出表等
  • 兼容 WinAFL(包含头文件)和 kAFL

用法

IDA 分析

插桩脚本需要 IDA 的分析输出。
要生成该输出,请在 IDA 中运行提供的 ida_dumper.py 脚本。
该脚本需要 IDA 7+ 和 python3.8+。

插桩

root@kitploit:~
usage: pe_afl.py [-h] [-n] [-cb] [-tf] [-te THREAD_ENTRY] [-nt NTOSKRNL] [-e ENTRY] [-l ENLARGE] [-v] [-lf] pefile ida_dump

positional arguments:
  pefile                Target PE file for instrumentation
  ida_dump              dump.json from IDA (created by ida_dumper.py)

optional arguments:
  -h, --help            show this help message and exit
  -n, --nop             Instrument with NOPs for testing
  -cb, --callback       Instrument with a callback, which is in the helper driver that's written in C
  -tf, --thread-filter  Driver instrumentation that filters only on thread ID (must use "-te" with this option)
  -te THREAD_ENTRY, --thread-entry THREAD_ENTRY
                        The address (RVA) of the thread's initialization function
  -nt NTOSKRNL, --ntoskrnl NTOSKRNL
                        ntoskrnl.exe path for offset extraction (non-optional if instrumenting a driver)
  -e ENTRY, --entry ENTRY
                        Inject code on entry point, ie. -e9090
  -l ENLARGE, --enlarge ENLARGE
                        Enlarge factor for sections, default=4
  -v, --verbose         Print debug log
  -lf, --logfile        Print log to pe-afl64.log rather than stream

使用 NOP 对用户模式二进制文件进行插桩

root@kitploit:~
PS pe-afl-64> python .\pe_afl.py -n C:\Work\cmd.exe C:\Work\cmd.exe.dump.json
[*] User-mode binary is being instrumented
[*] Single-thread instrument is on
[*] Preparing new sections
[*] Added section .text^
[*] Added section .cov
[*] Expanding relative jumps
[*] Expanded 3874 of 14353 branches
[*] Building address map
[*] Updating relative instructions
[*] Updating relocations...
[*] Updating Export table
[*] Updating load config
[*] Updating exception records
[*] Updating the PE headers
[*] Finalizing...
[*] Creating instrumented code
[*] Writing address mapping to C:\Work\cmd.exe.mapping.txt
[*] Updating jump tables
[*] Updated .text
...
[*] Removing temporary PE files
[*] Fixing PE checksum
[*] Instrumented binary saved to: C:\Work\cmd.instrumented.exe

使用进程 ID 过滤对内核模式二进制文件进行插桩

root@kitploit:~
python .\pe_afl.py -l 6 -nt "C:\Work\ntoskrnl.exe" "C:\Work\driver.sys" "C:\Work\driver.sys.dump.json"

使用线程 ID 过滤并输出详细日志对内核模式二进制文件进行插桩

root@kitploit:~
python .\pe_afl.py -v -tf -te 0x40000 -l 6 -nt "C:\Work\ntoskrnl.exe" "C:\Work\ntoskrnl.exe" "C:\Work\ntoskrnl.exe.dump.json"

如何替换 Windows 驱动程序

首先,你需要检查你的机器是通过 BIOS 还是 UEFI 启动。
对于 Hyper-V 虚拟机:第 1 代虚拟机基于 BIOS,第 2 代基于 UEFI。
如果你的机器基于 BIOS,则需要修补 winload.exe:

  • 从你的虚拟机中获取一份 winload.exe,并在其中找到函数 ImgpValidateImageHash
  • 将返回值修补为始终在 rax 中返回 0。例如,将函数最后一段代码块中的 mov eax, edi 替换为 xor eax, eax
  • 将修补后的 winload 复制到 system32 文件夹,并运行 bcdedit /set path \Windows\system32\winload2.exe

如果你的机器使用 UEFI 启动,则使用 EfiGuard 工具来修补 winload.efi。
如果使用 Hyper-V 管理器,命令速查表如下:

  1. 为虚拟机创建一个新的硬盘
  2. 使用 Tools 文件夹中提供的 FAT.vhdx(或自行创建一个),其中包含 UefiShell+EfiGuard 模块,并与新的硬盘一起使用
  3. 更改机器的启动顺序,使新硬盘排在第一位
  4. 启动后,在 UefiShell 中运行以下命令:
root@kitploit:~
FS1:
cd EFI/Boot
Load EfiGuard.Dxe.efi
FS0:
\EFI\Boot\bootx64.efi

然后对你选择的驱动程序进行插桩。要在 Windows 机器上加载已插桩的驱动程序,必须对其进行签名, 而自签名证书足以满足操作系统的要求:

root@kitploit:~
# In elevated powershell terminal
$c = New-SelfSignedCertificate -Type CodeSigningCert -KeyUsage DigitalSignature -Subject 'CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US'
Set-AuthenticodeSignature .\driver.instrumented.sys -Certificate $c -Force

如果你插桩的驱动程序已被系统使用,请使用以下命令(以管理员身份)替换驱动文件:

root@kitploit:~
set NAME=mydriver.sys
icacls %NAME% /save C:\windows\temp\%NAME%.icacls
takeown /F %NAME%
icacls %NAME% /grant Everyone:F
move %NAME% %NAME%.bak
move instrumented_driver.sys %NAME%
icacls . /restore C:\windows\temp\%NAME%.icacls

然后运行:

root@kitploit:~
bcdedit /set recoveryenabled no
bcdedit /set nointegritychecks on
shutdown -t 0 -r

WinAFL 模糊测试

与 WinAFL 的集成方式是通过使用提供的头文件编译一个 harness。
在头文件旁边还有 example.c,这是一个示例程序,演示了如何使用它们。
所提供的头文件是对 WinAFL 自带头文件的一处轻微修改,目的是与另一个名为 Syzygy 的静态二进制插桩工具集成。

kAFL 模糊测试

我们与 kAFL 集成的方式非常简单。
通常,kAFL harness 运行在虚拟机上,并通过特殊的“hypercalls”与模糊测试器的前端通信。
这些 hypercalls 让模糊测试器执行许多操作,其中包括从 IntelPT 加载覆盖率数据并将其解析为 AFL 位图。
由于 peafl64 使 IntelPT 跟踪变得不再必要,我们必须准备一种方式将覆盖率数据传输给模糊测试器。
因此,我们为 qemu 和 kvm 扩展了“hypercalls”,使运行在虚拟机中的(用户模式)harness 能够发送它通过辅助驱动程序收集到的覆盖率数据。

ESXi 设置

这里具体介绍 ESXi 上的设置,但同样适用于 AWS 等其他虚拟化平台。
设置非常简单:

  • 创建一台 Ubuntu 机器
  • 确保在机器的 CPU 配置中启用了“Expose hardware assisted virtualization to the guest OS”
  • 克隆 sbi_kAFL 仓库
  • 按照 kAFL 仓库中的说明正常安装 kAFL,但不执行 install.sh qemu 步骤,而是运行 install.sh qemu_sbi

要使用 kAFL 和 peafl64 进行模糊测试,我们需要搭建一台模糊测试机器:

  • 编译辅助驱动程序并为其签名
  • 使用我们 kAFL fork 提供的头文件编译一个 harness
  • 在虚拟机上加载辅助驱动程序
  • 运行 kAFL 的 loader

除此之外,使用我们的 kAFL fork 进行模糊测试与使用 kAFL 进行常规模糊测试相同。

执行流程

步骤概览:

  1. 确定插桩代码的插入点
  2. 定位需要调整的指令和结构
  3. 将插桩代码插入到指定函数中
  4. 调整:
    • 相对寻址指令
    • 跳转表
    • 异常处理程序
    • PE 头
    • 各种 PE 配置(加载配置 load config)
  5. 使用已插桩的节重建 PE

首先,我们使用 IDA 来查找并分析感兴趣的指令和位置。
分析会生成一个 dump.json 文件,其中包含所有这些信息的 json 格式。
instrument.py 包含插桩逻辑,其流程在 process_pe 函数中概述。
要对二进制文件进行插桩,我们会复制其可执行节,所有插桩代码都会放在这些复制的节中。
接下来,我们处理所有相对寻址指令,并确定是否需要以及如何处理它们。
假设从地址 X 到地址 Y 有一个短跳转(short jmp)。我们在 X 和 Y 之间插入插桩代码,现在目标位于地址 Z(Z = Y + len(instrumentation))。
这意味着我们必须修改这条跳转指令。
如果地址 Z 现在位于短跳转(short jmps)的范围之外,我们需要将跳转从 short 转换为 far。(instrument.py:expand_relative_instructions)
例如:

  • short jmp 0x57 (eb 55) -> near jmp 0x604 (e9 ff 05 00 00)

对于 call、loop 和条件跳转等指令也是如此。
另一个需要处理的常见情况是 x64 汇编中引入的 rip 相对寻址指令:

  • call [rip+0x1000]

我们会更新以下内容,使其指向插桩后的代码:重定位表、导出表、加载配置、TLS 目录和异常记录。
所有地址都会从原始节更新到对应的插桩节。(instrument.py:update_addr)
PE 头也会被更新,以反映 PE 结构的更改——新增的节、更改的入口点和 PE 大小。(instrument.py:update_pe_headers)

此外,peafl64 能够对 Windows 内核进行插桩。为此,它解析并更新了动态值重定位表(DVRT)和 SSDT,并处理 PatchGuard 的特殊细节。

DVRT 是一个编译器生成的表,描述了加载 PE 时需要更改的地址位置。
它用于增强 KASLR,并有助于缓解 Spectre 漏洞(1, 2, 3)。
DVRT 通过一组模仿该表结构的类来解析(drt.py; instrument.py:get_updated_dynamic_relocs)

处理和更新 SSDT 并不那么简单。
它的地址没有被导出,因此我们只能依赖符号或启发式方法来定位它。
我们的解决方案采用启发式方法,使用 NtWaitForSingleObject 作为所有 Windows 10 版本的常量标记,并相对它来查找 SSDT 的地址。(instrument.py:ntoskrnl_update_KiServiceTable)
这种方法适用于所有 Windows 10 内核,但对于其他内核版本则需要调整。

待办事项

  • 支持 x64
  • 新的异常处理程序(cxx4)
  • 改进 IDA dumper 的性能
  • 完整解析 LOAD_CONFIG 结构
  • 添加测试
  • 开箱即用地支持更多 Windows 内核版本
  • 与 Nyx(新的 kAFL)集成
下载工具