Shadw_vault HackHub CTF

Dr.kasbr
4 min read5 days ago

--

Hey everyone! This was a fun reverse engineering challenge! We’re dealing with a virus that encrypts a secret, built with C code inside another virus developed in Rust. Let’s hunt it down and uncover the flag! 🕵️‍♂️

soo we have

enc_flag=905884E03CE01CA08014A4E098BC501C68C598D0601810B45CCDEDDD8014D4C93CCD20D5545498A8801C6C0C

i started analyzing by Ghidra and here we can see its rust code and I found a suspicious hex string in the strings section. So, I extracted it for decoding

I stumbled upon the magic phrase:

"This program cannot be run in DOS mode."

That tells us we’re dealing with an executable file. Our friend “Dev3il” left their mark, but we need to fix the signature before we can dive deeper

soo we can find all signature from here or we can use any another exe to be faster

so after fix it let’s analyze it

and here we can see the main

int __fastcall main(int argc, const char **argv, const char **envp) {
char v4[21]; // Buffer for the flag
void *Block;
size_t Size;
char *Str;
__int64 v8;
size_t k, j, i;


_main();
strcpy(v4, "FlagY{DUMMY}"); // Placeholder for the flag
v8 = 12i64;
Str = (char *)LOOOL(v4, 12i64); // Call to the LOOOL function
Size = strlen(Str);
Block = malloc(Size); // Allocate memory for the encoded string
if (Block) {
for (i = 0; i < Size; ++i)
*((_BYTE *)Block + i) = Str[i] ^ 0x42; // XOR operation
*(_QWORD *)&v4[13] = malloc(Size); // Allocate space for the final output
if (*(_QWORD *)&v4[13]) {
// Process and output the encoded string
for (j = 0; j < Size; ++j)
printf("%02X", *(unsigned __int8 *)(*(_QWORD *)&v4[13] + j));
printf("\n");
free(Str);
free(Block);
free(*(void **)&v4[13]);
return 0;
} else {
free(Str);
free(Block);
return 1;
}
} else {
free(Str);
return 1;
}
}

What About the LOOOL Function?

The LOOOL function is where the magic happens for encoding the string into base64. It processes the input and makes things a bit more complex with some XOR action

_BYTE *__fastcall LOOOL(__int64 a1, int a2)
{
int v3; // eax
int v4; // eax
int v5; // eax
int v6; // eax
int v7; // eax
int v8; // eax
char v9; // dl
int v10; // eax
char v11; // dl
int v12; // eax
unsigned int v13; // [rsp+28h] [rbp-28h]
int v14; // [rsp+30h] [rbp-20h]
int v15; // [rsp+34h] [rbp-1Ch]
_BYTE *v16; // [rsp+38h] [rbp-18h]
int v17; // [rsp+44h] [rbp-Ch]
int v18; // [rsp+48h] [rbp-8h]
int v19; // [rsp+48h] [rbp-8h]
int v20; // [rsp+48h] [rbp-8h]
int v21; // [rsp+4Ch] [rbp-4h]
v17 = 4 * ((a2 + 2) / 3);
v16 = malloc(v17 + 1);
if ( !v16 )
return 0i64;
v21 = 0;
v18 = 0;
while ( v21 < a2 )
{
v3 = v21++;
v15 = *(unsigned __int8 *)(v3 + a1);
if ( v21 >= a2 )
{
v5 = 0;
}
else
{
v4 = v21++;
v5 = *(unsigned __int8 *)(v4 + a1);
}
v14 = v5;
if ( v21 >= a2 )
{
v7 = 0;
}
else
{
v6 = v21++;
v7 = *(unsigned __int8 *)(v6 + a1);
}
v13 = v7 | (v15 << 16) | (v14 << 8);
v16[v18] = base64_chars[(v13 >> 18) & 0x3F];
v8 = v18 + 1;
v19 = v18 + 2;
v16[v8] = base64_chars[(v13 >> 12) & 0x3F];
if ( v21 > a2 + 1 )
v9 = 61;
else
v9 = base64_chars[(v13 >> 6) & 0x3F];
v10 = v19;
v20 = v19 + 1;
v16[v10] = v9;
if ( v21 > a2 )
v11 = 61;
else
v11 = base64_chars[v13 & 0x3F];
v12 = v20;
v18 = v20 + 1;
v16[v12] = v11;
}
v16[v17] = 0;
return v16;
}

soo The flag undergoes three transformations:

Base64 Encoding — Done by the function LOOOL

XOR Encryption — Each byte is XOR-ed with 0x42

Bit Manipulation — (byte >> 6) | (byte * 4) scrambles the bits

🕵️ Reversing the Encryption

To retrieve the flag, we reverse all transformations:

  1. Reverse Bit Manipulation
  2. Reverse XOR (^ 0x42)
  3. Base64 Decode
import base64

def reverse_bit_manipulation(byte):
for i in range(256):
if (i >> 6) | (i * 4) & 0xFF == byte:
return i
return 0

def decrypt_flag(enc_flag_hex):
enc_flag = bytes.fromhex(enc_flag_hex)
reversed_bytes = bytearray()

for byte in enc_flag:
reversed_byte = reverse_bit_manipulation(byte) ^ 0x42
reversed_bytes.append(reversed_byte)

return base64.b64decode(reversed_bytes).decode()

enc_flag = "905884E03CE01CA08014A4E098BC501C68C598D0601810B45CCDEDDD8014D4C93CCD20D5545498A8801C6C0C"
flag = decrypt_flag(enc_flag)
print(flag[::-1]) # Reverse the final output
FlagY{R34lly_Sh1dow_Dev3il#1337}

--

--

No responses yet