Compiled
First download the file from the room (https://tryhackme.com/room/compiled) in order to analyze it.
strings Compiled-1688545393558.Compiled
...
PTE1
u+UH
StringsIH
sForNoobH
Password:
DoYouEven%sCTF
__dso_handle
_init
Correct!
Try again!
...
Strings is for noob
Ghidra
undefined8 main(void)
{
int iVar1;
char local_28 [32];
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;
}
-
undefined8 main(void)
:main
: This is the entry point of the program. Every C program starts execution here.void
: Thevoid
inside the parentheses means that themain
function takes no arguments.undefined8
: This indicates the return type.undefined8
is often seen in decompiled code (like what you might get from Ghidra or IDA Pro). It essentially means "an 8-byte value of unspecified type". For our purposes, think of it as a generic return type, similar toint
on many systems. The return value (0 in both success and failure cases) isn't crucial for solving the challenge.
-
int iVar1;
:- Declares an integer variable named
iVar1
. This variable will store the result of thestrcmp
function calls.
- Declares an integer variable named
-
char local_28 [32];
:- Declares a character array (a string) named
local_28
. [32]
: This array can hold up to 32 characters (including the null terminator,\0
, which marks the end of a C string). This is where the user's input will be stored. The namelocal_28
is typical of decompilers; it indicates a local variable at a specific offset on the stack.
- Declares a character array (a string) named
-
fwrite("Password: ",1,10,stdout);
:- This line prints "Password: " to the console (standard output).
fwrite
: A function that writes data to a stream."Password: "
: The string to be written.1
: The size (in bytes) of each element to be written (1 byte, because it's a character).10
: The number of elements to write (10 characters in "Password: ").stdout
: A predefined stream representing the standard output (usually the console).
-
__isoc99_scanf("DoYouEven%sCTF",local_28);
:- This is the crucial line that reads user input. It's using the
scanf
function, a standard C input function. __isoc99_scanf
: A specific version ofscanf
(likely indicating the C standard used)."DoYouEven%sCTF"
: This is the format string. The%s
is a format specifier. It tellsscanf
to expect a string from the input. The input is expected to start with "DoYouEven", followed by the string we want to capture (%s
), and it could continue with "CTF". However, the "CTF" part is not strictly enforced. The%s
will read characters until it encounters whitespace (space, tab, newline).local_28
: The address of thelocal_28
array.scanf
will write the string it reads from the input into this array.
- This is the crucial line that reads user input. It's using the
-
iVar1 = strcmp(local_28,"__dso_handle");
if ((-1 < iVar1) && (iVar1 = strcmp(local_28,"__dso_handle"), iVar1 < 1)) { ... }
:strcmp(str1, str2)
: This function compares two strings lexicographically (like dictionary order).- Returns 0 if
str1
andstr2
are equal. - Returns a value less than 0 if
str1
comes beforestr2
alphabetically. - Returns a value greater than 0 if
str1
comes afterstr2
alphabetically.
- Returns 0 if
- The first
strcmp
compares the user input with "__dso_handle". - The
if
condition is a bit convoluted. It checks ifiVar1
is greater than -1 and ifiVar1
(after being reassigned the result of the same comparison) is less than 1. - The result is that this
if
block executes if and only ifiVar1
is 0. In other words, this is a complicated way of checkingif (strcmp(local_28, "__dso_handle") == 0)
. If the strings are equal, it prints "Try again!" and exits. This is a red herring.
-
iVar1 = strcmp(local_28,"_init");
if (iVar1 == 0) { ... } else { ... }
:- This is the real password check.
strcmp
is used again, this time comparing the user input with"_init"
.if (iVar1 == 0)
: If the result ofstrcmp
is 0 (meaning the strings are equal), the "Correct!" message is printed.else
: Otherwise, "Try again!" is printed.
-
return 0;
:- This line exits the
main
function and returns a value of 0 to the operating system. A return value of 0 typically indicates successful execution.
- This line exits the
Solution
-
Input Format and
scanf
's Behavior: Thescanf
format stringDoYouEven%sCTF
is deceptive. While it suggests the input should beDoYouEven<PASSWORD>CTF
, the%s
specifier reads characters only until it finds whitespace. The "CTF" part is a potential continuation, but not a requirement. Pressing Enter adds a newline character (\n
), which is whitespace. -
Password: The code checks if the string captured by
%s
is equal to"_init"
. -
Correct Input: Because of the newline added by pressing Enter, the correct input is:
DoYouEven_init
scanf
readsDoYouEven
.scanf
encounters%s
and starts reading intolocal_28
.scanf
reads_init
.scanf
encounters the newline (\n
) from pressing Enter. Because newline is whitespace,scanf
stops reading for%s
at this point. The "CTF" part is ignored.local_28
contains "_init".- The second
strcmp
succeeds.
Key Takeaways
scanf
with%s
and Whitespace: This is the most important point.%s
inscanf
reads until any whitespace character is encountered (space, tab, newline, etc.). It does not require the rest of the format string to match exactly.- Trailing Newline: Pressing Enter adds a newline character (
\n
) to the input. This acts as the whitespace that terminates the%s
input. - Format String as a Guide: The format string in
scanf
provides a guide for the expected input, but%s
will stop reading at whitespace, regardless of the rest of the format string. - Red Herrings: The first
strcmp
check and the "CTF" in the format string are distractions.