FlagsFlagsFlags
Description
Author: @Kkevsterrr
Did you see the strings? One of those is right, I can just feel it.
Reversing
Disclaimer:
I am not a professional reverse engineer, I just love it and I love CTFs. Not sure if this was the correct way to solve it, as I had to brute force the flag.
First we downloaded the flagsflagsflags
binary. Then we did some static analysis:
1
2
> file flagsflagsflags
flagsflagsflags: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header
The binary was packed so we could not decompile it properly as shown here we can see the upx
info and even header at the beginning of running strings flagsflagsflags
More info to confirm shown below:
We unpacked it first:
1
> upx -d flagsflagsflags
Then we can do more enumeration on it, as even the file command displays more data:
1
2
> file flagsflagsflags
flagsflagsflags: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=8bbcb5450afeba98d27154e01464d3e4888218b7, stripped
We then can see more interesting strings and we noticed we could grep the flags:
We then stored all the strings matching flag{*}
inside a file called string-flags.txt
using the following command to count the number of lines we got in the binary:
1
2
> strings ./unpacked-flagsflagsflags | grep -o 'flag{[^}]*}' | wc -l
100000
We needed it stored in a file, so we did the following:
1
2
> strings ./unpacked-flagsflagsflags | grep -o 'flag{[^}]*}' > string-flags.txt # storing the flags
wc -l string-flags.txt # counting the lines
Here we verify that we got all the flags stored:
This seems like a brute force type of attack, since when even running the binary it ask us for a flag and we have a 100000 flags stored in the binary. But only one of them needs to match in order to retrieve the flag. :
So here we made a script called script.py
to brute force the flag. Due to the amount of flags we have stored in the binary, we will need to use threads to speed up the process and subprocess to run the binary and insert the flags one by one.
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
import threading
import subprocess
from queue import Queue
NUM_THREADS = 100
BINARY_PATH = './flagsflagsflags'
FLAG_FILE = 'string-flags.txt'
# Shared queue of flags
flag_queue = Queue()
found_flag = threading.Event()
def worker(thread_id):
while not flag_queue.empty() and not found_flag.is_set():
flag = flag_queue.get().strip()
print(f"[Thread-{thread_id}] Testing: {flag}")
try:
result = subprocess.run(
[BINARY_PATH],
input=flag + '\n',
text=True,
capture_output=True
)
if "Correct" in result.stdout:
print(f"\n[💀] Flag found by Thread-{thread_id}: {flag}\n")
found_flag.set()
except Exception as e:
print(f"[!] Error testing flag {flag}: {e}")
finally:
flag_queue.task_done()
def main():
# Load flags into the queue
with open(FLAG_FILE, 'r') as f:
for line in f:
flag_queue.put(line)
# Create and start threads
threads = []
for i in range(NUM_THREADS):
t = threading.Thread(target=worker, args=(i,))
t.start()
threads.append(t)
# Wait for queue to be empty or a flag to be found
flag_queue.join()
# Ensure all threads exit
for t in threads:
t.join()
if not found_flag.is_set():
print("\n[-] No valid flag found.\n")
if __name__ == "__main__":
main()
Running our script disclosed the flag as shown below.
Flag
flag{20dec9363618a397e9b2a0bf5a35b2e3}
Happy hacking ! 😊