Skip to content
KitploitKITPLOIT
FerramentasBlog
Log in
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2021-4034-CTF-writeup — Writeup de desafio CTF pwn explorando CVE-2021-4034 (pkexec) através de manipulação de heap, com engenharia reversa baseada em Ghidra e um binário auxiliar customizado shelly.so. | Kitploit
Ferramentas/GitHubGitHub/wechicken456/cve-2021-4034-ctf-writeup
ExploraçãoEngenharia ReversaCTFAprendizado e EducaçãoExploração de BináriosLabs e Prática
GitHubwechicken456/cve-2021-4034-ctf-writeup

CVE-2021-4034-CTF-writeup

Writeup de desafio CTF pwn explorando CVE-2021-4034 (pkexec) através de manipulação de heap, com engenharia reversa baseada em Ghidra e um binário auxiliar customizado shelly.so.

Ver Repositório
211há 2 anosAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2021-4034-CTF-writeup

Este é um desafio CTF do tipo pwn que escrevi em C e que exige que o usuário explore a vulnerabilidade CVE-2021-4034. Os jogadores recebem 2 binários no diretório challenge deste repositório. O binário chal implementa o desafio CTF e o shelly.so é um binário auxiliar.

Como emular este desafio

No momento em que este writeup foi escrito, o Dockerfile ainda não está completo. O Dockerfile é necessário para implantar este desafio durante um CTF ao vivo, mas não localmente: Você ainda pode emular este desafio localmente configurando as permissões de usuário e instalando os pacotes vulneráveis da seguinte forma:

  1. Para explorar com sucesso essa vulnerabilidade, os jogadores que não estiverem em uma máquina Linux devem primeiro instalar uma VM Linux. Em seguida, você precisará instalar um kernel vulnerável. Instruções de como fazer isso: [https://askubuntu.com/a/700221]
  2. Instale os pacotes libpolkit-gobject-1-0=0.105-26ubuntu1 libpolkit-agent-1-0=0.105-26ubuntu1 policykit-1=0.105-26ubuntu1.
  3. Crie um arquivo flag.txt pertencente a root:root no diretório atual.
  4. Crie um usuário não privilegiado. Troque para esse usuário.
  5. Baixe os arquivos na pasta challenge para o diretório atual.
  6. Execute chal como o usuário não privilegiado.

Análise Cega

Executar o binário chal nos dá uma ideia vaga do que esse binário faz:``` 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 :)
Brincar com o tamanho da entrada na função `Add` e os índices das funções `Cancel` não nos dá nada especial (sem overflow ou segmentation fault). No entanto, algumas coisas interessantes:
  - Parece que os pedidos são colocados numa lista (talvez uma lista ligada) e são indexados a partir de 0?
  - Há este `Order number: 0x7ffde93681f0` que parece imprimir alguma localização na pilha?
  - Além disso, o programa cria um diretório com o nome que introduzimos juntamente com 3 executáveis, um dos quais é o ficheiro binário auxiliar que nos é dado:```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

Os executáveis contêm nossa entrada.


Análise no Ghidra

Você pode brincar com as outras funções e torcer para encontrar alguns bugs (o que é provável), mas vou direto ao ponto e abrir o programa no Ghidra.

Comparando as strings que aparecem durante a execução do programa e as strings presentes no Ghidra, podemos renomear algumas das funções FUN_* para nomes familiares:```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");

O `printf("Order number: %p\n",&local_18);` **imprime a localização de uma variável local na pilha.**

Uma verificação rápida no gdb mostra-nos que o endereço vazado é o endereço do ponteiro para a string constante `/recipe`:```gdb
...
Order number: 0x7fffffffdfc0
...
gef➤  x/gx 0x7fffffffdfc0
0x7fffffffdfc0:	0x0000555555559020
gef➤  x/s 0x0000555555559020
0x555555559020:	"/recipe"

Vemos uma chamada mkdir, que cria um diretório com o nome da nossa entrada no diretório atual.

Isso é consistente com nossa observação quando executamos o programa. Em seguida, ele inicializa alguma variável antes de chamar a função main_menu, que se parece com algo como:```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 você não está familiarizado com REV, esta é a descompilação para a declaração `switch` em C. Há uma opção interessante, também conhecida como `0x539`. Ela permite que os jogadores adivinhem `0x10` bytes aleatórios. Se todos os bytes forem iguais, então chama `FUN_00101504();` que chama `system("cat flag.txt");`. Caso contrário, o programa encerra.
Baixar ferramenta