gamedev

Descrição do Desafio:

Autor: bliutech Categoria: pwn Descrição:

You've heard of rogue-likes, but have you heard of heap-likes?

Arquivos

Arquivo
Descrição

chall

Executável.

chall.c

Código-fonte.

Dockerfile

Arquivo docker.

ld-linux-x86-64.so.2

Linker da libc

libc.so.6

libc

solve.py

Script em Python que resolve o desafio.

📥 Download: Arquivos

Passo a Passo da Solução

1. Análise dos arquivos fornecidos

Este desafio fornece tanto o executável como o código-fonte. Analisando o código, vemos que ele é mais complexo, no sentido de não ser apenas 1 ou 2 funções, porém sua temática é bem interessante, já que ele permite o usuário criar 8 níveis de "dungeons", escrever dados em cada um desses níveis, ler o que está nesses níveis, e como qualquer rogue-like, acessar tais níveis.

Para cada nível acessado, as opções são as mesmas, criar, escrever, ler, e acessar.

Analisando a fundo cada função, podemos identificar algumas coisas interessantes:

  • Temos um vazamento do endereço da main(), dessa forma já podemos burlar o PIE do executável.

  • Na função de escrever no nível, nós podemos escrever 0x20 bytes a mais do que ele armazena.

  • A função de explorar não faz nenhuma verificação em relação ao endereço, ou seja, podemos acessar qualquer endereço que esteja na índice inserido.

Com isso uma ideia já fica em mente, com o overflow podemos sobrescrever o chunk da frente para que um de seus índices contenha um endereço da tabela .got, e dessa forma, podemos acessar esse endereço, ler o que tem nele para vazar um endereço da libc, e em seguida sobrescrever esse valor para ser a função system(). A questão fica, qual função da tabela .got devemos sobrescrever, por que ainda temos que passar /bin/sh para a função.

E é aí, que olhando para a função get_num(), identificamos nosso alvo, a função atoi() que é chamada como atoi(buf).

2. Exploit

Já sabendo o que fazer, a solução se torna bem simples, só falta descobrir o offset para chegar nos dados (curr->data, se curr for exatamente o endereço da .got, nós não escreveremos nela e nem vazaremos o endereço), e descobrir quantos bytes escrever até chegar no índice do próximo chunk. Com o pwndbg, e o comando vis_heap_chunks, podemos descobrir a quantidade de bytes.

Nota: No pwndbg os chunks saem coloridos facilitando a leitura.

Com isso descobrimos que devemos escrever 48 caracteres, e os próximos começarão a escrever nos índices daquele chunk. Agora, o offset podemos descobrir direto pelo assembly.

Note que antes de chamar a fgets, ele passa como buffer o curr + 0x40, e aí está o nosso offset.

Flag

lactf{ro9u3_LIk3_No7_R34LlY_RO9U3_H34P_LIK3_nO7_r34llY_H34P}

Autor da WriteUp

Membro de Exploitation - HenriUz

Atualizado