讲解pwngdb的用法,以csapp的bomb lab phase_1为例

参考资料

  • Guide to Faster, Less Frustrating Debugging

什么情况下会使用gbd

  • 需要逆向ELF文件时(掌握gdb的使用,是二进制安全的基本功)
  • 开发程序时,程序执行结果不符合预期

动态调试ELF文件可以使用另外一种方法:IDA的远程linux动态调试。个人觉得使用ida调试更为方便,因为ida是图形化界面,那么可以使用鼠标交互,比如通过鼠标光标确定打断点的位置等等。而且IDA具有反编译功能,对初学者较为友好。

为什么使用gbd呢
调试程序时,我们可能习惯使用printf , cout函数直接将变量打印在控制台上。如果用printf作为调试的主要方式,好处是这种做法确实方便,但以下缺点也会大大影响调试的进度(以及个人心情)

  • printf一个变量后,发现那个变量的值是正确的,需要继续printf其他变量
  • 大量printf会将编写的代码变得惨不忍睹,在测试完后,还需要将编写的printf删除掉
  • 如果我们要检查一个结构体变量有没有符合预期,使用printf将这个变量的所有属性打印出来十分繁琐。(虽然我更喜欢用IDE自带的调试功能观察2333)

所以我个人认为,在编写程序时,可以适当使用printf作为调试的手段,但如果太过依赖它,反而会事倍功半

接下来说一下gbd的好处:

  • 需要掌握的命令少,和markdown一样,熟练使用了就能转换成自己的肌肉记忆。
  • 具有一个调试器应该有的功能,如可以显示运行程序的寄存器,运行时栈堆,支持反汇编等等 (虽然使用体验确实比不上支持图形化的调试器2333)

常用命令

知乎:GDB使用详解


介绍一下打断点的方式

  • b functionName: 在函数的入口处添加断点
  • b line: 在文件的第line行添加断点
  • b *adderess 在某一个地址添加断点

解下来以csapp的第二个lab为例,讲解pwngdb的使用

这篇博客假设大家已经有汇编语言基础,因此我不会花很多篇幅在汇编语句讲解上 😃

我之所以使用pwngdb,是因为之前做ctf pwn题目时配置好了。pwngdb比起原版的gdb新增了一些独有的指令,尤其是在堆的方面。

csapp lab的网页: https://csapp.cs.cmu.edu/3e/labs.html

分析整个程序的流程如下:
输入disassemble main观察main函数反汇编的结果

0x0000000000400e2d <+141>:	call   0x400b10 <puts@plt>0x0000000000400e32 <+146>:	call   0x40149e <read_line>0x0000000000400e37 <+151>:	mov    rdi,rax0x0000000000400e3a <+154>:	call   0x400ee0 <phase_1>0x0000000000400e3f <+159>:	call   0x4015c4 <phase_defused>0x0000000000400e44 <+164>:	mov    edi,0x4023a80x0000000000400e49 <+169>:	call   0x400b10 <puts@plt>0x0000000000400e4e <+174>:	call   0x40149e <read_line>0x0000000000400e53 <+179>:	mov    rdi,rax0x0000000000400e56 <+182>:	call   0x400efc <phase_2>0x0000000000400e5b <+187>:	call   0x4015c4 <phase_defused>0x0000000000400e60 <+192>:	mov    edi,0x4022ed0x0000000000400e65 <+197>:	call   0x400b10 <puts@plt>0x0000000000400e6a <+202>:	call   0x40149e <read_line>0x0000000000400e6f <+207>:	mov    rdi,rax0x0000000000400e72 <+210>:	call   0x400f43 <phase_3>0x0000000000400e77 <+215>:	call   0x4015c4 <phase_defused>0x0000000000400e7c <+220>:	mov    edi,0x40230b0x0000000000400e81 <+225>:	call   0x400b10 <puts@plt>0x0000000000400e86 <+230>:	call   0x40149e <read_line>0x0000000000400e8b <+235>:	mov    rdi,rax0x0000000000400e8e <+238>:	call   0x40100c <phase_4>0x0000000000400e93 <+243>:	call   0x4015c4 <phase_defused>0x0000000000400e98 <+248>:	mov    edi,0x4023d80x0000000000400e9d <+253>:	call   0x400b10 <puts@plt>0x0000000000400ea2 <+258>:	call   0x40149e <read_line>0x0000000000400ea7 <+263>:	mov    rdi,rax0x0000000000400eaa <+266>:	call   0x401062 <phase_5>0x0000000000400eaf <+271>:	call   0x4015c4 <phase_defused>0x0000000000400eb4 <+276>:	mov    edi,0x40231a0x0000000000400eb9 <+281>:	call   0x400b10 <puts@plt>0x0000000000400ebe <+286>:	call   0x40149e <read_line>0x0000000000400ec3 <+291>:	mov    rdi,rax0x0000000000400ec6 <+294>:	call   0x4010f4 <phase_6>0x0000000000400ecb <+299>:	call   0x4015c4 <phase_defused>

一般来说,函数的返回值会放在eax寄存器中。所以以下的代码

   0x0000000000400e32 <+146>:	call   0x40149e <read_line>0x0000000000400e37 <+151>:	mov    rdi,rax0x0000000000400e3a <+154>:	call   0x400ee0 <phase_1>

read_line读取的字符串先放在rax寄存器中,再经过mov rdi,rax 放在rdi寄存器中。

接下来分析第一关卡:
b phase_1打下断点,r运行程序。接着输入一串字符串,为了表示方便,我称其为input
按下s 程序单步运行,结果如下图。
在这里插入图片描述

在上面的截图中,程序被蓝色的横线分为了三个区域

  • 最上面的是寄存器区域,用于显示各个寄存器的值。寄存器有很多作用:比如数据可以存储在寄存器里,数据也可以通过寄存器在函数之间传递。高级语言中的if , while等等功能都可以通过汇编语言实现,这需要使用到寄存器:比如将数据与寄存器中的值进行比较,如果小于就进行跳转命令等等。
  • 中间区域是反汇编区域,这是程序的运行代码。绿色箭头表示程序当前位置。
  • 最下面的区域是栈区。栈区存放函数的参数,返回地址,局部变量等等内容

如果使用gdb,按下s的时候可能不会跳出这么多内容
可以使用以下命令打印寄存器的值

info registers

或者是

i r

要打印栈的内容和栈帧信息,可以执行以下命令:

info frame

或者是

i f

继续单步执行。
在这里插入图片描述
这段代码告诉我们传入strings_not_equal的参数是什么
一个参数是我们输入的input字符串 。 另一个参数是程序自带的字符串Border relations with Canada have never been better.

解释一下:rdi: 0x003780 <- 0x333231

0x003780 表示rdi寄存器指向内存地址
0x333231 表示这段地址里存放的值
123 是0x333231 ascii码对应的字符

按下s ,分析strings_not_equal函数的代码

0x401338 <strings_not_equal>       push   r120x40133a <strings_not_equal+2>     push   rbp0x40133b <strings_not_equal+3>     push   rbx0x40133c <strings_not_equal+4>     mov    rbx, rdi0x40133f <strings_not_equal+7>     mov    rbp, rsi0x401342 <strings_not_equal+10>    call   string_length                      <string_length>0x401347 <strings_not_equal+15>    mov    r12d, eax0x40134a <strings_not_equal+18>    mov    rdi, rbp0x40134d <strings_not_equal+21>    call   string_length                      <string_length>0x401352 <strings_not_equal+26>    mov    edx, 10x401357 <strings_not_equal+31>    cmp    r12d, eax

这段代码调用string_length函数,用于取得字符串的长度。接着使用cmp r12d , eax比较两个传入字符串的长度。如果长度一样,那么第一关就过了。

接下来验证我们的想法:
分别在0x401342 和0x40134d添加临时断点,tb *0x401342 tb *0x40134d。然后按下c 运行到断点。按下n让函数执行完毕,观察rax 寄存器的值

第一个string_length函数执行完毕的寄存器页面
在这里插入图片描述

第二个string_lenth函数执行完毕的寄存器页面
在这里插入图片描述

按下r重新运行。输入字符串Border relations with Canada have never been better.
这样关卡1就通过了。

使用gdb是熟能生巧的过程,只要多练就能掌握这个软件的使用😃
在这里插入图片描述


照例meme时间

当导师发现你没有在规定时间内完成任务时 be like↓
在这里插入图片描述
摸了一周鱼的我 be like↓
在这里插入图片描述
不多说了,要赶紧完成java web的管理系统和qt的文件编辑器了 😭

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/785580.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java引入下载的依赖包配置

maven中央仓库没有依赖包&#xff0c;但是个别网站有可以下载的依赖包下载依赖包并引入的配置在maven工程目录下建立lib目录&#xff0c;并将下载的jar包放入在pom.xml文件中配置本地依赖 <dependency><groupId>org.ejml</groupId><artifactId>…

10.循环位移

问题描述 给定一个正好六位的正整数t&#xff0c;请将循环左移一位后输出。 所谓循环左移一位&#xff0c;是指将原来的十万位变为个位&#xff0c;原来的万位到个位向左移动依次变为十万位到十位。 例如:194910左移一位变为949101 又如:987123左移一位变为871239 输入格式 输入…

Java基础学习: hutool之CollUtil集合操作工具类

文章目录 一、介绍二、Hutool集合操作示例1、判断是否为空&#xff1a;2、判断是否非空3、集合是否包含某个元素4、集合是否包含某些元素5、集合是否不包含某些元素6、两个集合的交集操作7、两个集合的并集操作8、两个集合的差集操作9、集合元素是否相等10、集合转换为字符串&a…

LeetCode——动态规划(Java)

动态规划 简介[简单] 509. 斐波那契数[简单] 70. 爬楼梯[简单] 746. 使用最小花费爬楼梯[中等] 62. 不同路径[中等] 63. 不同路径 II[中等] 343. 整数拆分[中等] 96. 不同的二叉搜索树背包问题01背包[中等] 416. 分割等和子集[中等] 1049. 最后一块石头的重量 II[中等] 494. 目…

Nginx: proxy_set_header 与 add_header 区别

proxy_set_header 1 &#xff09;概述 proxy_set_header 和 add_header 是 Nginx 配置中两个不同的指令, 它们各自有不同的用途proxy_set_header 指令用于修改转发到代理服务器&#xff08;通常是后端应用服务器&#xff09;的 HTTP 请求头它允许您设置或覆盖请求头中的字段&a…

【游戏分析】FPS游戏狩猎百发百中

某某游戏狩猎玩法及其类似于FPS游戏 即3D射击 所以同样拥有 自动瞄准功能和爆头功能 想达到百发百中我们就要精准的计算出3D朝向值 读取人物坐标 遍历怪物,读取怪物坐标比较简单,不过多陈诉 朝向自然而然一定是我们和敌人的坐标计算出来的 那么怎么计算的呢&#xff1f; 我…

JAVA学习笔记21(访问修饰符)

1.访问修饰符 ​ *基本介绍 ​ java提供四种访问控制修饰符号&#xff0c;用于控制方法和属性(成员变量)的访问权限(范围) 1.公开级别&#xff1a;用public修饰&#xff0c;对外公开 2.受保护级别&#xff1a;用protected修饰&#xff0c;对子类和同一个包中的类公开 3.默…

基础知识系列

文章目录 一、linux passwd文件 一、linux passwd文件 linux中&#xff0c;用户名存放在/etc/passwd中&#xff0c;密码存放在/etc/shadow中。/etc/passwd只允许root用户可读可写&#xff0c;root组的用户可读&#xff0c;其他用户不可读不可写不可执行。/etc/shadow只允许roo…

手写简易操作系统(二十)--实现堆内存管理

前情提要 前面我们实现了 0x80 中断&#xff0c;并实现了两个中断调用&#xff0c;getpid 和 write&#xff0c;其中 write 还由于没有实现文件系统&#xff0c;是个残血版&#xff0c;这一节我们实现堆内存管理。 一、arena 在计算机科学中&#xff0c;“arena” 内存管理通…

DC-9靶场

一.环境搭建 1.下载地址 靶机下载地址&#xff1a;https://download.vulnhub.com/dc/DC-9.zip 2.虚拟机配置 设置虚拟机为nat&#xff0c;遇到错误点重试和是 开启虚拟机如下图所示 二.开始渗透 1. 信息收集 查找靶机的ip地址 arp-scan -l 发现靶机的ip地址为192.168.11…

C++从入门到精通——auto的使用

auto 前言一、auto类型别名思考二、auto简介三、auto的使用细则auto与指针和引用结合起来使用在同一行定义多个变量auto不能推导的场景auto不能作为函数的参数auto不能直接用来声明数组 lambda表达式 前言 C的auto关键字用于自动推导变量的类型&#xff0c;让编译器根据变量的…

如何使用单片机 pwm 控制 mos 管?

目录 选择适合的硬件 连接电路 编写代码 参考示例 程序一 程序二 测试与调试 注意事项 使用单片机&#xff08;如常见的Arduino、STM32等&#xff09;通过PWM&#xff08;脉冲宽度调制&#xff09;控制MOS管&#xff08;金属氧化物半导体场效应管&#xff09;是一种常见…

Linux使用Docker部署RStudio Server结合内网穿透实现公网访问本地服务

文章目录 前言1. 安装RStudio Server2. 本地访问3. Linux 安装cpolar4. 配置RStudio server公网访问地址5. 公网远程访问RStudio6. 固定RStudio公网地址 前言 RStudio Server 使你能够在 Linux 服务器上运行你所熟悉和喜爱的 RStudio IDE&#xff0c;并通过 Web 浏览器进行访问…

Java如何使用nignx实现静态资源服务

在Java应用中&#xff0c;通常我们不会直接用Nginx来服务静态资源&#xff0c;而是会让Java应用&#xff08;如Spring Boot应用&#xff09;处理动态请求&#xff0c;而将静态资源&#xff08;如HTML、CSS、JS、图片等&#xff09;交给Nginx来服务。这样的架构有很多好处&#…

标准版IP地址证书

IP地址证书是一种网络安全工具&#xff0c;用于确保互联网通信中IP地址的所有权和真实性。它类似于为网站颁发的SSL/TLS证书&#xff0c;但专门针对IP地址。这种证书由受信任的第三方机构&#xff08;如证书颁发机构&#xff09;签发&#xff0c;包含公钥、所有者信息和有效期。…

抖店被清退身份证还能入驻吗?被清退保证金可以退吗?

在抖音平台上开设自己的抖店是许多人追求的梦想&#xff0c;但有时候由于一些原因&#xff0c;抖店可能会被清退。此时&#xff0c;很多人会担心自己的身份证是否还能用来再次入驻。 一、抖店被清退身份证还能入驻吗&#xff1f; 首先&#xff0c;需要明确的是&#xff0c;抖…

【Linux】开始掌握进程控制吧!

送给大家一句话&#xff1a; 我并不期待人生可以一直过得很顺利&#xff0c;但我希望碰到人生难关的时候&#xff0c;自己可以是它的对手。—— 加缪 开始学习进程控制 1 前言2 进程创建2.1 fork函数初识2.2 fork函数返回值2.3 写时拷贝2.4 fork常规用法2.5 fork调用失败的原因…

Free RTOS day2

1.思维导图 2.使用PWMADC光敏电阻完成光控灯的实验 int adc_val0;//用于保存ADC采样得到的数值 float volt0;//用于保存电压值 int main(void) {MX_GPIO_Init();MX_DMA_Init();MX_TIM1_Init();MX_USART1_UART_Init();MX_ADC_Init();MX_TIM3_Init();HAL_TIM_PWM_Start(&hti…

【linux】基础IO(一)

文件只有站在系统层面才能彻底理解 简单回顾一下文件&#xff1a; 首先我们要明确一点&#xff0c;我们说的打开文件不是写下fopen就打开文件&#xff0c;而是当我们的进程运行起来&#xff0c;进程打开的文件。 我们在C语言一般都会使用过如下的代码进行向文件中写入 但是除…

GUID测试程序

全局唯一标识符&#xff08;GUID&#xff0c;Globally Unique Identifier&#xff09;是一种由算法生成的二进制长度为128位的数字标识符。GUID主要用于在拥有多个节点、多台计算机的网络或系统中。在理想情况下&#xff0c;任何计算机和计算机集群都不会生成两个相同的GUID。G…