CTF Codeby Games - PWN Цепи (writeup)

Всем привет.
Продолжаем продолжать.
Вариант решения таска.

По классике открываем IDA и смотрим main
IDA_main.png


Видим тут несколько функций (я переименовал функции, аргументы и пременные чтобы мне было удобно разбираться в алгоритме):
1. greeting - функция выводит свое приветствие. Ничего что может нам помочь нет.
2. enter_name - функция, принимающая пользовательский ввод. Может быть полезна, оставим на потом.
3. setting_current_position - функция устанавливающая + на карте. Ничего интересного тут нет.
4. moving - функция, принимающая от пльзователя AWSD и передвигает. В теории тут может быть выход за границу массива.

Просмотрев 2 интересные функции меня сильно заинтересовала enter_name
IDA_enter_name.PNG

и ее стек
IDA_enter_name_stack.PNG


Ага. Буфер размером 16 (0x10) байт, а читаем 256. BOF!
Посмотрев на функции, которые есть в бинаре не увидел ничего что поможет получить флаг, значит тут не просто ROP, а ret2libc. Значит надо ликать адреса в libc, получать эту саму libc, получать ее базу и получть шелл.

Для того, что бы ликнуть адреса нам нужно их напечатать, для этого у нас есть функции puts, write. Хорошо. Использовать буду puts, т.к. она проще, потому что там только один аргумент и передается он с помощью гаджета POP RDI
Адреса функций, которые беруться из Libc находятся в .got.
Также нам понадобится адрес функции enter_name, для того, что бы можно было заново эксплуатировать уязвимость. Таким образом считаем нагрузку для ROP, далее печатаем адрес функции из got, запомниаем его и ищем какая же у нас либа. Так как я ленивый и искать на libc.blukat.me мне было лень, то я автоматизировал это.

libc_leak.PNG

На скриншоте видно, как берутся гаджеты из бинаря, как формируется PADDING (то что всегда необходимо делать перед ROP), как происходит получение адресов функций из .got и их печать, как возвращаемся в enter_name.
И две функции, которые получают возможные libc по ликнутым адресам, скачивают первую либу и подгружают ее, что бы иметь возможность искать прямо в либе оффсеты system и /bin/sh, ну и посчитать базу libc.

НО, почему-то я не смог взять адрес enter_name из EXE.symbols/EXE.sym. Если кто-то знает почему он тут не взялся, расскажите, ооочень интересно.

Сам эксплоит выглядит вот так:
exploit.PNG


0. Предыдущие шаги + классический io = start()
1. Ликаем адреса и запоминаем их.
2. Пробуем получить либу в libc.blukat.me (оно почему-то сломалось =)). Если не получается, то ищем через Libc database. Если снова не получилось, то что-то не то, перестает эксплоит работать.
3. Получение оффсетов из либс и подсчет базы libc. Я сделал 2 раза, чтобы наверняка =)
4. Ищем /bin/sh\x00, почему именно так, потому что бывают /bin/sh без завершающего 0, что совсем не надо.
5. Ищем system для получения шелла.
6. Финальная нагрузка.
7. PWNED

Спасибо.
 
Всем привет.
Продолжаем продолжать.
Вариант решения таска.

По классике открываем IDA и смотрим main
Посмотреть вложение 75151

Видим тут несколько функций (я переименовал функции, аргументы и пременные чтобы мне было удобно разбираться в алгоритме):
1. greeting - функция выводит свое приветствие. Ничего что может нам помочь нет.
2. enter_name - функция, принимающая пользовательский ввод. Может быть полезна, оставим на потом.
3. setting_current_position - функция устанавливающая + на карте. Ничего интересного тут нет.
4. moving - функция, принимающая от пльзователя AWSD и передвигает. В теории тут может быть выход за границу массива.

Просмотрев 2 интересные функции меня сильно заинтересовала enter_name
Посмотреть вложение 75152
и ее стек
Посмотреть вложение 75153

Ага. Буфер размером 16 (0x10) байт, а читаем 256. BOF!
Посмотрев на функции, которые есть в бинаре не увидел ничего что поможет получить флаг, значит тут не просто ROP, а ret2libc. Значит надо ликать адреса в libc, получать эту саму libc, получать ее базу и получть шелл.

Для того, что бы ликнуть адреса нам нужно их напечатать, для этого у нас есть функции puts, write. Хорошо. Использовать буду puts, т.к. она проще, потому что там только один аргумент и передается он с помощью гаджета POP RDI
Адреса функций, которые беруться из Libc находятся в .got.
Также нам понадобится адрес функции enter_name, для того, что бы можно было заново эксплуатировать уязвимость. Таким образом считаем нагрузку для ROP, далее печатаем адрес функции из got, запомниаем его и ищем какая же у нас либа. Так как я ленивый и искать на libc.blukat.me мне было лень, то я автоматизировал это.

Посмотреть вложение 75154
На скриншоте видно, как берутся гаджеты из бинаря, как формируется PADDING (то что всегда необходимо делать перед ROP), как происходит получение адресов функций из .got и их печать, как возвращаемся в enter_name.
И две функции, которые получают возможные libc по ликнутым адресам, скачивают первую либу и подгружают ее, что бы иметь возможность искать прямо в либе оффсеты system и /bin/sh, ну и посчитать базу libc.

НО, почему-то я не смог взять адрес enter_name из EXE.symbols/EXE.sym. Если кто-то знает почему он тут не взялся, расскажите, ооочень интересно.

Сам эксплоит выглядит вот так:
Посмотреть вложение 75155

0. Предыдущие шаги + классический io = start()
1. Ликаем адреса и запоминаем их.
2. Пробуем получить либу в libc.blukat.me (оно почему-то сломалось =)). Если не получается, то ищем через Libc database. Если снова не получилось, то что-то не то, перестает эксплоит работать.
3. Получение оффсетов из либс и подсчет базы libc. Я сделал 2 раза, чтобы наверняка =)
4. Ищем /bin/sh\x00, почему именно так, потому что бывают /bin/sh без завершающего 0, что совсем не надо.
5. Ищем system для получения шелла.
6. Финальная нагрузка.
7. PWNED

Спасибо.
Ничего себе, первый раз в жизни увидел моржовый оператор
Ахтунг!
 
  • Нравится
Реакции: yetiraki
Мы в соцсетях:

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