TryHackMe: Compiled CTF Walkthrough
🧰 Writeup Overview
This writeup explains the reverse-engineering of the provided ELF binary Compiled.Compiled, culminating in finding the correct input that triggers the message Correct!.
Compiled CTF Challenge | TryHackMe
Initial Enumeration
File Type Check
1
file Compiled.Compiled
- ELF 64-bit LSB pie executable, dynamically linked (using
ld‑linux‑x86_64.so.2), not stripped: symbol names are available.
Strings Inspection
1
strings Compiled.Compiled
Key findings:
Password:DoYouEven%sCTF__dso_handle_initCorrect!&Try again!
These strongly hint that input is processed via a custom scanf format string, with logic comparing two strings.
Runtime Behavior
Test Basic Execution
1
2
3
4
./Compiled.Compiled
# Try random password:
Password: test
Try again!
Monitor with ltrace
1
ltrace ./Compiled.Compiled
Input:
1
test
Output trace:
1
2
3
4
5
6
7
write("Password: ", 1, 10, 0x7f7af50705c0) = 10
__isoc99_scanf(0x55d159b6700f, 0x7ffe92dfe6b0, 0, 1024Password: test
) = 0
strcmp("", "__dso_handle") = -95
strcmp("", "_init") = -95
printf("Try again!") = 10
Try again!+++ exited (status 0) +++
Reverse Engineering the Logic
Disassemble or Use Ghidra / IDA
Here’s a deep dive explanation of decompiled pseudo‑C logic main() function, Let’s break it down line-by-line.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
undefined8 main(void)
{
int iVar1;
char local_28 [32]; // 32-byte buffer
fwrite("Password: ", 1, 10, stdout);
__isoc99_scanf("DoYouEven%sCTF", local_28);
iVar1 = strcmp(local_28, "__dso_handle");
if ((-1 < iVar1) && (iVar1 = strcmp(local_28,"__dso_handle"), iVar1 < 1)) {
printf("Try again!");
return 0;
}
iVar1 = strcmp(local_28, "_init");
if (iVar1 == 0) {
printf("Correct!");
}
else {
printf("Try again!");
}
return 0;
}
🧠 Line-by-Line Breakdown
char local_28[32];
- A 32-byte buffer to store the user input.
- Used to store the result of the
scanf.
fwrite("Password: ", 1, 10, stdout);
- Displays the prompt:
Password: - Equivalent to
printf("Password: ");but done using fwrite() in this case.
__isoc99_scanf("DoYouEven%sCTF", local_28);, 📌 Key Point
- The format string
DoYouEven%sCTFmeans: - It expects the user to input a string that matches this exact pattern.
- For example, if user types DoYouEven
ABCCTF, then: The string"ABC"will be extracted and stored intolocal_28. - Only the
%spart is stored – the surrounding text (DoYouEvenandCTF) is just expected for formatting.
🧪 Example:
1
2
Input: DoYouEventestCTF
Then local_28 = "test"
Behavior:
The format string “DoYouEven%sCTF” expects:
Literal “DoYouEven” at the start.
A string (%s) in the middle.
Literal “CTF” at the end.
Only the %s part is stored in input.
🔑 Important:
%sis wrapped by fixed strings, so user must input format as string
strcmp(local_28, "__dso_handle")
- Compares user input against
"__dso_handle". - If equal, strcmp() returns
0.
Then we enter this condition:
1
if ((-1 < iVar1) && (iVar1 = strcmp(local_28,"__dso_handle"), iVar1 < 1))
🧠 What’s Going On?
- This is a tricky condition.
- It does a double comparison against
"__dso_handle", structured like:
1
if (strcmp(...) >= 0 && strcmp(...) <= 0)
- So the only possible value that passes is when:
strcmp(...) == 0
If input is "__dso_handle" until if true:
printf("Try again!")is shown. -Function returns early.
🔐 This acts as a blacklist: if you input "__dso_handle" → it gets blocked.
strcmp(local_28, "_init")
- If the above check is bypassed, the code now compares input with “_init”.
✅ If local_28 == “_init” Message: Correct!
❌ Else Message: Try again!
✅ Correct Summary
- If input is
"__dso_handle"→ “Try again!” Failure because Blacklisted. - If input is
"_init"→ “Correct!” - Anything else → “Try again!”
1
DoYouEven<password>
And only <password> is stored.
Final Payload & Result
This triggers the “Correct!” message because:
scanfextracts_init(betweenDoYouEvenand theend of input)._initis not blacklisted and matches the expected string.If you
omit CTF, scanf will still store _init (since%sstops at whitespace or end of input) ==> correct, but some binaries may reject due to extra input such this case.CTF(matches format, but ignored).
%s in scanf stops reading when it encounters several cases:
- Whitespace (space, tab, newline).
- End of input (if no more characters are available).
like that
1
./Compiled.Compiled
Enter:
1
DoYouEven_initCTF
Output:
1
Try again!
1
./Compiled.Compiled
Enter:
1
DoYouEven_init
Output:
1
Correct!
1
ltrace ./Compiled.Compiled
Enter:
1
DoYouEven_init
Output:
1
2
3
4
5
6
7
8
fwrite("Password: ", 1, 10, 0x7f95a0c605c0) = 10
__isoc99_scanf(0x5601aa8f200f, 0x7ffd41387e90, 0, 1024Password: DoYouEven_init
) = 1
strcmp("_init", "__dso_handle") = 10
strcmp("_init", "__dso_handle") = 10
strcmp("_init", "_init") = 0
printf("Correct!") = 8
Correct!+++ exited (status 0) +++
👏 Clear indication that _init is accepted after bypassing the blacklist & making strcmp("_init", "_init") = 0.


