
Classic Passwd
Platform : TryHackMe
Type : Challenge
Difficulty : ⭐⭐⭐☆☆
Table of contents
Basic analysis
First, I used file Challenge.Challenge to know what type of file it is :
┌──(attacker㉿AttackBox)-[~/Bureau/CTF/Classic_Passwd]
└─$ file Challenge.Challenge
Challenge.Challenge: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=b80ce38cb25d043128bc2c4e1e122c3d4fbba7f7, for GNU/Linux 3.2.0, not strippedReversing with Ghidra
Looking at the functions in the executable, we can see 3 interesting functions :
main<- The main functiongfl<- Seems to stand for « Get flag »vuln<- Vulnerable function ?
First, let’s see the source code of the main function :
undefined8 main(void)
{
vuln();
gfl();
return 0;
}We see in the main function (this function is the entry point of the program) that there is 2 functions called. vuln() and then gfl(). I think gfl stands for ‘get flag’, and obviously, vuln stands for vulnerable. Let’s take a look at the vuln function :
void vuln(void)
{
int iVar1;
char local_2c8 [130];
undefined8 local_246;
undefined4 local_23e;
undefined2 local_23a;
char local_238 [512];
undefined8 local_38;
undefined8 local_30;
undefined8 local_28;
undefined2 local_20;
undefined local_1e;
undefined8 local_15;
undefined4 local_d;
undefined local_9;
local_15 = 0x207962206564614d;
local_d = 0x6e6f6e34;
local_9 = 0;
local_38 = 0x2f2f3a7370747468;
local_30 = 0x632e627568746967;
local_28 = 0x69626f306e2f6d6f;
local_20 = 0x3474;
local_1e = 0;
local_246 = 0x6435736a36424741;
local_23e = 0x476b6439;
local_23a = 0x37;
printf("Insert your username: ");
__isoc99_scanf(&DAT_0010201b,local_238);
strcpy(local_2c8,local_238);
iVar1 = strcmp(local_2c8,(char *)&local_246);
if (iVar1 == 0) {
puts("\nWelcome");
return;
}
puts("\nAuthentication Error");
/* WARNING: Subroutine does not return */
exit(0);
}So what is happening in this function ? First, there are some variable declarations. We can skip this for the moment. Then, the program asks a username to the user using the scanf function. The program copies the variable local_238 (which contains the string the user entered before) to the variable local_2c8.
Then, it compares the variable local_2c8 to the variable local_246 (so we can assume that local_246 contains the right username). If they are equal, the program prints Welcome, else, it prints Authentification Error.
Resolving the challenge
First method
Knowing that local_246 contains the right username, we can look at its value and try to decode it. So local_246 is equal to 0x6435736a36424741. But remember, this is an ELF 64-bit **LSB** pie executable, which means that we have to start interpreting this value from the least significant bit. So let’s reverse it like so : 41 47 42 36 6a 73 35 64
Now let’s decode this to ASCII : AGB6js5d
If you try to use this as a username, it won’t work. Why ? Because it’s only a part of the username to find. Looking at the C code in ghidra don’t help. So let’s take a look at the assembly code :

We can see that there are 3 hexadecimal values here, the first one is the one we already decoded, and the two others seems to be the missing parts of the username. You may be asking « Why those three values ? ». To answer this question, we must know something about the strcmp function. This function will read strings till it encounters a null byte. But as you can see, those 3 values are not separeted by a null byte.
The first null byte strcmp will encounter when reading memory from the first string is right after the third string (0x37). So let’s try to decode the two values we are missing and see if it works :
0x476b6439->9dkG0x37->7
So if we take the 3 values we found and put them together, we have AGB6js5d9dkG7. Let’s use it in the program to get the flag :
attacker@AttackBox:~/Bureau/CTF/Classic_Passwd$ ./Challenge.Challenge
Insert your username: AGB6js5d9dkG7
Welcome
THM{<REDACTED>}
attacker@AttackBox:~/Bureau/CTF/Classic_Passwd$Second method
We can use ltrace to recover the value of local_246 variable (the variable that contains the right username). I used ltrace ./Challenge.Challenge. When the program asked for a username, I just entered a random string test. And I got the value of variable local_246 :
attacker@AttackBox:~/Bureau/CTF/Classic_Passwd$ ltrace ./Challenge.Challenge
printf("Insert your username: ") = 22
__isoc99_scanf(0x55b7e298d01b, 0x7ffda64a7a60, 0, 0Insert your username: test
) = 1
strcpy(0x7ffda64a79d0, "test") = 0x7ffda64a79d0
strcmp("test", "AGB6js5d9dkG7") = 51
puts("\nAuthentication Error"
Authentication Error
) = 22
exit(0 <no return ...>
+++ exited (status 0) +++Now we have the right username which is AGB6js5d9dkG7. To get the flag, we just have to execute the binary like this : ./Challenge.Challenge. When the executable asks for a username, we just need to enter AGB6js5d9dkG7, and we have the flag !
attacker@AttackBox:~/Bureau/CTF/Classic_Passwd$ ./Challenge.Challenge
Insert your username: AGB6js5d9dkG7
Welcome
THM{<REDACTED>}Third method
There is a third method to get the flag, but this time without finding the right username. Let’s take a look at the gfl function :
void gfl(void)
{
int local_10;
int local_c;
local_c = 0x52c8d5;
do {
if (0x77d088 < local_c) {
return;
}
if (local_c == 0x638a78) {
for (local_10 = 0x1474; local_10 < 9999; local_10 = local_10 + 1) {
if (local_10 == 0x2130) {
printf("THM{%d%d}",0x638a78,0x2130);
/* WARNING: Subroutine does not return */
exit(0);
}
}
}
local_c = local_c + 1;
} while( true );
}Let’s resume what happens in this function :
- There is some variables declarations of course. After that, there is a while loop.
- In this while loop, if the variable
local_cis greater than0x77d088, we exit thegflfunction and it returns nothing. - Then, if the
local_cvariable is equal to0x638a78, we enter in a for loop. - At the beginning of the for loop, we give the
local_10variable an initial value of0x1474, and since it is lesser than9999, we increase this variable by1and we continue to go throughout the for loop. - In the for loop, we check if
local_10is equal to0x2130, iftrue, we print something in the console.
Let’s take a closer look at this print. It looks like it is the flag we are looking for. The two hexadecimal values passed as arguments in the function are interpreted as integer values (because of the %d in the print), so let’s try to convert them to integer values :
- The first one (
0x638a78) is equal to6523512 - The second (
0x2130) is equal to8496
So we have the flag : THM{<REDACTED>}.
Tools used
| Tool | Purpose |
|---|---|
| file | Analyse the binary headers |
| ltrace | Display calls to shared libraries |
| Ghidra | – Analyse the binary assembly code – Rebuild the C code of the binary |
| RapidTables | Convert hexadecimal values to string or integers |
Sources
- strcmp function : https://www.geeksforgeeks.org/strcmp-in-c/