尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

pwndbg entry 命令全解析:在程序入口点停下的启动调试指南

pwndbg entry 命令全解析:在程序入口点停下的启动调试指南 pwndbg entry 命令全解析在程序入口点停下的启动调试指南【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg导读entry是 pwndbg 提供的一条启动类命令用于启动被调试程序并使其停在入口点entrypoint地址处方便在程序真正执行用户代码之前设置断点、检查映射与初始化状态。本文以仓库文档 docs/commands/start/entry.md 为骨架结合 pwndbg/commands/start.py 源码与测试用例完整讲解entry的语法、参数继承规则、shell 展开行为以及它在 GDB 与 LLDB 两个后端下的不同实现路径并对比start、sstart、starti等同类启动手段帮助你根据调试目标选择正确的启动方式。entry 命令是什么entry的功能一句话概括为启动被调试程序并在其入口点地址处停下。它属于 pwndbg 的启动START命令类别在 pwndbg/commands/start.py 中注册pwndbg.commands.Command(parser, categoryCommandCategory.START) pwndbg.commands.OnlyWithFile pwndbg.commands.OnlyWhenLocal def entry(argsNone) - None:从装饰器可以看出它的三个前提条件CommandCategory.START归属于启动类命令OnlyWithFile要求当前已加载可执行文件否则直接报错测试 tests/library/gdb/tests/test_loads.py 中test_entry_no_file_loaded验证了无文件时输出entry: There is no file loaded.OnlyWhenLocal仅对本地进程调试生效。一个容易混淆的要点是文档中特别强调的入口点并不一定是程序执行的第一条指令。动态链接器的初始化代码、启动例程startup routine都会在入口点之前运行。因此entry停下的位置是 ELF 头中e_entry指向的地址通常为_start而不是严格意义上的“第一条被执行的指令”。如果希望在第一条被执行的指令处停下需要改用 GDB 原生的starti命令或 LLDB 的process launch -s-s即--stop-at-entry。命令语法与参数entry的完整用法如下usage: entry [-h] [args ...]参数类型参数说明位置参数args启动二进制时传入的命令行参数可为零个或多个可选参数-h/--help显示帮助信息并退出它只有args一个位置参数没有额外的选项参数语法非常简洁。例如pwndbg entry arg1 arg2 pwndbg entry --flagvalue注意因为-h被 argparse 保留用于显示帮助如果想给程序传入以-开头的参数需要依赖下方的 shell 展开机制或先使用set args预置参数。核心行为细节文档与源码中的命令描述明确了以下几个关键行为理解它们才能正确驾驭entry1. shell 展开与重定向args中可以包含*或[...]等通配符它们会使用启动程序所用的 shell由$SHELL环境变量指定进行展开。同时输入输出重定向、、也被允许# 通配符展开把当前目录下所有 .so 文件作为参数传入 pwndbg entry *.so # 重定向把程序的 stdout 写入日志文件 pwndbg entry /tmp/out.log这在需要给程序传大量文件、或想保留程序输出用于后续分析时非常实用。2. 参数继承规则不带任何参数时entry会复用上一次通过run或set args指定的参数取消之前设置的参数、以无参数方式运行需要使用不带任何参数的set args即set args后面什么都不跟。这保证了entry与 GDB 的run/starti在参数记忆上行为一致不会因为换了启动方式就丢失已配置的参数。3. 不使用 shell 启动默认情况下程序会经由 shell 启动这也是*、重定向能生效的原因。如果希望不经过 shell 直接启动inferior可以设置(gdb) set startup-with-shell off此设置在startup-with-shell关闭后生效此时通配符与重定向将不再被展开参数会被原样传递给程序。源码级实现剖析GDB 后端内部等价于 starti在 GDB 环境下entry的实现非常直接——它直接拼接并执行了 GDB 的starti命令并对每个参数做了 shell 引号转义shlex.quoteif pwndbg.dbg.is_gdblib_available(): # If this is GDB, just start the process ourselves. run starti .join(map(quote, args)) gdb.execute(run, from_ttyFalse)也就是说在 GDB 下entry args等价于starti args进程会在第一条被执行的指令处停下随后 pwndbg 的上下文寄存器、反汇编、栈会自动刷新展示入口处的状态。map(quote, args)保证含空格或特殊字符的参数不会被 shell 错误拆解。LLDB 后端process launch -s 入口断点LLDB 后端目前没有“从命令内部启动进程”的通用机制因此采用了注释中说明的“部分命令覆盖”方案详见 pwndbg/dbg_mod/lldb/repl/init.py当用户在 LLDB 下输入entry或其别名时若当前还没有进程pwndbg 会先代之以process launch -s-s即--stop-at-entry见 pwndbg/dbg_mod/lldb/repl/init.py启动进程然后再交给 LLDB 完成entry的后续处理。如果进程已经在运行例如已用run -s启动则直接走breakpoint_at_entry()路径设置内部断点def breakpoint_at_entry(): addr int(pwndbg.aglib.elf.entry()) if not addr: print(message.error(No entry address found for the binary.)) return if int(pwndbg.aglib.regs.pc) addr: # Skip setting the breakpoint because we are already at the entry point. # This occurs when execution started with starti or run -s. return ...breakpoint_at_entry()的逻辑分为三步通过pwndbg.aglib.elf.entry()解析入口地址解析失败则打印No entry address found for the binary.若当前pc已经等于入口地址说明程序是用starti或run -s启动的本来就停在入口直接跳过断点设置否则在入口地址设置一个internalTrue的内部断点并通过执行控制器ExecutionController恢复执行直到命中入口断点。入口地址是怎么解析出来的pwndbg.aglib.elf.entry()的解析优先级见 pwndbg/aglib/elf.py依次是auxv中的AT_ENTRY项辅助向量里记录的动态入口地址最可靠inferior 的main_module_entry()调试器后端提供的主模块入口兜底查找常见符号名_start、start、__start、main全部失败则返回0。符号解析本身依赖pwndbg.aglib.symbol.lookup_symbol_addr()见 pwndbg/aglib/symbol.py支持按SymbolLookupType限制查找类型。这一套多级回退保证了即使辅助向量不可用也能尽量定位到入口。与其他启动命令的对比pwndbg 在start类别下提供了多条启动命令使用前应理解它们的差异。以下内容依据 docs/commands/start/ 目录下的各命令文档与 pwndbg/commands/start.py 源码整理命令停下的位置命令底层实现适用场景entry [args...]程序入口点地址GDB 下等价startiLLDB 下process launch -s 入口断点从入口开始逐步理解启动流程、检查初始映射start [args...]别名main、init仅 GDB第一个方便停靠的位置依次尝试main、_main、start、_start、init、_init对找到的符号设临时断点后run找不到再回退到entry想直接停在用户代码入口如main跳过启动例程sstart仅 GDB__libc_start_main等价于tbreak __libc_start_main; run分析 glibc 启动流程、查看main被调用的上下文GDBstarti/ LLDBrun -s第一条被执行的指令调试器原生能力严格停在最开始的指令attachp仅 GDB——附加而非启动包装 GDBattach支持按名称/部分 cmdline 匹配进程调试已在运行的进程需要特别说明的是start与entry的分工start优先寻找main等高层符号并设临时断点后run只有在这些符号都找不到时才回退调用entry见 pwndbg/commands/start.py。因此对带调试符号、含main的程序start通常更“方便”而对 stripped 的二进制或只想看启动序列的场景entry更合适。另外sstart全称 system start专门用于停在__libc_start_main适合追踪动态链接与 libc 初始化过程。典型实战场景场景一调试 stripped 二进制从入口看启动序列pwndbg file ./vuln pwndbg entry程序会在_start处停下pwndbg 自动展示寄存器、反汇编与栈内容可以单步观察栈布局、_start如何调用__libc_start_main对理解无符号程序的启动路径很有帮助。场景二带着参数与重定向启动pwndbg entry ./payload.bin /tmp/prog.logshell 展开与重定向让参数传递、输出收集一气呵成与直接run的体验一致。场景三复用已有参数pwndbg set args -s 0x1337 pwndbg entry # 自动带上 -s 0x1337 pwndbg set args # 清空参数 pwndbg entry # 无参数启动场景四LLDB 下的使用在 LLDB 会话中直接输入entrypwndbg 会代为执行process launch -s并停在入口若进程已运行如用run -s启动则会走内部断点路径补设入口断点。若进程未运行且后端无法代启动会提示The program is not running. Start the program with run -s and then use entry to set the breakpoint.源码注释也说明这是后端机制限制下的权宜方案见 pwndbg/dbg_mod/lldb/repl/init.py。测试验证情况仓库测试对entry相关行为有直接覆盖可作为行为契约参考tests/library/dbg/tests/test_mallocng.py在 mallocng 相关测试中通过ctrl.execute(entry)启动程序验证入口状态下堆调试命令可用tests/library/gdb/tests/heap/test_inferior_call_cache.pygdb.execute(entry)后验证 inferior 调用缓存行为tests/library/gdb/tests/test_loads.py验证未加载文件时entry报错There is no file loaded.对应OnlyWithFile装饰器tests/host/gdb/pytests_launcher.py 与 tests/library/gdb/conftest.py测试框架普遍以starti作为启动方式与entry在 GDB 下的内部实现一致。小结entry是 pwndbg 启动命令族中定位精确的一员GDB 下它等价于startiLLDB 下等价于process launch -s目标都是让程序停在入口点且完整继承了参数记忆、shell 展开与重定向等 GDB 启动语义。理解它与start、sstart的差别你就能在“停在入口”、“停在 main”、“停在 __libc_start_main”三种需求之间准确选择。若需要更细粒度控制可阅读 pwndbg/commands/start.py 与 docs/commands/start/ 目录下的相关文档并结合 docs/commands/start/sstart.md、docs/commands/start/start.md 对比学习。【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表