Skip to content
KitploitKITPLOIT
StrumentiBlog
Log in
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2021-4034-CTF-writeup — Scrittura di una sfida CTF pwn che sfrutta CVE-2021-4034 (pkexec) tramite manipolazione dell'heap, con reverse engineering basato su Ghidra e un binario helper personalizzato shelly.so. | Kitploit
Strumenti/GitHubGitHub/wechicken456/cve-2021-4034-ctf-writeup
ExploitReverse EngineeringCTFApprendimento e FormazioneBinary ExploitationLab e Pratica
GitHubwechicken456/cve-2021-4034-ctf-writeup

CVE-2021-4034-CTF-writeup

Scrittura di una sfida CTF pwn che sfrutta CVE-2021-4034 (pkexec) tramite manipolazione dell'heap, con reverse engineering basato su Ghidra e un binario helper personalizzato shelly.so.

Vedi Repository
2112 anni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2021-4034-CTF-writeup

Questa è una sfida CTF pwn che ho scritto in C e che richiede all'utente di sfruttare la vulnerabilità CVE-2021-4034. Ai giocatori vengono forniti 2 binari nella directory challenge di questo repository. Il binario chal implementa la sfida CTF e shelly.so è un binario di supporto.

Come emulare questa sfida

Al momento della stesura di questo writeup, il Dockerfile non è ancora completo. Il Dockerfile è necessario per distribuire questa sfida durante un CTF dal vivo, ma non localmente: Puoi comunque emulare questa sfida localmente impostando i permessi utente e installando i pacchetti vulnerabili come segue:

  1. Per sfruttare con successo questa vulnerabilità, i giocatori che non sono su una macchina Linux dovrebbero prima installare una VM Linux. Quindi, dovrete installare un kernel vulnerabile. Istruzioni su come fare: [https://askubuntu.com/a/700221]
  2. Installare i pacchetti libpolkit-gobject-1-0=0.105-26ubuntu1 libpolkit-agent-1-0=0.105-26ubuntu1 policykit-1=0.105-26ubuntu1.
  3. Creare un file flag.txt di proprietà di root:root nella directory corrente.
  4. Creare un utente non privilegiato. Passare a questo utente.
  5. Scaricare i file nella cartella challenge nella directory corrente.
  6. Eseguire chal come utente non privilegiato.

Analisi alla cieca

Eseguire il binario chal ci dà un'idea vaga di cosa fa questo binario:``` 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 :)
Giocando con la dimensione dell'input nella funzione `Add` e con gli indici delle funzioni `Cancel` non otteniamo nulla di speciale (nessun overflow o segmentation fault). Tuttavia, alcune cose interessanti:
  - Sembra che gli ordini siano inseriti in una lista (forse una lista concatenata) e che siano indicizzati a partire da 0?
  - C'è questo `Order number: 0x7ffde93681f0` che sembra stampare una posizione nello stack?
  - Inoltre, il programma crea una directory con il nostro nome di input insieme a 3 eseguibili, uno dei quali è il file binario helper che ci viene fornito:```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

The executables contain our input.


Ghidra analysis

You can play around with the other functions and hope that you might run into some bugs (which is probable), but I'm gonna cut to the chase and open the program in Ghidra.

Comparing the strings that appear while running the program and the strings that are present in Ghidra, we can rename some of the FUN_* functions into familiar names:```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");

L'istruzione `printf("Order number: %p\n",&local_18);` **stampa la posizione di una variabile locale nello stack.**

Un rapido controllo in gdb mostra che l'indirizzo divulgato è l'indirizzo del puntatore alla stringa costante `/recipe`:```gdb
...
Order number: 0x7fffffffdfc0
...
gef➤  x/gx 0x7fffffffdfc0
0x7fffffffdfc0:	0x0000555555559020
gef➤  x/s 0x0000555555559020
0x555555559020:	"/recipe"

Vediamo una chiamata a mkdir, che crea una directory con il nostro nome di input nella directory corrente.

Questo è coerente con quanto osservato quando abbiamo eseguito il programma. Poi inizializza una variabile prima di chiamare la funzione main_menu, che assomiglia a:```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(); }

Se non hai familiarità con REV, questa è la decompilazione per l'istruzione `switch` in C. C'è un'opzione interessante, a.k.a `0x539`. Permette ai giocatori di indovinare `0x10` byte casuali. Se tutti i byte sono uguali, allora chiama `FUN_00101504();` che chiama `system("cat flag.txt");`. Altrimenti, il programma termina.
Scarica lo strumento