PDA

Просмотр полной версии : Эксплуатация бинарных уязвимостей или учимся "пывнить" (Часть 1 / Stack0)


CyberDen
15.07.2024, 02:32
Всем привет! В этой серии райтапов мы разберем известные задания по эксплуатации бинарных уязвимостей с Exploit Exercises (там их больше нет, поэтому я их перекомпилировал под Win). О том, что такое Buffer Overflow прекрасно и с примерами написано ТУТ (https://forum.antichat.xyz/threads/1641110/) (отличная статья от @Mogen (https://forum.antichat.xyz/members/2651428/)). Кстати говоря, много крутых задачек на тему PWN есть на Antichat, так что рекомендую

Часть 4 (https://forum.antichat.xyz/threads/1643746/)
Часть 3 (https://forum.antichat.xyz/threads/1643731/)
Часть 2 (https://forum.antichat.xyz/threads/1643714/)

Итак... мы будем решать наши задачки, используя статический (Ghidra) и динамический анализ (x64dbg). И самое главное, мы будем делать это без исходников уязвимой программы, в отличие от того, как это сделано ТУТ и ТУТ (https://forum.antichat.xyz/threads/1627042/).

Stack0

Для решения этой задачки я буду использовать свою "песко-реверс-лабораторию", где у меня уже все "стоит"

https://forum.antichat.xyz/attachments/29112897/1.png

Сначала будем делать "статику". Запускаем гидру и закидываем программу, которую будем "пывнить".

https://forum.antichat.xyz/attachments/29112897/2.png

Запускаем анализ:

https://forum.antichat.xyz/attachments/29112897/3.png

Получаемдизасм-листинг и декомпилированный код:

https://forum.antichat.xyz/attachments/29112897/4.png

Переименовываем переменные (тут кода мало - не сильно нужно, но привычка хорошая ):

https://forum.antichat.xyz/attachments/29112897/5.png

Итак, видим, что у нас есть массив buf на 64 символа и "плохая" функция gets(). Также у нас есть условие: если переменная var1 = 0, то мы получим "Try again". Соответственно, чтобы попасть в ветку else, нам нужно как-то модифицировать переменную var1. Выделяем код и запоминаем инструкцию "test eax, eax", она нам пригодится чуть позже.

https://forum.antichat.xyz/attachments/29112897/6.png

Переходим к "динамике". Открываем программу в x64dbg, смотрим strings и находим тот самый "Try again", проваливаемся по инструкции, видим "test eax, eax" и "test al, al". Ставим на любой из этих инструкций точку останова.

https://forum.antichat.xyz/attachments/29112897/7.png

https://forum.antichat.xyz/attachments/29112897/8.png

"Подаем на вход" 10 символов.

https://forum.antichat.xyz/attachments/29112897/9.png

Видим, что регистр EAX никак не поменялся (равен 0). P.S. Инструкция "test eax, eax" в языке ассемблера x86/x64 выполняет битовый логический оператор AND между регистром eax и самим собой. Инструкция "test" не изменяет значение в регистре eax, но влияет на флаги процессора, в частности, на флаг нуля (ZF), который устанавливается, если результат операции AND равен нулю. Это означает, что если eax содержит нуль, то ZF будет установлен, а если eax не равен нулю, то ZF будет сброшен. Это позволяет использовать инструкцию je (jump if equal) или jne (jump if not equal) для перехода к определенным меткам в зависимости от значения EAX.

Делаем условный переход (je) и получаем "Try again".

https://forum.antichat.xyz/attachments/29112897/10.png

https://forum.antichat.xyz/attachments/29112897/11.png

Здорово! А что будет, если мы отправим не 64 символа, а 65?

https://forum.antichat.xyz/attachments/29112897/12.png

Видим, что в EAX находится единичка. Таким образом, 64 байта "привели" нас к началу измененной переменной (var1), и уже следующий байт будет помещен в измененную переменную. Другими словами, 65 байт данных изменят 0x00000000 на 0x00000041 (65-ый символ "A"). Таким образом, небезопасная функция gets() позволила нам переполнить buf и изменить переменную var1, что привело нас к следующему результату:

https://forum.antichat.xyz/attachments/29112897/13.png

Всем спасибо за внимание

E909
28.09.2024, 10:12
del..