(THM//MEDIUM) Classic Passwd
Difficulty: Medium // Category: reverse
Finding the flag
Finding the flag on this one is really easy, I don’t know why it’s rated as “medium difficulty”. When decompiling the binary into Cutter using the Ghidra decompiler, we get the following:
main:
undefined8 main(void)
{
vuln();
gfl();
return 0;
}
sym.vuln:
void vuln(void)
{
int32_t iVar1;
char *dest;
char *s2;
int64_t var_23eh;
int64_t var_38h;
int64_t var_30h;
int64_t var_28h;
int64_t var_20h;
int64_t var_15h;
int64_t var_dh;
var_15h = 0x207962206564614d;
var_dh._0_4_ = 0x6e6f6e34;
var_dh._4_1_ = 0;
var_38h = 0x2f2f3a7370747468;
var_30h = 0x632e627568746967;
var_28h = 0x69626f306e2f6d6f;
var_20h._0_2_ = 0x3474;
var_20h._2_1_ = 0;
s2 = (char *)0x6435736a36424741;
var_23eh._0_4_ = 0x476b6439;
var_23eh._4_2_ = 0x37;
printf("Insert your username: ");
__isoc99_scanf(data.0000201b, (int64_t)&var_23eh + 6);
strcpy(&dest, (int64_t)&var_23eh + 6);
iVar1 = strcmp(&dest, &s2);
if (iVar1 == 0) {
puts("\nWelcome");
return;
}
puts("\nAuthentication Error");
// WARNING: Subroutine does not return
exit(0);
}
sym.glf:
void gfl(void)
{
int32_t var_10h;
long long signed int var_ch;
var_ch._0_4_ = 0x52c8d5;
do {
if (0x77d088 < (int32_t)var_ch) {
return;
}
if ((int32_t)var_ch == 0x638a78) {
for (var_10h = 0x1474; var_10h < 9999; var_10h = var_10h + 1) {
if (var_10h == 0x2130) {
printf("THM{%d%d}", 0x638a78, 0x2130);
// WARNING: Subroutine does not return
exit(0);
}
}
}
var_ch._0_4_ = (int32_t)var_ch + 1;
} while( true );
}
I started looking at the vuln() function and renaming variables, but then I told myself that I should look at all the relevant code. When looking at glf(), it clearly appears that the flag is.. directly printed? I wrote this very small program:
#include <stdio.h>
int main()
{
printf("THM{%d%d}", 0x638a78, 0x2130);
return 0;
}
compiled it, and it displayed the flag!
$ gcc main.c -o main
$ ./main
THM{REDACTED}
Well, okay :^)
Actually reversing the program
I’m not satisfied with this answer, so I tried to properly reverse the binary and find the correct input that would lead me to the flag being displayed. To solve this challenge, we just have to enter in the if{} block in the vuln() function. After a little bit of clean-up, here’s what I got:
void vuln(void)
{
int32_t result;
char *user_input;
char *secret;
int64_t var_23eh;
secret = (char *)0x6435736a36424741; // d5sj6BGA
var_23eh._0_4_ = 0x476b6439; // Gkd9
var_23eh._4_2_ = 0x37; // 7
printf("Insert your username: ");
scanf(data.0000201b, (int64_t)&var_23eh + 6);
strcpy(&user_input, (int64_t)&var_23eh + 6);
result = strcmp(&user_input, &secret);
if (result == 0) {
puts("\nWelcome");
return;
}
puts("\nAuthentication Error");
exit(0);
}
What’s interesting is that the value we have to find is composed of a concatenation of secret and what’s inside var_23eh. As we’re in little endian, var_23eh is equal to 9dkG7 and secret is AGB6js5d, so our secret is the concatenation of both those strings:
$ ./challenge
Insert your username: AGB6js5d9dkG7
Welcome
THM{REDACTED}