pwndbg checksec 命令:在 GDB/LLDB 会话中快速检测二进制安全防护属性
【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB & LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg
导读
checksec是 pwndbg 提供的一条实用命令,用于在调试会话内直接输出当前目标二进制(或用户指定文件)的安全防护属性,包括 RELRO、栈金丝雀(Stack Canary)、NX、PIE 以及基于 CET 的 SHSTK/IBT 等关键信息。它以 pwntools 的ELF.checksec()为基础实现,能够复用 pwndbg 的颜色主题输出结果。读完本文,你将掌握checksec的完整用法、输出字段含义,以及它在 pwndbg 源码中的实现原理,并能将它与内核加固检查命令kchecksec配合使用。
命令概览与定位
checksec命令属于 pwndbg 命令体系中的MISC(杂项)类别,对应的说明文档位于 docs/commands/misc/checksec.md,命令入口实现在 pwndbg/commands/checksec.py。
在 pwndbg 的 命令索引 中,它的定位是:
checksec- Prints out the binary security settings usingchecksec
一句话概括:当你在调试一个二进制程序时,输入checksec即可在不退出调试器、不借助外部工具的情况下,立刻看到该文件开启了哪些安全机制——这是漏洞利用(Exploit Development)阶段评估攻击面、判断防护强度的常用前置步骤。
语法与参数
命令的完整语法如下:
usage: checksec [-h] [-f FILE]| 短参数 | 长参数 | 说明 |
|---|---|---|
-h | --help | 显示帮助信息并退出 |
-f | --file | 指定要运行checksec检查的文件 |
两种典型用法:
- 不带参数:检查当前正在调试的程序(GDB 中已加载的目标文件);
- 带
-f FILE:显式指定任意一个 ELF 文件进行检查,即使该文件当前并未被调试。
从源码看,参数解析由 pwndbg/commands/checksec.py 中的argparse定义:
parser = argparse.ArgumentParser( description="Prints out the binary security settings using `checksec`.", ) parser.add_argument("-f", "--file", type=str, help="Specify the file to run `checksec` on.")典型输出与字段解读
在调试会话中执行checksec,例如针对/usr/bin/bash,输出形如:
pwndbg> checksec File: /usr/bin/bash Arch: amd64 RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled SHSTK: Enabled IBT: Enabled逐字段解读如下:
| 字段 | 含义 | 说明 |
|---|---|---|
File | 被检查文件的路径 | 未指定-f时为当前调试目标 |
Arch | 目标架构 | 如amd64、i386、aarch64等 |
RELRO | 重定位表只读 | 可能为Full RELRO、Partial RELRO或No RELRO,决定 GOT 表能否被改写 |
Stack | 栈金丝雀 | Canary found表示存在栈保护,No canary found表示可尝试栈溢出 |
NX | 不可执行栈 | NX enabled表示栈页不可执行,限制 shellcode 直接入栈执行 |
PIE | 地址随机化 | PIE enabled表示基址随机化开启,需要配合泄漏绕过 |
SHSTK | Shadow Stack(影子栈) | CET 特性,返回地址被额外保护,可有效对抗 ROP 中改写返回地址的手法 |
IBT | Indirect Branch Tracking(间接分支跟踪) | CET 特性,校验间接跳转目标,限制 ret2plt / 跳板类利用 |
其中SHSTK与IBT属于 Intel CET(Control-flow Enforcement Technology)的两大支柱,在较新工具链编译的二进制上会以Enabled形式出现。攻击者视角下,SHSTK/IBT 开启意味着经典 ROP 链的构造条件大幅收紧,需要在利用设计中专门规避。
实战:两种调用方式
方式一:检查当前调试目标(默认行为)
在 GDB/LLDB 中启动任意程序后直接执行:
pwndbg> checksec命令会自动确定“当前被调试的可执行文件”。根据 pwndbg/commands/checksec.py 的实现:
@pwndbg.commands.OnlyWithFile def checksec(file: str) -> None: local_path = file or pwndbg.aglib.file.get_proc_exe_file() print(pwndbg.wrappers.checksec.get_raw_out(local_path))- 若用户传入
-f FILE,local_path取用户指定路径; - 否则调用
pwndbg.aglib.file.get_proc_exe_file()(见 pwndbg/aglib/file.py),它返回“调试目标文件的本地路径”,从而实现对 GDB 加载目标的自动解析。
方式二:显式指定文件
调试过程中想顺带分析另一个二进制(例如漏洞利用要打的目标版本、或崩溃样本),无需重新加载:
pwndbg> checksec -f /path/to/other/binary这在对比“当前调试程序”与“待攻击目标”防护差异时非常实用。
无文件加载时的行为
checksec被@pwndbg.commands.OnlyWithFile装饰器(定义于 pwndbg/commands/init.py)约束:只有当前会话能够确定目标文件时才执行。当没有加载任何文件时,它会拒绝执行并给出错误提示:
- 在 QEMU 调试场景下报错:
Could not determine the target binary on QEMU. - 其他场景下报错:
There is no file loaded.
这意味着该命令依赖调试器上下文中存在可解析的 ELF 目标,不能在“空会话”下凭空工作。
源码级原理:与 pwntools 的集成
checksec的输出并非 pwndbg 自行实现,而是基于 pwntools 的pwnlib.elf.ELF.checksec()生成。核心逻辑集中在 pwndbg/wrappers/checksec.py:
def get_raw_out(local_path: str) -> str: elf = ELF(local_path) output = "File:".ljust(10) + elf.path + "\n" output += "Arch:".ljust(10) + elf.arch + "\n" with monkeypatch_pwnlib_term_text(): output += elf.checksec() return output几个实现细节值得注意:
列对齐的“魔数 10”:
File:与Arch:两行使用ljust(10)对齐,源码注释明确指出10是 pwntoolself.checksec()内部用于对齐输出的魔数,二者必须保持一致,否则输出会错位。若将来 pwntools 变更对齐宽度,此处的10也需要同步更新。颜色输出接管(monkeypatch):pwntools 默认使用自己的
pwnlib.term.text配色(红/绿/黄)来标记各防护状态。pwndbg 通过monkeypatch_pwnlib_term_text()上下文管理器,把这些颜色函数临时替换为 pwndbg 自己的配色体系(见 pwndbg/color/message.py 的error/success/warn),从而让checksec的输出与 pwndbg 整体主题风格统一:pwnlib.term.text.red = message.error pwnlib.term.text.green = message.success pwnlib.term.text.yellow = message.warn离开上下文后立即
del恢复,避免污染 pwntools 全局状态。这是一个典型的“第三方库输出风格适配”模式,也提示读者:此处与 pwntools 内部实现强耦合,升级 pwntools 时需要关注兼容性。日志静默:模块顶部通过
pwnlib.elf.elf.log._logger.disabled = True关闭 pwntools 的日志输出,避免其调试信息混入 pwndbg 的命令结果。
此外,该包装模块还提供了两个独立的判断函数:
relro_status(local_path):将 pwntools 的elf.relro取值("Full"/"Partial"/None)映射为人类可读的Full RELRO/Partial RELRO/No RELRO;pie_status(local_path):根据elf.pie返回PIE enabled或No PIE。
这两个函数可被 pwndbg 其他模块复用,作为独立的防护状态查询接口。
延伸:内核加固检查kchecksec
pwndbg 还提供了一条同族命令kchecksec(文档见 docs/commands/kernel/kchecksec.md,实现见 pwndbg/commands/kchecksec.py),用于检查 Linux 内核的加固配置,而非单个二进制。它需要满足OnlyWhenQemuKernel(QEMU 内核调试环境)与OnlyWhenPagingEnabled两个前提,逐项读取内核 Kconfig 配置并对照一组加固期望值输出。
其检查项覆盖面很广,包括:
- 栈溢出保护:
STACKPROTECTOR、STACKPROTECTOR_STRONG、SHADOW_CALL_STACK; - 可写可执行(RWX):
STRICT_KERNEL_RWX、STRICT_MODULE_RWX、DEBUG_WX; - ASLR:
RANDOMIZE_BASE、RANDOMIZE_KSTACK_OFFSET_DEFAULT等; - 内存分配加固:
SLAB_FREELIST_HARDENED、SLAB_FREELIST_RANDOM、KFENCE; - CFI:
CFI_CLANG; - 访问控制:
SECURITY_YAMA、SELinux 相关选项; - 以及
FORTIFY_SOURCE、HARDENED_USERCOPY、RANDSTRUCT_FULL、STRICT_DEVMEM等数十项杂项加固。
且针对不同架构附加专属检查项:x86 系(i386/x86-64)额外检查X86_SMAP、IA32_EMULATION、X86_X32;aarch64则检查ARM64_PAN、ARM64_EPAN、ARM64_PTR_AUTH、ARM64_BTI、ARM64_MTE等。该命令已有自动化测试覆盖,见 tests/library/qemu_system/tests/test_commands_kernel.py 中的test_command_kchecksec。
两者定位互补:checksec面向用户态二进制的安全属性,kchecksec面向内核映像的加固配置,在涉及内核漏洞利用、沙箱逃逸等场景时尤其值得联合使用。
小结
checksec在调试器内直接输出目标 ELF 的 RELRO、Canary、NX、PIE、SHSTK、IBT 等防护状态,零切换成本;- 默认自动识别当前调试文件,也可用
-f FILE指定任意文件; - 实现上以 pwntools
ELF.checksec()为引擎,由 pwndbg/wrappers/checksec.py 完成对齐、配色接管与日志静默; - 无文件加载或 QEMU 环境下命令会被
OnlyWithFile装饰器拦截并提示; - 配合
kchecksec可从“用户态二进制”与“内核配置”两个层面完成安全评估。
【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB & LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考