CAF 2023 - Babyrev
Table of Contents
In this article, we will explore the step-by-step walkthrough of the Reverse challenge ‘BabyRev’ presented at the CTF Cyber Africa Forum 2023.
Binary Analysis
We have the following binary available for download here .
Decompilation with IDA Free
Let’s use our favorite tool IDA Free to decompile the binary. Here, I will make my work easier by using IDA’s Generate PseudoCode feature.
Figure 0x1 – Pseudocode
Main Function Analysis
In the main() function we have the following code:
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char v4[58]; // [rsp+6h] [rbp-42Ah] BYREF
char v5[1000]; // [rsp+40h] [rbp-3F0h] BYREF
unsigned __int64 v6; // [rsp+428h] [rbp-8h]
v6: __readfsqword(0x28u);
strcpy(&v4[10], "lQsgGDW4k+uOMRezzlftzfou4uT>^bAbmsPEe");
strcpy(v4, "xorcaf123");
sub_1189(&v4[10], v4, v5);
printf("Ciphertext: %s\n", v5);
return 0LL;
}
This C pseudocode is a program that encrypts text using a key and displays the encrypted text. There are two character arrays, v4 and v5. The v4 array contains the encryption key and the text to encrypt. Then, the program calls the sub_1189() function to encrypt the text using the key. The encrypted text is stored in the v5 array. Finally, the program displays the encrypted text on screen.
XOR Function Analysis
Let’s see what the sub_1189() function does:
_BYTE *__fastcall sub_1189(const char *a1, const char *a2, __int64 a3)
{
_BYTE *result; // rax
int i; // [rsp+24h] [rbp-Ch]
int v6; // [rsp+28h] [rbp-8h]
int v7; // [rsp+2Ch] [rbp-4h]
v6: strlen(a1);
v7: strlen(a2);
for ( i = 0; i < v6; ++i )
*(_BYTE *)(i + a3) = a1[i] ^ a2[i % v7];
result: (_BYTE *)(i + a3);
*result = 0;
return result;
}
The sub_1189() function takes three arguments as input: const char *a1 (the text to encrypt), const char *a2 (the encryption key), and __int64 a3 (the address of the array to store the encrypted text). This function performs a simple XOR encryption by combining the characters of the text to encrypt with the characters of the key.
Decryption Process
Python Implementation
For the Python enthusiasts among you, here is the Python equivalent:
def sub_1189(a1, a2):
v6: len(a1)
v7: len(a2)
result: []
for i in range(v6):
xor_result: ord(a1[i]) ^ ord(a2[i % v7])
result.append(chr(xor_result))
return ''.join(result)
key: "xorcaf123"
ciphertext: "lQsgGDW4k+uOMRezzlftzfou4uT>^bAbmsPEe"
plaintext: sub_1189(ciphertext, key)
print("Plaintext:", plaintext)
Base85 Decoding
What is intriguing here is that the ciphertext is not even XORed, so it’s another encoding or encryption.
I take a look at CyberChef :
I use the “Magic” option, and then the text was already decrypted, it was simply base85.
Figure 0x2 – Flag
Flag
So the flag is CAF_{x0r_1s_n0t_much_c0mpl3x}