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个字节,一开始它是这样的
我们输入abcde,栈变成这样了
完蛋了呀,int被修改了!这时候,对前面的int进行cmp,发现ZF是0了,所以进入了第一条语句,You are Admin被输出。
注意这里比较容易混淆的是,ebp是栈底,但是它的地址比较高。esp是栈顶,地址较低,int先存,它比较靠栈底(栈是从底部往上存的)。char后存,它挨在int后面。而当char分配的空间存满,它就会往后面覆盖,就把int的内容给覆盖了。
参考文章
致谢: