🗒️理解栈溢出并使用 gdb 来调试 C 语言程序
2023-5-2
| 2023-5-27
0  |  Read Time 0 min
type
status
date
slug
summary
tags
category
icon
password

编写并编译

编写一个简单的C语言程序,比如
保存为 main.c ,并执行 gcc -g main.c main
然后使用 gdb main 开始执行

使用asm布局调试

执行 layout asm 开始调试,layout split能看到代码

设置 intel 语法

使用 show disassembly-flavor 可以看到使用的是att语法,可以通过 set disassembly-flavor intel 切换为intel语法

断点调试

使用 b 11 来给第11行代码设置断点,使用ni,si来对每条指令进行断点,使用n,s来对每行代码进行断点
ni和si差别就是,si会进入函数,ni不会

起始代码解析

先写一个简单的程序
 

缓冲区溢出利用原理

看了上面的解释,其实溢出原理就很好理解了
因为一开始,会将栈底指针存到栈中,然后再开始下一轮的操作,而存储栈数据的时候,会从栈顶不断往下存,所以一旦覆盖掉了之前存的栈底指针,就会导致,最终这个函数结束的时候,通过leave想要返回,就会返回到被覆盖的栈底指针,最终访问到某个本来不属于这个函数的内容。
好比如说,我给栈开拓的空间是0x10,但是我手贱,我偏偏存到0x14,把之前的栈底指针地址给覆盖了,然后整个函数执行完毕了,函数要返回带它来的故乡了。其实也不一定要等到整个函数执行完毕,比如说想修改不属于这个栈的外面的内容,就可以通过这种方式修改。亦或者是修改属于同一个函数的其他变量的内容,也可以这样修改

例子

下面用一个简单的例子来说明这个问题
其他汇编语句基本相同,关键在于,给int分配的空间为四个字节,给char分配的也是4个字节,一开始它是这样的
notion image
我们输入abcde,栈变成这样了
notion image
完蛋了呀,int被修改了!这时候,对前面的int进行cmp,发现ZF是0了,所以进入了第一条语句,You are Admin被输出。
注意这里比较容易混淆的是,ebp是栈底,但是它的地址比较高。esp是栈顶,地址较低,int先存,它比较靠栈底(栈是从底部往上存的)。char后存,它挨在int后面。而当char分配的空间存满,它就会往后面覆盖,就把int的内容给覆盖了。

参考文章

致谢:
💡
U2F sdGVkX1
 
 
学习思考
  • 学习
  • 从CTF.Show签到题入手尝试逆向题[Klee-CTF] VulnStack 靶场实战 一 (1)
    • GitTalk
    Catalog