Don Reverso
17.07.2024, 02:24
Название: Царь-админ
Категория: pwn
Платформа: antichat
В архиве нас ждут 3 файла: cipher, genи task_local. Все без расширений, все помечены как исполняемые - в общем, ничего непонятно. Поэтому прогоним их через file:
https://forum.antichat.xyz/attachments/29112933/1721161183138.png
Как видно из скриншота, cipher- это просто текст, в то время как 2 остальных файла - ELF-бинари. Сначала заглянем в cipher:
https://forum.antichat.xyz/attachments/29112933/1721161547279.png
Пока неясно, как это ковырять: вроде похоже на base64, но получается какая-то ересь; dcode.fr тоже выпал в осадок, поэтому пока отложим в сторону cipherи глянем на первый бинарь - gen:
https://forum.antichat.xyz/attachments/29112933/1721161656397.png
Ээ... Штош, увидели мы достаточно, поэтому кидаем его в IDA(переменные я переименовал для наглядности):
https://forum.antichat.xyz/attachments/29112933/1721161799708.png
А тут уже всё выглядит интереснее: у нас создаются 10 файлов в папке /tmp, в которые записываются сначала текущее время в секундах, а затем случайно сгенерированные строки, где в качестве сида генерации использовалось как раз то время. И действительно, в папке /tmp нас ждут 10 файлов:
https://forum.antichat.xyz/attachments/29112933/1721161997035.png
Всё это, конечно, интересно, но пока толком непонятно, для чего всё это и что от нас хотят. Поэтому теперь перейдём к task_local:
https://forum.antichat.xyz/attachments/29112933/1721162084588.png
Уже что-то! Для начала глянем рейтинг:
https://forum.antichat.xyz/attachments/29112933/1721162173048.png
Действительно рейтинг, ничего не скажешь. Попробуем залогиниться за какую-нить команду:
https://forum.antichat.xyz/attachments/29112933/1721162239677.png
Мдэ, методом пристального взгляда и двух попыток можно понять, что логин сверяется с действительными командами, а пароль принимается любой. И опять непонятно: что от нас хотят? Поэтому и этот файлик летит в IDA(переменные переименованы, все строки в конструкциях вида
puts(&byte_23EC)
заменены на читабельные):
https://forum.antichat.xyz/attachments/29112933/1721162748054.png
Здесь представлена стандартная реализация консольного интерфейса. Предлагаю без промедлений заглянуть вlogin_function():
https://forum.antichat.xyz/attachments/29112933/1721163152337.png
https://forum.antichat.xyz/attachments/29112933/1721163163199.png
Полотно кода большое, поэтому давайте разберём его частично!
https://forum.antichat.xyz/attachments/29112933/1721163377310.png
Сначала мы вводим название команды, которое сравнивается со всеми 50 вариантами существующих - и, если какая-то совпала, то партия довольна, идём дальше. Кстати, весьма интересно сделан итерационный переход от названия к названию:
https://forum.antichat.xyz/attachments/29112933/1721163539797.png
На название каждой команды выделяется 44 байта, которыми и оперируют при проверке. Удобно, и нет массива в явном виде!
https://forum.antichat.xyz/attachments/29112933/1721163771047.png
Далее, наше введённое название проверяется со строкой "admin" (если перейти по адресу admin_str, то там будет эта красота в чистом виде). А вот дальше начинается кое-что смутно знакомое - strange_func():
https://forum.antichat.xyz/attachments/29112933/1721163992725.png
Здесь прослеживается связь с предыдущим файлом gen, генерирующим 10 файлов в папке /tmp. А эта функция как раз пытается какой-то из них прочесть и сохранить у себя первые 4 байта (сид генерации), и саму генерированную строку (всё остальное). После этого файл удаляется - мистика, да и только! Давайте вернёмся в функцию выше и глянем, что там происходит дальше:
https://forum.antichat.xyz/attachments/29112933/1721164200604.png
Дальше, если в качестве команды мы указали admin, то у нас начинают просить какой-то PIN-код, причём, как видно невооружённым глазом, этот пинкод должен равняться числу 133(Б - безопасность). А дальше интересный момент: Если byte_4943будет равен символу 'A', то мы увидим на экране тот самый прочитанный сид из strange_func(), а в противном случае - лишь наш введённый PIN-код. Обратите внимание на адрес byte_4943:
https://forum.antichat.xyz/attachments/29112933/1721164422724.png
Он идёт сразу же после pincode, для которой выделено 3 байта, но нам позволено ввести 4! (62-я строка, 1 картинка вверх) Поэтому мы можем спокойно перезаписать этот байт на'A' и зачем-то увидеть сид генерации из того tmp-файла. Пока непонятно, зачем он, поэтому двигаемся дальше!
https://forum.antichat.xyz/attachments/29112933/1721164573835.png
А вот здесь - самый сок: нас просят ввести пароль админа (да сколько можно-то...), причём тот не должен начинаться с символа 'q', иначе мы просто вернёмся в меню. А судя по адресам переменной, этот пароль - и есть та самая сгенерированная строка! И если мы её введём, то вызовется функция print_flag(), печатающая флаг (это локальный бинарь, так что флаг фейковый). Поэтому нам нужно лишь скопировать строку из файла
/tmp/pass[i].txt
, где
[i]
- минимальное число из оставшихся файлов, и получить флаг!
Давайте теперь с полученной информацией проверим ту на практике:
https://forum.antichat.xyz/attachments/29112933/1721164873440.png
Действительно, adminпринимается в качестве названия. Попробуем ввести в качестве PIN-кода не просто 133, а 133A:
https://forum.antichat.xyz/attachments/29112933/1721165158546.png
А 0x6696d7b0, как вы уже догадались, наш сид в виде шестнадцатиричного числа. Теперь от нас просят пароль, так что скопируем его из самого первого оставшегося файла:
https://forum.antichat.xyz/attachments/29112933/1721165203522.png
Обратите внимание, команды, вывод которых представлен на переднем окне, выполнялись до запуска task_local, т.к. последний читает файл из /tmp и сразу же его удаляет. Так что на момент ввода пароля из pass3.txt, этого файла уже не существовало
И вот, флаг получен! Осталось лишь повторить эти действия на сервере... Но как же нам прочитать там файлы из/tmp? А никак! Поэтому мы их будем генерировать сами! Ведь, по сути, для этого нам необходим лишь сид, который мы можем получить через переполнение с 'A'. Так что ноги в руки и бегом переписывать скрипт:
C:
#include
#include
void
main
(
void
)
{
char
secret
[
100
]
=
{
0
}
;
int
seed
;
printf
(
"enter seed: "
)
;
scanf
(
"%x"
,
&
seed
)
;
printf
(
"seed: %x\n"
,
seed
)
;
srand
(
seed
)
;
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
for
(
int
j
=
0
;
j
<
50
;
j
++
)
{
secret
[
j
]
=
rand
(
)
%
26
+
97
;
}
printf
(
"Passwd %d: %s\n"
,
i
+
1
,
secret
)
;
}
}
Обратите внимание! Так как нам неизвестно, сколько файлов с паролями в /tmp на сервере осталось, мы будем генерировать все 10, и каждый пробовать пихать программе - и на каком-то из них она должна сдаться. Скомпилируем этот код с помощью gccи оформим тестовый запуск:
https://forum.antichat.xyz/attachments/29112933/1721165718360.png
Вроде всё работает, так что давайте протестируем на локальном бинаре:
https://forum.antichat.xyz/attachments/29112933/1721166163769.png
Получилось! Единственное - мне немного не повезло с сидом и первый пароль начинался с 'q' - так что я его пропустил. Но один из следующих подошёл, а значит, можно то же самое проделать на сервере и получить реальный флаг!
https://forum.antichat.xyz/attachments/29112933/1721166302227.png
А вот тут поподробнее... Почему не работает наша хитрость с PIN-кодом? А всё дело в хинте, который любезные разработчики оставили на странице с заданием:
https://forum.antichat.xyz/attachments/29112933/1721166386031.png
Как по мне, это что-то из разряда обязательных хинтов. Искренне сожалею тем людям, кто таски проходит только без них - им могу пожелать лишь фаззить символ после 133. А нам, судя по хинту, нужен вместо 'A' символ с кодом 1. Я недавно писал райтап (https://forum.antichat.xyz/threads/1643689/), где тоже нужен был такой символ, и им оказалась комбинация
CTRL+A
, которую можно ввести с клавиатуры. Попробуем её:
https://forum.antichat.xyz/attachments/29112933/1721166620857.png
Получилось! Осталось дело за малым - сгенерировать пароли с выданным нам сидом:
https://forum.antichat.xyz/attachments/29112933/1721166730637.png
Странно, но ни один из наших паролей не подошёл. И дело даже не в том, что один из них начинался с 'q' (невезучее время). Что же делать, мы же были так близки?!
Давайте рассуждать логически: генерация псевдопростых чисел имеет два фактора, которые на неё влияют: это сам сид, передающийся в srand() и... libc! А если быть точнее, сам алгоритм генерации. И если с первым пунктом итак всё понятно, то давайте детальнее разберём второй.
Возможно, кто-то из читателей не знал, но существуют несколько видов реализации libc:
всем привычная glibc
musl libc
uClibc
BSD libc
и, возможно, некоторые другие, о которых автор не знает. В каждой из этих реализаций свой способ генерировать псевдочисла: в сравнении с glibc, где-то он отличается лишь константами, где-то алгоритм проще, где-то сложнее. Но в любом случае, при одинаковом сиде, одна и та же программа, скомпилированная разными компиляторами для разных libc, будет выдавать совершенно разные числа. И раз мы уже попробовали glibc, то придётся попробовать другие вариации, больше идей нет.
Сперва попробуем musl:
Bash:
sudo
apt
update
sudo
apt
install
musl musl-dev musl-tools
Теперь скомпилируем программу под musl libc:
Bash:
musl-gcc solve.c -o solve
Сравним вывод программ из под muslи gccна одном сиде:
https://forum.antichat.xyz/attachments/29112933/1721167601822.png
Как и предполагалось, мы получили совершенно разный результат. Так что теперь попробуем сгенерировать пароли для сервера через musl_solve:
https://forum.antichat.xyz/attachments/29112933/1721167750897.png
Первый пароль подошёл! Копируем флаг, лутаем баллы и кайфуем)
Кстати, а помните тот самый файл cipherиз начала? Оказывается, в нём зашифрован какой-то текст, говорящий о том, что на сервере стоит докер с alpine linux - а там по умолчанию не glibc, а musl libc. Правда, я так и не понял, как этот файл расшифровать, спросил в чате - никто тоже не понял. Такая вот петрушка :/
Если вы знаете, как этот файл расшифровать - поделитесь, интересно!
Надеюсь, этот довольно длинный райтап помог вам в нашей нелёгкой стезе.
Удачного пывына!
made 4@rev_with_da_boys
Категория: pwn
Платформа: antichat
В архиве нас ждут 3 файла: cipher, genи task_local. Все без расширений, все помечены как исполняемые - в общем, ничего непонятно. Поэтому прогоним их через file:
https://forum.antichat.xyz/attachments/29112933/1721161183138.png
Как видно из скриншота, cipher- это просто текст, в то время как 2 остальных файла - ELF-бинари. Сначала заглянем в cipher:
https://forum.antichat.xyz/attachments/29112933/1721161547279.png
Пока неясно, как это ковырять: вроде похоже на base64, но получается какая-то ересь; dcode.fr тоже выпал в осадок, поэтому пока отложим в сторону cipherи глянем на первый бинарь - gen:
https://forum.antichat.xyz/attachments/29112933/1721161656397.png
Ээ... Штош, увидели мы достаточно, поэтому кидаем его в IDA(переменные я переименовал для наглядности):
https://forum.antichat.xyz/attachments/29112933/1721161799708.png
А тут уже всё выглядит интереснее: у нас создаются 10 файлов в папке /tmp, в которые записываются сначала текущее время в секундах, а затем случайно сгенерированные строки, где в качестве сида генерации использовалось как раз то время. И действительно, в папке /tmp нас ждут 10 файлов:
https://forum.antichat.xyz/attachments/29112933/1721161997035.png
Всё это, конечно, интересно, но пока толком непонятно, для чего всё это и что от нас хотят. Поэтому теперь перейдём к task_local:
https://forum.antichat.xyz/attachments/29112933/1721162084588.png
Уже что-то! Для начала глянем рейтинг:
https://forum.antichat.xyz/attachments/29112933/1721162173048.png
Действительно рейтинг, ничего не скажешь. Попробуем залогиниться за какую-нить команду:
https://forum.antichat.xyz/attachments/29112933/1721162239677.png
Мдэ, методом пристального взгляда и двух попыток можно понять, что логин сверяется с действительными командами, а пароль принимается любой. И опять непонятно: что от нас хотят? Поэтому и этот файлик летит в IDA(переменные переименованы, все строки в конструкциях вида
puts(&byte_23EC)
заменены на читабельные):
https://forum.antichat.xyz/attachments/29112933/1721162748054.png
Здесь представлена стандартная реализация консольного интерфейса. Предлагаю без промедлений заглянуть вlogin_function():
https://forum.antichat.xyz/attachments/29112933/1721163152337.png
https://forum.antichat.xyz/attachments/29112933/1721163163199.png
Полотно кода большое, поэтому давайте разберём его частично!
https://forum.antichat.xyz/attachments/29112933/1721163377310.png
Сначала мы вводим название команды, которое сравнивается со всеми 50 вариантами существующих - и, если какая-то совпала, то партия довольна, идём дальше. Кстати, весьма интересно сделан итерационный переход от названия к названию:
https://forum.antichat.xyz/attachments/29112933/1721163539797.png
На название каждой команды выделяется 44 байта, которыми и оперируют при проверке. Удобно, и нет массива в явном виде!
https://forum.antichat.xyz/attachments/29112933/1721163771047.png
Далее, наше введённое название проверяется со строкой "admin" (если перейти по адресу admin_str, то там будет эта красота в чистом виде). А вот дальше начинается кое-что смутно знакомое - strange_func():
https://forum.antichat.xyz/attachments/29112933/1721163992725.png
Здесь прослеживается связь с предыдущим файлом gen, генерирующим 10 файлов в папке /tmp. А эта функция как раз пытается какой-то из них прочесть и сохранить у себя первые 4 байта (сид генерации), и саму генерированную строку (всё остальное). После этого файл удаляется - мистика, да и только! Давайте вернёмся в функцию выше и глянем, что там происходит дальше:
https://forum.antichat.xyz/attachments/29112933/1721164200604.png
Дальше, если в качестве команды мы указали admin, то у нас начинают просить какой-то PIN-код, причём, как видно невооружённым глазом, этот пинкод должен равняться числу 133(Б - безопасность). А дальше интересный момент: Если byte_4943будет равен символу 'A', то мы увидим на экране тот самый прочитанный сид из strange_func(), а в противном случае - лишь наш введённый PIN-код. Обратите внимание на адрес byte_4943:
https://forum.antichat.xyz/attachments/29112933/1721164422724.png
Он идёт сразу же после pincode, для которой выделено 3 байта, но нам позволено ввести 4! (62-я строка, 1 картинка вверх) Поэтому мы можем спокойно перезаписать этот байт на'A' и зачем-то увидеть сид генерации из того tmp-файла. Пока непонятно, зачем он, поэтому двигаемся дальше!
https://forum.antichat.xyz/attachments/29112933/1721164573835.png
А вот здесь - самый сок: нас просят ввести пароль админа (да сколько можно-то...), причём тот не должен начинаться с символа 'q', иначе мы просто вернёмся в меню. А судя по адресам переменной, этот пароль - и есть та самая сгенерированная строка! И если мы её введём, то вызовется функция print_flag(), печатающая флаг (это локальный бинарь, так что флаг фейковый). Поэтому нам нужно лишь скопировать строку из файла
/tmp/pass[i].txt
, где
[i]
- минимальное число из оставшихся файлов, и получить флаг!
Давайте теперь с полученной информацией проверим ту на практике:
https://forum.antichat.xyz/attachments/29112933/1721164873440.png
Действительно, adminпринимается в качестве названия. Попробуем ввести в качестве PIN-кода не просто 133, а 133A:
https://forum.antichat.xyz/attachments/29112933/1721165158546.png
А 0x6696d7b0, как вы уже догадались, наш сид в виде шестнадцатиричного числа. Теперь от нас просят пароль, так что скопируем его из самого первого оставшегося файла:
https://forum.antichat.xyz/attachments/29112933/1721165203522.png
Обратите внимание, команды, вывод которых представлен на переднем окне, выполнялись до запуска task_local, т.к. последний читает файл из /tmp и сразу же его удаляет. Так что на момент ввода пароля из pass3.txt, этого файла уже не существовало
И вот, флаг получен! Осталось лишь повторить эти действия на сервере... Но как же нам прочитать там файлы из/tmp? А никак! Поэтому мы их будем генерировать сами! Ведь, по сути, для этого нам необходим лишь сид, который мы можем получить через переполнение с 'A'. Так что ноги в руки и бегом переписывать скрипт:
C:
#include
#include
void
main
(
void
)
{
char
secret
[
100
]
=
{
0
}
;
int
seed
;
printf
(
"enter seed: "
)
;
scanf
(
"%x"
,
&
seed
)
;
printf
(
"seed: %x\n"
,
seed
)
;
srand
(
seed
)
;
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
for
(
int
j
=
0
;
j
<
50
;
j
++
)
{
secret
[
j
]
=
rand
(
)
%
26
+
97
;
}
printf
(
"Passwd %d: %s\n"
,
i
+
1
,
secret
)
;
}
}
Обратите внимание! Так как нам неизвестно, сколько файлов с паролями в /tmp на сервере осталось, мы будем генерировать все 10, и каждый пробовать пихать программе - и на каком-то из них она должна сдаться. Скомпилируем этот код с помощью gccи оформим тестовый запуск:
https://forum.antichat.xyz/attachments/29112933/1721165718360.png
Вроде всё работает, так что давайте протестируем на локальном бинаре:
https://forum.antichat.xyz/attachments/29112933/1721166163769.png
Получилось! Единственное - мне немного не повезло с сидом и первый пароль начинался с 'q' - так что я его пропустил. Но один из следующих подошёл, а значит, можно то же самое проделать на сервере и получить реальный флаг!
https://forum.antichat.xyz/attachments/29112933/1721166302227.png
А вот тут поподробнее... Почему не работает наша хитрость с PIN-кодом? А всё дело в хинте, который любезные разработчики оставили на странице с заданием:
https://forum.antichat.xyz/attachments/29112933/1721166386031.png
Как по мне, это что-то из разряда обязательных хинтов. Искренне сожалею тем людям, кто таски проходит только без них - им могу пожелать лишь фаззить символ после 133. А нам, судя по хинту, нужен вместо 'A' символ с кодом 1. Я недавно писал райтап (https://forum.antichat.xyz/threads/1643689/), где тоже нужен был такой символ, и им оказалась комбинация
CTRL+A
, которую можно ввести с клавиатуры. Попробуем её:
https://forum.antichat.xyz/attachments/29112933/1721166620857.png
Получилось! Осталось дело за малым - сгенерировать пароли с выданным нам сидом:
https://forum.antichat.xyz/attachments/29112933/1721166730637.png
Странно, но ни один из наших паролей не подошёл. И дело даже не в том, что один из них начинался с 'q' (невезучее время). Что же делать, мы же были так близки?!
Давайте рассуждать логически: генерация псевдопростых чисел имеет два фактора, которые на неё влияют: это сам сид, передающийся в srand() и... libc! А если быть точнее, сам алгоритм генерации. И если с первым пунктом итак всё понятно, то давайте детальнее разберём второй.
Возможно, кто-то из читателей не знал, но существуют несколько видов реализации libc:
всем привычная glibc
musl libc
uClibc
BSD libc
и, возможно, некоторые другие, о которых автор не знает. В каждой из этих реализаций свой способ генерировать псевдочисла: в сравнении с glibc, где-то он отличается лишь константами, где-то алгоритм проще, где-то сложнее. Но в любом случае, при одинаковом сиде, одна и та же программа, скомпилированная разными компиляторами для разных libc, будет выдавать совершенно разные числа. И раз мы уже попробовали glibc, то придётся попробовать другие вариации, больше идей нет.
Сперва попробуем musl:
Bash:
sudo
apt
update
sudo
apt
install
musl musl-dev musl-tools
Теперь скомпилируем программу под musl libc:
Bash:
musl-gcc solve.c -o solve
Сравним вывод программ из под muslи gccна одном сиде:
https://forum.antichat.xyz/attachments/29112933/1721167601822.png
Как и предполагалось, мы получили совершенно разный результат. Так что теперь попробуем сгенерировать пароли для сервера через musl_solve:
https://forum.antichat.xyz/attachments/29112933/1721167750897.png
Первый пароль подошёл! Копируем флаг, лутаем баллы и кайфуем)
Кстати, а помните тот самый файл cipherиз начала? Оказывается, в нём зашифрован какой-то текст, говорящий о том, что на сервере стоит докер с alpine linux - а там по умолчанию не glibc, а musl libc. Правда, я так и не понял, как этот файл расшифровать, спросил в чате - никто тоже не понял. Такая вот петрушка :/
Если вы знаете, как этот файл расшифровать - поделитесь, интересно!
Надеюсь, этот довольно длинный райтап помог вам в нашей нелёгкой стезе.
Удачного пывына!
made 4@rev_with_da_boys