Après les verifications d’usage (file, strings), une execution ou 2 qui retournent un “Nope!” déplaisant… go Ghidra!
Chance, tout semble dans le main.
Le voici avec quelques remplacements de noms de variables pour y voir plus clair et mes commentaires de lecture :
undefined8 main(void)
{
int iVar1;
char *usr_input;
undefined8 uVar2;
long in_FS_OFFSET;
size_t usr_input_len;
undefined8 ii;
char usr_input_buff [48];
char flag [32];
undefined1 uStack_18;
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
usr_input = fgets(usr_input_buff,0x28,stdin);
if (usr_input == (char *)0x0) {
puts("Nope.");
uVar2 = 1;
}
else {
usr_input_len = strlen(usr_input_buff);
/* remove \n replace by \0 */
if ((usr_input_len != 0) && (usr_input_buff[usr_input_len - 1] == '\n')) {
usr_input_buff[usr_input_len - 1] = '\0';
usr_input_len = usr_input_len - 1;
}
/* flag must be 32 chars long */
if (usr_input_len == 0x20) {
for (ii = 0; ii < 0x20; ii = ii + 1) {
flag[(ii * 0x11 + 0x33) % 0x20] = usr_input_buff[ii];
}
uStack_18 = 0;
iVar1 = strcmp(flag,"4B}mCuCNJmeVhvCzQusFHS7{2gCBCrQW");
if (iVar1 == 0) {
puts("Congrats! You can use this flag to validate the challenge.");
}
else {
puts("Nope.");
}
uVar2 = 0;
}
else {
puts("Nope.");
uVar2 = 1;
}
}
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return uVar2;
}
Tout se joue dans la boucle for.
Le ii ème caractère de la saisie est égal au [(ii * 0x11 + 0x33) % 0x20]-ième caractère de la chaine mélangée.
Facile a inverser avec un peu de Python :
exploit = [""]*32
print(exploit)
scrambled = "4B}mCuCNJmeVhvCzQusFHS7{2gCBCrQW"
for ii in range(32):
jj = (ii * 0x11 + 0x33) % 0x20
exploit[ii]=scrambled[jj]
print("".join(exploit))