CSAPP AttackLab 对 getbuf函数 的GDB调试
一、调试前的准备:
原因:
- 想要跳转到touch1或touch2,不可或缺地需要知道这两个函数的地址。
- 我们需要查明getbuf函数对buf字符数组究竟分配了多少空间,buf字符数组的首地址距离分配该变量的函数的返回地址究竟有多远。
- 对getbuf函数的断点调试,也需要函数中各条指令的地址进行支持。
在对getbuf函数进行GDB调试前,我们需要先对ctarget进行反汇编,以获得一些ctarget中指令级别的信息。
(可以获得ctarget由哪些函数构成(以汇编形式表示),同时可以获得函数以及其内部每一条汇编指令对应的地址)。
至于getbuf函数运行时的栈帧情况,则要通过GDB调试来获得。
操作:

objdump – d ctarget > code_ctarget.txt
一些函数的截图:
getbuf :

touch1 :

touch2 :

二、对ctarget中getbuf函数进行GDB调试:
首先在ctarget文件的目录下打开终端

然后通过GDB 打开 ctarget

设置断点

break *0x4017ac
运行

run -q
查看寄存器情况

info registers
单独查看%rsp

print $rsp
三、调试中遇到的问题:
有的同学在用GDB对getbuf调试时,调试出了两种%rsp指示的地址
一个是0x5561dca0 ,另一个是0x5561dc78
就结论而言,0x5561dc78才是我们要的数。
那么0x5561dca0又是如何得来的呢?
当时在从网络中搜寻GDB调试方法时,搜到了:

break getbuf
可以通过函数名来设置断点的方法(这也就是调试出“问题栈地址”的罪魁祸首)
使用”break getbuf” GDB会自动地在对应的函数中设置一个断点
(然而根据断点设置的不同,寄存器的值是会产生差异的,即使是在一个函数里运行,%rsp的值也是可能发生变化的)
注意观察断点设置的位置,在0x4017a8的位置(等于指令break *0x4017a8的效果)
在到之前反汇编得到的汇编指令文件中观察

破案了!
break getbuf 按照它的想法在getbuf函数中找了一点当断点,
然而它却找了分配函数栈帧空间的指令(sub $0x28 , %rsp)当断点,
(准确来说断点是设在了该条指令的前边)
所以,GDB就把getbuf函数分配空间前的寄存器信息显示出来了

单独看%rsp寄存器的

所以在对getbuf进行GDB调试时会出现两种%rsp的信息,进而产生了XX影响。
由此可知,
- 通过函数名设置的断点不一定是我们想要的,我们自己应该根据程序的指令信息手动地设置断点位置,以达到我们所想要的调试情况。
- 在一个函数中,根据断点位置设置的不同,寄存器也很有可能处于不同的状态,所以我们在设置断点时,应根据指令结构按照需求合理地设置断点。
另外补充一点0x5561dc78是直接猜中了get输入的第一个字节的位置,但实际栈地址可不是这么容易猜的,往往是先猜个大概,再通过空操作滑过去。
如果返回地址没有接入合适的指令操作,会报段错误。
另外原本buf字符数组的区域十分有限,下面是起始区域,上面是返回地址区域,代码量显示比较大,建议把攻击代码放到返回地址再往上,那里空间比较充分,(由于指令读的时候是从低到高一条一条的往上读,建议在攻击代码的下侧垫入 大量的 nop 空指令 以接收返回地址)
输入字符串的结构大致为 从低到高 :
原本 buf字符数组的 空间 (0x24 40个字节大小) getbuf函数的返回test函数的返回地址 (0x8 一个字(64位) , 8个字节的大小) nop滑雪撬区域 攻击代码区域
另外 0x5561dca0 是 getbuf函数 分配空间前 %rsp 指向的 栈 地址,根据代码结构分析,换言之就是返回地址的位置 ,所以 0x5561dca0 直接指向了 返回地址 ,这个位置就是要放返回地址 ,没法放 nop 空操作 或 攻击代码 ,所以 在实际改写返回地址时 尽量 把返回地址 再往上写高一些 , 因为再往上的区域就可以设置 nop 空操作了 ,新的返回地址 再加上 nop滑雪撬 区域 ,便可以顺利地将程序 引入到要执行代码的区域了
这是对CSAPP AttackLab 注入 Level2 的相关分析,欢迎大家在评论区进行交流讨论,增加编写代码的安全意识,编出检查缓冲区溢出的相对安全的代码

浙公网安备 33010602011771号