Desabilitar a proteção de pilha no Ubuntu para estouro de buffer sem sinalizadores do compilador C

10

Gostaria de experimentar alguns códigos de shell e quero desativar as proteções do linux.

Eu sei que poderia compilar usando sinalizadores, mas sei que existe outra maneira de desativar essas proteções em geral que simplesmente não me lembro. Pode me ajudar?

Phate
fonte

Respostas:

6

A proteção da pilha é feita pelo compilador (adicione alguns dados extras à pilha e esconda alguns fora de chamada, verifique a sanidade ao retornar). Não é possível desativar isso sem recompilar. É parte do ponto, realmente ...

vonbrand
fonte
6
O ASLR requer que o sistema operacional faça isso em tempo de execução. Os bits do NX também exigem suporte do sistema. Qual parte não pode ser desativada no tempo de execução?
Jeff Ferland
25

Para expandir o que vonbrand disse (corretamente, +1), existem duas partes na proteção de pilha do Linux.

Canários de pilha

Canários de pilha são o recurso imposto pelo compilador ao qual vonbrand se refere. Eles não podem ser desativados sem uma recompilação.

Para provar isso a si mesmo e ver como eles funcionam, use o seguinte código:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

int mybadfunction(char* a_bad_idea)
{
    char what[100];
    strcpy(what, a_bad_idea);
    printf("You passed %s\n", what);
}

int main(int argc, char** argv)
{
    printf("Tralalalaala\n");
    mybadfunction(argv[1]);
}

Agora compile isso ( gcc -fstack-protector -masm=intel -S test.c) em algo que o gnu gostaria de montar e ler a saída. O ponto importante é que, ao sair da mybadfunctionfunção, existe este pequeno pedaço de código:

    mov edx, DWORD PTR [ebp-12]
    xor edx, DWORD PTR gs:20
    je  .L2
    call    __stack_chk_fail

Como você pode imaginar, isso é pegar um cookie de pilha [ebp-12]e compará-lo com o valor em gs:20. Não combina? Em seguida, ele chama uma função __stack_chk_failna glibc que mata seu programa ali mesmo.

Existem maneiras de contornar isso em termos de exploração de gravação, mas a maneira mais fácil em termos de criação de um caso de teste de código de shell é compilar seu programa -fno-stack-protector.

Páginas não executáveis

Existem outras considerações nos sistemas Linux modernos. Se você usar o stub habitual de teste de código de shell:

char buffer[] = {...};

typedef void (* func)(void);

int main(int argc, char** argv)
{
    func f = (func) buffer;
    f();
    return 0;
}

O GCC / Linux moderno mapeará a .rodataseção do arquivo PE somente para leitura, sem permissões de execução. Você precisa desativar isso, o que pode ser feito usando o exemplo de código desta postagem do blog . Ideia básica: use mprotectpara adicionar as permissões desejadas às páginas nas quais os dados do código do shell residem.

Pilhas não executáveis

Se você for testar um cenário de exploração tradicional, por exemplo, meu código incorreto acima, com seu código de shell, também será necessário garantir que a pilha seja executável nos casos simples. O formato do arquivo PE contém um campo para determinar se a pilha é executável - você pode consultar e controlar isso com execstack . Para habilitar uma pilha executável, execute

execstack -s /path/to/myprog

Isso pode ser feito em programas arbitrários sem a necessidade de uma recompilação, mas não desabilita automaticamente os canários de pilha, pois eles são incorporados na compilação.

Bônus adicionado: aslr:

Para desligar isso echo 0 > /proc/sys/kernel/randomize_va_space.

Você acabou de dizer a alguém como explorar meu precioso pinguim?

Não. Qualquer exploração deve contornar canários de pilha (muito não triviais) e encontrar um programa com execstackset ou configurá-lo (o que significa que ele já pode executar comandos arbitrários de qualquer maneira) ou usar técnicas mais difíceis, como retornar à libc / return programação orientada.

Jonathan Leffler
fonte
0

Você pode desativar algumas proteções (detecção de quebra de pilha e execução da pilha) com essas opções.

--z execstack
-f no-stack-protector

Você também pode desativar o ASLR (randomização do layout do espaço de endereço) com o Bash com o comando:

echo 0 > /proc/sys/kernel/randomize_va_space
gotoat
fonte