Warmup, 960 pt
Run the binary and it asks for a passcode. Time to open it in IDA and see what it does with our input.
Digging into the decompiled code, one function stands out: it appends == at the end of its output. That padding is a dead giveaway for base64. I renamed the function accordingly, and sure enough it’s a hand-rolled base64 encoder running over the flag input.
_int64 __fastcall base64(__int64 flag_input, unsigned int a2, __int64 s_output)
{
unsigned int v3; // eax
unsigned int i; // [rsp+20h] [rbp-20h]
unsigned int v6; // [rsp+24h] [rbp-1Ch]
unsigned int v7; // [rsp+28h] [rbp-18h]
int v8; // [rsp+2Ch] [rbp-14h]
int v9; // [rsp+30h] [rbp-10h]
int v10; // [rsp+34h] [rbp-Ch]
unsigned __int64 v11; // [rsp+38h] [rbp-8h]
v11 = __readfsqword(0x28u);
v6 = 0;
v7 = 0;
for ( i = 0; i < a2; ++i )
{
v3 = v6++;
*(&v8 + v3) = *(_DWORD *)(4LL * i + flag_input);
if ( v6 == 3 )
{
*(_BYTE *)(s_output + v7) = abcd_string[(unsigned __int8)v8 >> 2];
*(_BYTE *)(s_output + v7 + 1) = abcd_string[((unsigned __int8)v9 >> 4) | 16 * (_BYTE)v8 & 48];
*(_BYTE *)(s_output + v7 + 2) = abcd_string[((unsigned __int8)v10 >> 6) | 4 * (_BYTE)v9 & 60];
*(_BYTE *)(s_output + v7 + 3) = abcd_string[v10 & 63];
v6 = 0;
v7 += 4;
}
}
if ( v6 )
{
if ( v6 == 1 )
v9 = 0;
*(_BYTE *)(s_output + v7) = abcd_string[(unsigned __int8)v8 >> 2];
*(_BYTE *)(s_output + v7 + 1) = abcd_string[((unsigned __int8)v9 >> 4) | 16 * (_BYTE)v8 & 48];
if ( v6 == 2 )
*(_BYTE *)(s_output + v7 + 2) = abcd_string[4 * (_BYTE)v9 & 60];
else
*(_BYTE *)(v7 + 2 + s_output) = '=';
*(_BYTE *)(v7 + 3 + s_output) = '=';
v7 += 4;
}
*(_BYTE *)(v7 + s_output) = 0;
return v7;
}
The routine is standard base64: it processes the input in 3-byte groups, shifting and masking bits, and indexes into the character set stored in abcd_string. After encoding, the binary checks the base64 output byte by byte. The comparisons are all straightforward, so I worked through them by hand and turned the constraints into a script that reconstructs each flag byte:
s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
flag = ["?"]*36
flag[0] = s[28]
flag[1] = s[54]
flag[2] = s[(82 >> 2)+1]
flag[3] = "j"
flag[4] = chr(ord(flag[0])+1)
flag[5] = "X"
flag[6] = chr(ord(flag[3])-32)
flag[7] = chr(112)
flag[8] = chr(ord(s[28])-1)
flag[10] = flag[2]
flag[11] = chr(48)
flag[12] = chr(ord(flag[4])-1)
flag[13] = "3"
flag[14] = chr(ord(flag[7])+4)
flag[15] = chr(ord(flag[7])+3)
flag[17] = "3"
flag[18] = chr(ord(flag[7])-30)
flag[19] = chr(122)
flag[20] = "X"
flag[21] = "3"
flag[22] = chr(ord(flag[4])-1)
flag[23] = chr(48)
flag[24] = chr(ord(flag[4])-1)
flag[26] = chr(49)
flag[27] = chr(ord(flag[4])+2)
flag[29] = "X"
flag[30] = flag[18]
flag[31] = flag[27]
flag[9] = chr(ord(flag[27])+7)
flag[16] = chr(ord(flag[9])-32)
flag[25] = chr(ord(flag[27])+7)
flag[28] = flag[16]
flag[32] = flag[4]
flag[33] = "X"
flag[34] = chr(ord(flag[0])-33)
flag[35] = chr(ord(flag[11]) + 9)
print(flag)
flag = ''.join(flag)
try:
print flag.decode('base64')
except:
print('Nope')
flag : securinets{l3ts_w4rm_1t_up}