Skip to content
KitploitKITPLOIT
ИнструментыБлог
Log in
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2021-4034-CTF-writeup — Разбор CTF pwn-задачи с эксплуатацией CVE-2021-4034 (pkexec) через манипуляцию кучей, с реверс-инжинирингом в Ghidra и пользовательским вспомогательным бинарником shelly.so. | Kitploit
Инструменты/GitHubGitHub/wechicken456/cve-2021-4034-ctf-writeup
ЭксплуатацияОбратная инженерияCTFОбучение и ОбразованиеЭксплуатация Бинарных ФайловЛаборатории и Практика
GitHubwechicken456/cve-2021-4034-ctf-writeup

CVE-2021-4034-CTF-writeup

Разбор CTF pwn-задачи с эксплуатацией CVE-2021-4034 (pkexec) через манипуляцию кучей, с реверс-инжинирингом в Ghidra и пользовательским вспомогательным бинарником shelly.so.

Репозиторий
2112 лет назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2021-4034-CTF-writeup

Это CTF-pwn задание, которое я написал на C, требующее от пользователя эксплуатации уязвимости CVE-2021-4034. Участникам выдаются 2 бинарных файла в каталоге challenge этого репозитория. Бинарник chal реализует задание CTF, а shelly.so — вспомогательный бинарник.

Как эмулировать это задание

На момент написания этого райтапа Dockerfile ещё не завершён. Dockerfile требуется для развёртывания задания во время живого CTF, но не для локального запуска: вы всё ещё можете эмулировать это задание локально, настроив права пользователей и установив уязвимые пакеты следующим образом:

  1. Чтобы успешно эксплуатировать эту уязвимость, участникам, которые не используют Linux, сначала нужно установить Linux VM. Затем вам потребуется установить уязвимое ядро. Инструкции по этому поводу: [https://askubuntu.com/a/700221]
  2. Установите пакеты libpolkit-gobject-1-0=0.105-26ubuntu1 libpolkit-agent-1-0=0.105-26ubuntu1 policykit-1=0.105-26ubuntu1.
  3. Создайте файл flag.txt, принадлежащий root:root, в текущем каталоге.
  4. Создайте непривилегированного пользователя. Переключитесь на этого пользователя.
  5. Загрузите файлы из каталога challenge в текущий каталог.
  6. Запустите chal от имени непривилегированного пользователя.

Blind Analysis

Запуск бинарника chal даёт нам смутное представление о том, что делает этот бинарник:``` WELCOME TO THE HUB CTRL+ALT+DELICIOUS We're not just a sandwich hub. We are the beacon of flavors, serving a symphony in every byte

  1. ENTER THE HUB
  2. QUIT 1 Order number: 0x7ffde93681f0 Enter your name: tin
  3. ADD NEW ORDER
  4. EDIT ORDER
  5. SHOW ORDER
  6. CANCEL ORDER
  7. CHECKOUT
  8. DONE 1 Pick your bread: aaaa Select your spread: bbbb Choose your veg: cccc Slam your meat & egg: dddc Any side notes for the cook? 0000
  9. ADD NEW ORDER
  10. EDIT ORDER
  11. SHOW ORDER
  12. CANCEL ORDER
  13. CHECKOUT
  14. DONE 1 Pick your bread: AAAA Select your spread: BBBB Choose your veg: CCCC Slam your meat & egg: DDDD Any side notes for the cook? 1111
  15. ADD NEW ORDER
  16. EDIT ORDER
  17. SHOW ORDER
  18. CANCEL ORDER
  19. CHECKOUT
  20. DONE 3 Enter order index: 0 aaaa, bbbb, cccc, dddc, 0000
  21. ADD NEW ORDER
  22. EDIT ORDER
  23. SHOW ORDER
  24. CANCEL ORDER
  25. CHECKOUT
  26. DONE 3 Enter order index: 1 AAAA, BBBB, CCCC, DDDD, 1111
  27. ADD NEW ORDER
  28. EDIT ORDER
  29. SHOW ORDER
  30. CANCEL ORDER
  31. CHECKOUT
  32. DONE 4 Enter order index: 1
  33. ADD NEW ORDER
  34. EDIT ORDER
  35. SHOW ORDER
  36. CANCEL ORDER
  37. CHECKOUT
  38. DONE 3 Enter order index: 1 Invalid index!
  39. ADD NEW ORDER
  40. EDIT ORDER
  41. SHOW ORDER
  42. CANCEL ORDER
  43. CHECKOUT
  44. DONE 5 /notes ./tin/notes
  45. ADD NEW ORDER
  46. EDIT ORDER
  47. SHOW ORDER
  48. CANCEL ORDER
  49. CHECKOUT
  50. DONE 6
  51. ENTER THE HUB
  52. QUIT 2 Come again :)
Играя с размером ввода в функции `Add` и индексами функций `Cancel`, мы не получаем ничего особенного (ни переполнения, ни ошибки сегментации). Однако кое-что интересное:
  - Похоже, заказы помещаются в список (возможно, связный список), и они индексируются с нуля?
  - Здесь есть `Order number: 0x7ffde93681f0`, который, похоже, выводит какой-то адрес в стеке?
  - Кроме того, программа создаёт каталог с именем нашего ввода, а также 3 исполняемых файла, один из которых — это вспомогательный бинарный файл, который нам дан:```sh
peasant@Tin-VM:~/Desktop$ ls
chal  chal.c  Dockerfile shelly.so  solve.py  tin
peasant@Tin-VM:~/Desktop$ ls -l tin/
total 28
-rwxrwx--- 1 peasant vboxsf     5 Feb  4 14:33 notes
-rwxrwx--- 1 peasant vboxsf    20 Feb  4 14:33 recipe
-rwxr-x--- 1 peasant vboxsf 16488 Feb  4 14:33 shelly.so
peasant@Tin-VM:~/Desktop$ cat tin/notes 
0000
peasant@Tin-VM:~/Desktop$ cat tin/recipe 
aaaa
bbbb
cccc
dddc

Исполняемые файлы содержат наш ввод.


Анализ в Ghidra

Вы можете повозиться с другими функциями в надежде наткнуться на баги (что вполне вероятно), но я перейду к сути и открою программу в Ghidra.

Сравнивая строки, которые появляются при запуске программы, и строки, присутствующие в Ghidra, мы можем переименовать некоторые функции FUN_* в знакомые имена:```C undefined8 main(void)

{ int iVar1; size_t sVar2; undefined2 *puVar3; long in_FS_OFFSET; int opt; int local_1c; char *local_18; long local_10;

local_10 = *(long *)(in_FS_OFFSET + 0x28); local_18 = "/recipe"; print("WELCOME TO THE HUB CTRL+ALT+DELICIOUS\n"); print( "We're not just a sandwich hub. We are the beacon of flavors, serving a symphony in every by te\n\n" ); while( true ) { print("1. ENTER THE HUB\n"); print("2. QUIT\n"); __isoc99_scanf(&DAT_001030c5,&opt); getc(stdin); if (opt != 1) break; printf("Order number: %p\n",&local_18); print("Enter your name: "); __isoc99_scanf(&DAT_0010334f,&DAT_00105120); sVar2 = strlen(&DAT_00105120); puVar3 = (undefined2 *)malloc(sVar2 + 2); DAT_00105100 = puVar3; *puVar3 = 0x2f2e; *(undefined *)(puVar3 + 1) = 0; strcpy((char *)(DAT_00105100 + 1),&DAT_00105120); iVar1 = FUN_001022f0(DAT_00105100,&DAT_00105060); if (iVar1 == -1) { mkdir((char *)DAT_00105100,0x1c0); } DAT_00105140 = 0; order_cnt = 0; for (local_1c = 0; local_1c < 10; local_1c = local_1c + 1) { *(undefined8 *)(&ptr_array + (long)local_1c * 8) = 0; } main_menu(); } print("Come again :)\n");

`printf("Order number: %p\n",&local_18);` **выводит адрес локальной переменной в стеке.**

Быстрая проверка в gdb показывает, что утёкший адрес — это адрес указателя на константную строку `/recipe`:```gdb
...
Order number: 0x7fffffffdfc0
...
gef➤  x/gx 0x7fffffffdfc0
0x7fffffffdfc0:	0x0000555555559020
gef➤  x/s 0x0000555555559020
0x555555559020:	"/recipe"

Мы видим вызов mkdir, который создаёт каталог с нашим введённым именем в текущей директории.

Это согласуется с тем, что мы наблюдали при запуске программы. Затем она инициализирует некоторые переменные перед вызовом функции main_menu, которая выглядит примерно так:```C while( true ) { while( true ) { while( true ) { while( true ) { while( true ) { while( true ) { print("1. ADD NEW ORDER\n"); print("2. EDIT ORDER\n"); print("3. SHOW ORDER\n"); print("4. CANCEL ORDER\n"); print("5. CHECKOUT\n"); print("6. DONE\n"); __isoc99_scanf(&DAT_001030c5,&local_40); getc(stdin); if (local_40 != 1) break; add_order(); } if (local_40 != 2) break; edit_order(); } if (local_40 != 3) break; show_order(); } if (local_40 != 4) break; cancel_order(); } if (local_40 != 5) break; checkout(); } if (local_40 == 6) break; if (local_40 == 0x539) { print( "\nGORDON RAMSAY: Finally, a worthy opponent, our battle will be legendary! I BET YOU CAN 'T GUESS THE SECRET RECIPE.\n" ); fgets(inp,0x20,stdin); getrandom(random-bytes,0x10,0); for (local_3c = 0; local_3c < 0x10; local_3c = local_3c + 1) { if (inp[local_3c] != random-bytes[local_3c]) { print("...Nuh Uh!...\n"); /* WARNING: Subroutine does not return */ exit(0); } print("...Ooh Yes.. sCruMpTioUs..."); } print("Fine... I'll give you a taste.\n"); FUN_00101504(); }

Если вы не знакомы с REV, это декомпиляция оператора `switch` на C. Есть один интересный вариант, также известный как `0x539`.  Он позволяет игрокам угадать `0x10` случайных байт. Если все байты равны, то вызывается `FUN_00101504();`, которая вызывает `system("cat flag.txt");`. В противном случае программа завершается.

Однако брутфорс 16 случайных байт эквивалентен попытке перебрать все 256**16 = 340282366920938463463374607431768211456 возможных комбинаций. Удачи с этим, лол.
Скачать инструмент