Статья [Врайт-ап по PWN] HTB no-return

кароче говоря там из гаджетов только безусловные jop-ы и всего один единственный ret;
я подумал, что этот таск - это жопа.
а жопа состоит из двух полужопий.
и между ними нужно вставить ret;

а пиндосы по другому проходят
они сначала ret; кладут

Предварительные ласки
Сам бинарник весит 4.4кб. В нем нету не plt ни got. не залинкована не одна либа. Нету не единой функции, нету даже названия у main().
1587822533900.png

мда, не густо. стек с защитой от выполнения. ну и aslr на сервере на уровне системы. посмотрим что внутри....

Прилюдия
1587822875000.png

а что вы знаете про минимализм?
start
vmmap
i fu

1587822993500.png

жесть. не исполняемый стек, и 4096 байт инструкций. и всё.
сперва появилась идея использовать vdso. такие функции, как time и gettimeofday имеют в себе огромное множество полезных вещей. Но, но на удалёной системе aslr.

задумавшись про ядро я вспомни про dmesg:
1587823404900.png

мда. исходя из увиденного, можно предположить, что у нас есть буффер. что программа крашится в любом случае. и что если буффер переполнить - то крашится она чуть иначе.
1587823538500.png

а ещё, что буффер не большой, так как излишки паттерна выплюнуло обратно в терминал.

Раздевайся
1587823717800.png

Пролог (преамбула) - кладём в стек указатель стекфрейма - $RSP. далее буквально капля кода. есть syscall, это уже хорошо. в конце, вместо эпилога, идёт безусловный переход по адресу, который находится в ячейке памяти на 8 байт меньше, чем ячейка памяти, которую занимает $RSP - указатель стекового фрейма.
зато над основным телом программы есть мёртвая зона с кодом.
1587824108300.png

тут-то мы и будем искать гаджеты.
но сперва посмотрим на краш под дебагером. и на память в процессе краша.

Экшен!
1587824288600.png

скармливаем паттерн, доходим до джампа. на этом джампе смело можно ставить брэйк, он нам понадобится. сверху ничего интересного не происходит.
как мы видем ведёт он в никуда.
1587824546400.png

C-подобный:
pwndbg> p 12*8*2
$2 = 192
pwndbg> p 12*8*2 - 16
$3 = 176
и так, у нас есть 176 байт буффера и 2 ячейки памяти по 8 байт за ним. в сумме 192 байта.
Последняя ячейка принадлежит текущему указателю стека - $RSP.
Джамп указывает на предыдущую ячейку памяти, как бы намекая нам на жоп-чейн. Забегая вперёд скажу, что JOP-чейн - это альтернатива привычным ret; чейнам. Используется в ситуациях когда нормальных гаджетов нету, либо когда нужно обойти файрвол или какой-либо модуль защиты на удалённом сервере. Так как про 0x41414141 все знают, то существуют комплексные решения для защиты серверов, которые тут же улавливают подобные вещи и сообщают куда надо. Но это не наш случай. Пока что не наш :3

А в нашем случае нужно делать stack pivoting.
Это методика, которая позволяет создать фейковый стекфрейм (вернее он настоящий, но не предусмотрен самой программой) и создать его в таком месте, где у нас есть возможность управлять памятью. То бишь - расширить себе стек.
It seems that the easiest way to set the stack pointer to a specific value is by using the xchg gadget. It exchanges the EAX and ESP register values. The plan is therefore:
что ещё мы знаем про ассемблер?
mov esp, edx; ret; == push edx; pop esp; ret

пока всё. у нас есть аж 3 мненоники которые позволят нам это осуществить. (вообще их значительно больше, но я знаю пока только эти)

Жоп-Чейн
Я специально оттягивал это на по-позже.
1587825722000.png

0x\ue\n\n0

1587825942400.png

эээээээээ..... всё что с сисколлом - сразу нет.
остаётся 4 гаджета. первый - нет, т.к. новый указатель будет в младших байтах от старого (выше).
второй тоже нет, т.к. он не влияет на указатель.
и 3 и 4 тоже не влияют. и шо делать?

1587826203900.png

ноу-ретурну ret; приделать. :)

и так, логика. у нас в стекфрейме 2 ячейки, в одну попадает каретка ($rip), во вторую мы можем записать данные.
мы берем и записываем в первую ячейку адрес гаджета, а во вторую ячейку - адрес начала нашего нового стекфрейма. каретка попадает на pop rsp, берет значение из текущего стекфрейма (тоесть из следуещей ячейки в данном случае, так как она у нас по совместительству ячейка текущего стекфрейма), и дублирует его в регистр $rsp. после этого стекфрейм сдвигается, а то, что находится в пределах нового стекфрейма - попадает в стек соответственно.

1587826579800.png

это какая-то просто 3/14 + 0x3da
реально, человеческому мозгу сложно думать снизу вверх и слева на право. ещё и в 16-ричной системе думанья. Но, это эксплойтинг, чёрная магия. А это значит, что вопрос только желания и усилий.
Я решил себе эту задачу с помощью подключения в дело ассоциативного мышления, так как мой мозг не работает в 16-ричной, и ему сложно было счтитать. по этому я расширил регистры своего мозга метамфетамином подключив мощьность абстрактного мышления.

C-подобный:
( (p64(0x1) + p64(0x2) + p64(0x3) + p64(0x4) + p64(0x5) + p64(0x6) + p64(0x7)) + p64(0x8) + p64(0x9) + p64(0xa) + p64(0xb) + p64(0xc) + p64(0xd) + p64(0xe) + p64(0xf) + p64(0x20) + p64(0x21) + p64(0x22) + p64(0x23) + p64(0x24) + p64(0x25) + p64(0x26) + ) ((( p64(0x00401000)+p64(0x7fffffffe4a8) )))

сперва я сделал вот так. пошёл на уступки всё-так процессору, проявил ссолидарность, и начал говорить с ним на его языке.
1587828483900.png

1587828509400.png

он ответил мне взаимностью, и пояснил, что в стеке лежат не данные, а указатели на данные и данные.
то бишь, jmp [rdi] == переход не на инструкцию, которая лежит в $rdi, а на инструкцию, которая лежит по адресу, который лежит в $rdi.

1587828976600.png

гениальная хрень. как в шахматах или в шашках. всё ради одного региста - rdx
а потом - джамп через rcx. куда?? нам осталось сделать 2 вещи:
1 - положить в $RAX 0x3b
2 - вызваать syscall

1587829080900.png

ага ага. только мы с rcx прыгаем в жоп. а с жопа - в rcx. привет, infloop.

сутки где-то я думал что-же делать.
1587829172700.png

оказалось просто. вставить ret;
а за ret; положить в память то, что нам нужно. я так до конца и не понял опираясь на что процессор выбирает ячейку из которой ему вздумается взять следующий адрес для rsp (после ret фрейм так же сдвигается), но поскольку мы с ним договорились - он обьяснил мне на пальцах.


1587829499100.png

ну и для красаты чисто
Эпилог
В начале бинарник выплёвывает нам лик. это адрес последней ячейки из 192.
1587829410300.png


не сильно сложная математика, если учитывать особенность данных в памяти и указателей на данные в памяти.



1587827606100.png



Это был Кот. Если шо - на связи.
 

Вложения

  • 1587827489500.png
    1587827489500.png
    13,3 КБ · Просмотры: 122
  • Нравится
Реакции: fuzzz и Debug

swagcat228

Заблокирован
19.12.2019
341
86
BIT
0
swagcat228 таск на хтб активный?
Да, Сэр, но я специально выложил только общую концепцию. на скришотах готового решения нету.
Просто это найболее удачный пример, как по мне, для новичка, как я, что бы освоить нечто новое для себя
 
Мы в соцсетях:

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