BASEic (SunshineCTF 2025)
BASEic (SunshineCTF 2025)
Steps:
- Read the binary in Ghidra and locate the flag check in FUN_001014d1.
- Notice it base64 encodes your input with a custom routine and compares against a hardcoded prefix plus a trailing chunk stored in .rodata.
- Concatenate the two base64 strings to get the full target base64 of the correct input.
- Base64 decode that target to recover the flag.
- Optionally verify by re-encoding the recovered flag and comparing.
Detailed Explanation
We are given an x86_64 ELF. The interesting function is the programs entry’s target, which Ghidra names FUN_001014d1. Here is some relevant logic:
Seeds a buffer with a literal from .rodata
1
builtin_strncpy(local_56, "yX0I0NTM1fQ==", 0x0e);
It asks for input and appends it after those 14 bytes:
1
2
printf("What is the flag> ");
scanf("%s", local_56 + 0xe);
It requires raw input to be 0x16 bytes:
1
if (strlen(local_56 + 0xe) == 0x16){...}
it then base64 encodes only the input using the function at FUN_001012c6:
1
2
size_t n = strlen(local_56 + 0xe);
char *b64 = FUN_001012c6(local_56 + 0xe, n);
Then the result is checked in two parts:
1
2
3
4
5
6
if (strncmp(b64, "c3Vue2MwdjNyMW5nX3V", 0x13) == 0) {
size_t m = strlen(local_56);
if (strncmp(b64 + 0x13, local_56, m) == 0) {
puts("You got it, submit the flag!");
}
}
From these two checks we learn that the correct input must be:
1
"c3Vue2MwdjNyMW5nX3V" + "yX0I0NTM1fQ==" = c3Vue2MwdjNyMW5nX3VyX0I0NTM1fQ==
When we base64 decode the string we get the plaintext flag:
flag: sun{c0v3r1ng_ur_B4535}
This post is licensed under CC BY 4.0 by the author.