栈
特性:先进先出
内存的一片区间,栈型结构管理,高地址向低地址增长。
esp指向栈顶
push sth -> [esp]=sth,esp=esp-4
pop sth -> sth=[esp],esp=esp+4
以栈帧切割,保存函数调用信息和局部变量
调用约定
函数调用:call,ret
调用约定:_stdcall,cdecl,fastcall,thiscall,nakecall,_pascal
参数传递:取决于调用约定,x86默认从右到左,x64优先寄存器,然后用栈
pc程序计数器,用于指示当前将要执行的下一条机器指令的内存地址
call func -> push pc,jmp func
leave -> mov esp,ebp, pop ebp
ret -> pop pc
栈溢出保护机制
1.NX/DEP
2.ASLR
3.STACK Canary/Cookie
4.PIE
5.RELNO
栈溢出利用方法
1.ROP
- 1.用法
- 1.第一次触发漏洞,通过ROP泄露libc的address(如puts_got),计算system地址,然后返回到一个可以重现触发漏洞的位置(如main),再次触发漏洞,通过ROP调用system(“/bin/sh”)
- 2.直接execve("/bin/sh",["/bin/sh"],NULL),通常在静态链接时比较常用
2.SROP
- 1.用法
- 1.系统Signal Dispatch之前会所有寄存器压栈,然后调用signal handler,signal handler返回时会将栈内容还原
- 2.如果实现填充栈,然后直接调用signal handler,那在返回的时候就可以控制寄存器的值
3.BROP
- 1.用法
- 1.目标binary未给出
- 2.必须先存在一个已知的stack overflow漏洞,而且攻击者知道如何揭发这个漏洞
- 3.服务器进程在crash之后会重新激活,复活的进程不会被re-hand
4.stack pivot
- 1.用法
- 1.存在地址一直且内容可控的buffer
- 1.bss段,由于bss段尾端常有大量空余空间,所以bss段尾端也往往是stack pivot的目标
- 2.堆块,如果堆地址已泄且堆上的数据可控,那堆也可以作为stack pivot的目标
- 2.控制流可劫持
- 3.存在劫持栈指针的gadgets
- 1.如pop esp,ret,具体binary具体分析
- 1.存在地址一直且内容可控的buffer
5.ret2dl_resovle,fake linkmap绕过ASLR
- 1.用法
- 1.动态链接就是从函数名到地址的转换过程,所以可以通过动态链接器解析任何函数,无需leak
- 2.理论上任何可以stack pivot且FULLRELRO未开额题目都可以利用这种技术
6.低地址12bit不变,Partial Overwrite绕过ASLR
- 用法
- PIE开启时,一个32地址的高20位被随机化,低12bit不变。
- 改写低12bit绕过PIE,不仅在栈溢出使用,各种利用都经常使用。
7.leak canary,overwrite canary,改写指针与局部变量绕过stack canary
- 用法
- 以上所有套路,遇到stack canary均无效
- 不覆盖stack canary,只覆盖stack canary前的局部变量、指针
- 几乎不行,编译器会根据占用内存大小从小到大排列变量
- 某些极限情况可以,一般都是精心构造的
- leak canary
- printf泄露,canary一般从00开始
- overwrite canary
- canary在TLS, TLS地址被随机化
8.溢出位数不够:覆盖ebp,Partial Overwrite
-
用法
-可以覆盖Func2的ebp,会影响到Func1的esp,进而影响func1的ip1 2 3 4 5 6 7 8 9
Func1: call func2 leave(mov esp ebp, pop ebp) ret(pop ip) Func2: stack overflow leave(move esp, ebp, pop ebp) ret(pop ip)