GDB使用基础

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

GDB作为Linux平台下的动态调试工具,对安全测试人员来说和Windows下的Ollydebug、ImmunityDebug实质来说差不多,对于不太习惯命令行的同学来说,建议先在Windows平台上熟悉一个动态调试器操作的基本逻辑和功能再来Linux平台上学习使用GDB*(尽管使用习惯上的差距确实让人会觉得很痛苦) *。

vi ~/.gdbinit 可以设置一些gdb内容
在这里插入图片描述


一、如何开始调试

gbd和其他调试器一样,有多种开始的方式,这里我们重点讲gdb直接运行、attach这两种,调试coredump文件的这种目前应该还不会用到。

  • 直接运行:如果我们需要从头开始对一个程序进行调试,可以在程序路径下使用gdb file_name 的方式进入调试界面
    在这里插入图片描述
  • Attach:很多时候我们需要调试一个正在运行中的程序,就需要使用attach。
    首先我们需要确认程序的PID,有2中方式:
    1. 在路径下使用pidof filename 查看
    2. 使用ps -ef |grep filename 查看

    然后就可以使用gdb attach pid 调试程序

二、常用指令

命令名称 命令缩写 命令说明
run r 运行一个待调试的程序
continue c 让暂停的程序继续运行
next n 运行到下一行
step s 单步执行,遇到函数会进入
until u 运行到指定行停下来
finish fi 结束当前调用函数,回到上一层调用函数处
return return 结束当前调用函数并返回指定值,到上一层函数调用处
jump j 将当前程序执行流跳转到指定行或地址
print p 打印变量或寄存器值
backtrace bt 查看当前线程的调用堆栈
frame f 切换到当前调用线程的指定堆栈
thread thread 切换到指定线程
break b 添加断点
tbreak tb 添加临时断点
delete d 删除断点
enable enable 启用某个断点
disable disable 禁用某个断点
watch watch 监视某一个变量或内存地址的值是否发生变化
list l 显示源码
info i 查看断点 / 线程等信息
ptype ptype 查看变量类型
disassemble dis 查看汇编代码
set args set args 设置程序启动命令行参数
show args show args 查看设置的命令行参数

接下来以这段代码为例,

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char sh[]="/bin/sh";
int init_func(){
    setvbuf(stdin,0,2,0);
    setvbuf(stdout,0,2,0);
    setvbuf(stderr,0,2,0);
    return 0;
}

int func_test(char *cmd){
        system(cmd);
        return 0;
}

int main(){
    char a[8] = {};
    char b[8] = {};
    //char a[1] = {'b'};
        puts("input:");
        gets(a);
        printf(a);
        if(b[0]=='a'){
                func_test(sh);
        }
    return 0;
}

1.断点与开始

断点

break命令(简写为b)用于添加断点,可以使用以下几种方式添加断点:

break FunctionName,在函数的入口处添加一个断点;
break LineNo,在当前文件行号为LineNo处添加断点;需要-g
break FileName:LineNo,在FileName文件行号为LineNo处添加一个断点;需要-g
break FileName:FunctionName,在FileName文件的FunctionName函数的入口处添加断点;
break -/+offset,在当前程序暂停位置的前/后 offset 行处下断点;
break *address
break … if cond,下条件断点;
这里补充说明下,在学习gdb时最好在使用gcc编译程序时加上-g参数带入调试信息,这样在调试时可以关联到源码的相关信息(不过在一些需要逆向的场景下本来也不会有源码,也可以选择提前适应通过标记函数地址的方式命名函数,这个过程也可以借助静态分析工具,比如IDA pro完成)
在这里插入图片描述

断点的查看、禁用/启用、删除

info b
delete b_id
在这里插入图片描述
disable b_id
enable b_id
i b中 Enb字段代表当前断点的激活状态,当为n时,该断点并不会生效
在这里插入图片描述

开始运行

run 与 start
run命令直接从头运行程序直至结束或遇到断点,而start命令则首先在main函数的起点设置一个断点,然后开始执行,便于从程序的起始处进行调试。下面就能看到,我们并没有对main下断点,当使用start时会自动停在main函数入口
在这里插入图片描述
当我们再使用run时,会先提示是否从头开始执行,选择y后我们看到程序停在了断点4,也就是puts函数中
在这里插入图片描述

继续运行

continue
run 和 start都是从头开始执行程序,那如何快速执行到下一个断点尼?continue
在这里插入图片描述
next 单步步过 step 单步步入
在这里插入图片描述
ni si汇编语言的单步步过和单步步入,这里有Windows动态调试经验的应该知道汇编的步过逻辑就是rip指向下个指令,遇到call往里走还是要靠si

finish 跳出函数:当我们步入到puts函数中不想继续执行的时候可以直接用finish函数跳出来回到main函数中
在这里插入图片描述

看点什么

disassemble

基本用法

直接使用,可以查看当前运行指令附近的汇编代码
在这里插入图片描述

查看目标地址附近的汇编代码

在这里插入图片描述

查看目标函数的汇编代码

在这里插入图片描述

与源码对照

在这里插入图片描述

info

info能查看的东西很多,暂时先写一些可能会比较常用的,有机会的话再试着遍历一遍吧

info args 显示当前函数的入参
info locals 显示局部变量
info b 显示断点信息
info reg 显示当前寄存器状态
info symbol 显示符号所在文件及其归属的section
info address 反查地址属于哪个符号

监视器 watch

打印print

内存查看X

X指令的f\u\t参数本质上是一种开关,当上一次输入确定后,下次只需要输入要查看的对象(addr)和显示的内存单元数量即可
这里只写几种常见搭配,有机会再遍历一下
x/[n][fu][t]addr
x/20i $rip 显示rip以下的20行汇编指令
x/i 0x5555555552e7:显示0x5555555552e7这个地址上的汇编指令
x/20b $rbp-0x10 显示[rbp-0x10]后20个字节的内容
x/20b 0x5555555552e7:显示0x5555555552e7指针指向的地址后20个字节的值

x/[n][fu][t]addr
n: (可选)要显示的内存单元数量。默认单位是byte
f: (可选)显示格式,如x(十六进制)、d(十进制)、u(无符号)、o(八进制)、t(二进制),a(地址),c(字符),s(字符串)等。
u: (可选)单位大小,如b(字节)、h(半字,即2字节)、w(字,通常4字节,在x86-64上是8字节)、g(巨型字,通常是8字节)。
t: (可选)当格式为s(字符串)时,限制输出的字符串长度。
addr: 要查看的内存地址。

用set做点手脚

set *addr = value
set *((unsigned int$ebp)) = value

  • 30
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值