3.9 KiB
False Flags
falseFlags is a beginner-friendly reverse engineering challenge. We are given a binary that contains multiple "fake" flags, and our goal is to identify the correct one.
1. Initial Analysis
We start by examining the file type and basic properties.
$ file false_flags
false_flags: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=..., for GNU/Linux 3.2.0, stripped
It's a standard 64-bit ELF executable. Let's try running it. The challenge is also available remotely at <SERVER_IP>:1301.
$ nc <SERVER_IP> 1301
=== The Vault of Falsehoods ===
There are many keys, but only one opens the door.
Enter the password: test
[-] Wrong! That was merely a decoy.
Since the description mentions "hiding passwords in the binary", the strings command is a good first step to see what's inside.
$ strings false_flags | grep flag
{flag:This_Is_Definitely_Not_It}
{flag:Try_Harder_To_Find_The_Key}
{flag:Strings_Are_Misleading_You}
...
{flag:Reverse_Engineering_Is_Cool}
...
We see a long list of potential flags. We could try them one by one, but that's tedious (and "brute-force" isn't the elegant way!). We need to find out which specific string the program compares our input against.
2. Static Analysis
We can analyze the binary using objdump to look at the assembly code. Since the binary is stripped, we won't see function names like main. However, we can find the entry point.
$ readelf -h false_flags | grep "Entry point"
Entry point address: 0x4019f0
The entry point is at 0x4019f0. If we disassemble at this address, we'll see the startup code (_start), which calls __libc_start_main. The first argument to __libc_start_main is the address of main.
$ objdump -d -M intel --start-address=0x4019f0 --stop-address=0x401a20 false_flags
00000000004019f0 <.text+0x830>:
...
401a08: 48 c7 c7 52 1b 40 00 mov rdi,0x401b52 <-- Address of main
401a0f: 67 e8 5b 15 00 00 addr32 call 0x402f70 <-- Call to __libc_start_main
...
So main is located at 0x401b52. Let's disassemble it.
$ objdump -d -M intel --start-address=0x401b52 --stop-address=0x401c50 false_flags
In the output, we see a call early in the function:
401ba0: e8 70 ff ff ff call 0x401b15
401ba5: 89 85 6c ff ff ff mov DWORD PTR [rbp-0x94],eax
The return value (in eax) is stored in [rbp-0x94]. This variable is later used to access an array. Let's look at what 0x401b15 does.
$ objdump -d -M intel --start-address=0x401b15 --stop-address=0x401b52 false_flags
0000000000401b15 <.text+0x955>:
...
401b4b: b8 0c 00 00 00 mov eax,0xc
401b50: 5d pop rbp
401b51: c3 ret
Despite some loop logic before it, the function ultimately returns 0xc (decimal 12). This index is used to select the correct flag from the array of strings we saw earlier.
3. The Solution
Now we simply need to find the string at index 12 (counting from 0) in the list we found earlier.
- {flag:This_Is_Definitely_Not_It}
- {flag:Try_Harder_To_Find_The_Key}
- {flag:Strings_Are_Misleading_You} ...
- {flag:Do_Not_Trust_Simple_Strings}
- {flag:Index_Twelve_Is_Not_Real_11}
- {flag:Reverse_Engineering_Is_Cool}
The string at index 12 is:
{flag:Reverse_Engineering_Is_Cool}
Let's verify by connecting to the remote server:
$ nc <SERVER_IP> 1301
=== The Vault of Falsehoods ===
There are many keys, but only one opens the door.
Enter the password: {flag:Reverse_Engineering_Is_Cool}
[+] Correct! Access Granted.
[*] The flag is indeed: {flag:Reverse_Engineering_Is_Cool}
Conclusion
This challenge demonstrates that while strings can reveal interesting data, understanding the logic (Control Flow) of the program is often necessary to distinguish useful data from decoys.