GDB调试stripped ELF二进制文件失败:无法反汇编main、设置断点问题求助
解决Stripped ELF二进制文件的GDB调试问题
你的核心问题在于这个二进制文件是stripped的(从file命令输出里的stripped关键词可以看出来)——编译后所有调试符号、函数名、变量名等信息都被移除了,所以GDB无法识别main这类符号,这直接导致了你遇到的所有错误。下面我逐个解释你的问题,并给出完整的调试方案:
为什么你的操作会失败?
(No debugging symbols found)提示:这是正常现象,stripped文件本来就没有调试符号,不用在意这个提示。disassemble main报错:GDB不知道main对应的内存地址(因为符号被删了),所以不能直接用函数名反汇编,必须指定实际的内存地址范围。start命令失败 + 断点无效:start命令依赖GDB找到main函数的符号,没有符号的话自然报错。- 你输入的
b *00400961是致命错误:GDB会把以0开头的数字解析为八进制,而不是十六进制!正确的十六进制地址必须加0x前缀(比如b *0x400961),你写的地址被解析成了无效的内存位置,程序根本不会走到那里,所以直接运行结束退出。
正确的调试步骤
第一步:获取程序关键地址信息
先在终端里用工具获取程序的入口点和代码段范围,方便后续调试:
- 获取入口点地址(程序启动后第一条执行的指令地址):
找到readelf -h impossible_password.binEntry point address这一行,比如输出可能是0x4007d0。 - 获取代码段(.text)的地址范围:
找到readelf -S impossible_password.bin.text段的Addr(起始地址)和Size(大小),比如Addr: 0x4007d0,Size: 0x260,意味着代码段从0x4007d0到0x4007d0+0x260=0x400a30。 - 反汇编整个程序到文件,方便查看所有指令:
打开这个文本文件,找看起来像objdump -d impossible_password.bin > disassembly.txtmain的函数——比如有call printf@plt、call scanf@plt这类调用标准库函数的位置,附近就是程序的核心逻辑。
第二步:用GDB调试的正确流程
- 启动GDB并加载程序:
gdb impossible_password.bin - 在入口点设置断点,确保程序启动后立刻暂停:
b *0x4007d0 # 替换成你从readelf拿到的入口点地址 run - 找到
main函数的位置:
用单步指令逐步执行,直到找到核心逻辑:
如果你已经从si # 单步进入每条指令(包括函数调用) # 或者用 ni 单步跳过函数调用,更快找到mainobjdump的反汇编里找到了疑似main的起始地址(比如0x400890),可以直接设置断点:b *0x400890 run - 查看程序内的数值:
因为没有符号,只能通过内存地址和寄存器来查看:- 查看寄存器值:
info registers或者直接打印单个寄存器,比如print $rax - 查看内存内容:
x/16xw 0x7fffffffe000:查看从0x7fffffffe000开始的16个32位数值x/10s 0x400a00:查看从0x400a00开始的10个字符串x/5i $rip:查看当前指令指针($rip)指向的5条指令
- 跟踪输入值:如果程序用
scanf读取输入,输入的值通常会存在栈上或者某个寄存器里,你可以在scanf调用后用x命令查看栈内容(比如x/8xw $rsp)。
- 查看寄存器值:
额外提示
- 如果动态链接的程序在启动时就退出,可以尝试关闭ASLR(地址空间随机化),让每次调试的内存地址固定:
调试完记得改回去:sudo sysctl -w kernel.randomize_va_space=0sudo sysctl -w kernel.randomize_va_space=2 - 用Ghidra分析时,记得重新导入二进制文件,让Ghidra自动分析函数,它会给疑似
main的函数标记为FUN_xxxxxx,你可以把这个地址复制到GDB里用。
内容的提问来源于stack exchange,提问作者Garsty100
相关产品推荐
相关产品推荐

