CTF场景下GDB调试时如何在断点后传入标准输入参数
解决GDB断点后向程序传入标准输入的问题
看起来你碰到的问题是:在GDB中断住程序获取PID后,继续执行时程序没法接收你输入的PID,直接退出了。这是因为默认情况下,GDB会接管程序的标准输入输出,当你用continue恢复执行后,程序等待输入时,GDB的交互环境可能没有正确把你的输入传递给目标进程。下面给你几个可行的解决方案:
方法1:将程序的终端重定向到真实TTY
这个方法让目标程序直接使用你的终端来接收输入,步骤如下:
- 启动GDB并加载目标程序:
gdb ./your_target_binary - 设置断点(比如在main开头):
break *main+0 - 运行程序触发断点:
r - 用
getpid获取当前进程的PID:getpid - 告诉GDB让目标程序使用你的终端:
set inferior-tty /dev/tty - 现在执行
continue,你会发现程序开始等待输入,直接在终端输入刚才获取的PID即可。
注意:如果你是在GUI终端里使用GDB,可能需要切换回程序的终端窗口输入;如果是纯命令行环境,直接在当前输入即可。
方法2:直接在GDB中模拟输入(无需切换终端)
如果不想切换终端,你可以通过GDB直接修改程序内存或寄存器,模拟输入的效果:
- 首先找到程序读取输入的位置,比如如果程序用
read函数读取标准输入,可以设置断点在read:break read - 运行程序:
r,当触发read断点时,用getpid获取PID - 找到程序存储输入的缓冲区地址:x86_64架构下,
read函数的第二个参数是缓冲区指针,可通过info registers查看rsi寄存器的值得到 - 将PID字符串写入缓冲区:比如你的PID是12345,就执行
set (char*)<buffer_addr> = "12345"(替换<buffer_addr>为实际地址) - 修改
rax寄存器(x86_64下read的返回值是读取的字节数),设置为PID字符串的长度:set $rax = 5 - 最后执行
return让程序跳过read函数的实际调用,直接使用你设置的返回值和缓冲区内容,这样程序就会认为已经读取到了正确的PID输入。
为什么你之前的操作会失败?
当你用r启动程序触发断点后,程序还处于GDB的控制下,标准输入并没有关联到你的终端。此时执行continue,程序尝试读取标准输入时,可能因为GDB没有正确转发输入,或者输入流被关闭,导致程序读取失败直接退出。上述方法就是解决这个输入转发的问题,或者直接绕过真实输入的步骤。
内容的提问来源于stack exchange,提问作者mahmoudadel




