Мне трудно понять, как отключить защиту стека в OS X 10.10.5 (Yosemite). Я как бы собирал многообещающие флаги gcc из различных потоков в Интернете, но пока не смог отключить защиту. В настоящее время я компилирую свою программу с помощью:
gcc -g3 -std=c99 -pedantic -Wall -m32 -fno-stack-protector -fno-sanitize=address -D_FORTIFY_SOURCE=0 -Wl,-no_pie -o program program.c
Но когда я пытаюсь разбить стек, я ошибаюсь.
Я попробовал ту же программу на Red Hat Enterprise Linux Server 7.2 (Maipo), и после корректировки различий адресов памяти, где это уместно, у меня не было проблем с разрушением стека после компиляции с помощью:
gcc -g3 -std=c99 -pedantic -Wall -m32 -fno-stack-protector -o program program.c
Также, вероятно, стоит отметить, что, как и на большинстве компьютеров Mac, gcc на моей машине является символической ссылкой на clang (версия Apple LLVM 7.0.0 (clang-700.0.72)).
Как я могу отключить защиту стека Yosemite?
дополнительные детали
Фиктивная программа, с которой я работаю:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int authenticate() {
char password[10];
printf("Enter password: ");
scanf("%s", password);
return strcmp(password, "1234567890") == 0;
}
void success() {
printf("Access granted\n");
exit(0);
}
void failure() {
printf("Access denied\n");
exit(1);
}
int main(int argc, char** argv) {
if (authenticate()) {
success();
} else {
failure();
}
}
Когда я запускаю otool -tv program
, я отмечаю следующее:
Подпрограмма success
, к которой я хочу перейти, находится по адресу 0x00001e70
.
Инструкция, к которой мы обычно возвращаемся после authenticate
, находится по адресу 0x00001efe
.
Когда я запускаю gdb
после ввода фиктивного пароля «xxxxxxxxxx» и проверки буфера с помощью x/30xb &password
, я наблюдаю:
0xbffffc32: 0x78 0x78 0x78 0x78 0x78 0x78 0x78 0x78
0xbffffc3a: 0x78 0x78 0x00 0x00 0x00 0x00 0x00 0x00
0xbffffc42: 0x00 0x00 0xfc 0xfc 0xff 0xbf 0x68 0xfc
0xbffffc4a: 0xff 0xbf 0xfe 0x1e 0x00 0x00
Мы хотим заменить 27-й 0xfe
байт на 0x70
.
Когда я пытаюсь разбить стек следующим образом:
printf "xxxxxxxxxxxxxxxxxxxxxxxxxx\x70" | ./program # 26 bytes of junk, followed by 0x70
Я получаю segfault.