Let’s open ConsolePew2.exe
in JetBrains dotPeek
:
We find the code for level 2. All we need is inside the level2
and EncryptUtils
classes.
The files are in this repo for reference, but I pieced together this LINQPad
-script to solve the challenge:
From solve.linq
:
const string flag = "j+Zdll1AHhxi496ET1Nw8CjfxIoVcaVCORWgKfWiH0KaBT7zrAMQK3ysXAuxurKLHuvRne6gxht6o8+0G6XdoA==";
// Code found in `isValidWeaponCode`
var code = new char[26]
{
'$', '"', '7', '$', '\u001E', '=', '1', '5', '\u0006', ' ', '1', '$', ' ', '"', '\u001C', '*', '\u001F', ';', '\n', '`', '\u001B', '*', '\u001F', 'd', '\n', 'q'
};
// In `isValidWeaponCode` we can see that the weaponCode is XOR'ed
// with the `EPT`-key and then compared to the `code` above
// So we have the following XOR key
var xorkey = new char[3] {'E', 'P', 'T'};
// If we then XOR the `code` with the XOR-key we get the
// plaintext weapon name to use
int cnt = 0;
while (cnt < code.Length)
{
for (int i = 0; i < xorkey.Length; i++)
{
if (code.Length > cnt)
{
code[cnt] = (char)(code[cnt] ^ xorkey[i]);
}
cnt++;
}
}
//Convert.ToBase64String(code.Select(x => (byte)x).ToArray()).Dump();
var SuperSecretCode = new String(code);
SuperSecretCode.Dump();
// This is the weapon code we find
// arcaNiteReaperHoOoO0OoO0O!
// Try it:
CheckSuperSecretCode(SuperSecretCode).Dump();
// Returns: EPT{YouAreAReversingWizard}
static string CheckSuperSecretCode(string code)
{
EncryptUtils encryptUtils = new EncryptUtils();
string str = "boomLigHningBoltLigntingBoltLightnigBolt";
if (!isValidWeaponCode(code))
return "";
string encKey = str + code;
return encryptUtils.Decrypt(flag, encKey);
}
static bool isValidWeaponCode(string s)
{
char[] charArray = s.ToCharArray();
int length = s.Length;
for (int index1 = 0; index1 < length; ++index1)
{
char[] chArray = charArray;
int index2 = index1;
if (index1 % 3 == 0)
chArray[index2] ^= 'E';
else if (index1 % 3 == 1)
chArray[index2] ^= 'P';
else
chArray[index2] ^= 'T';
}
return Enumerable.SequenceEqual<char>((IEnumerable<char>)charArray, (IEnumerable<char>)new char[26]
{
'$',
'"',
'7',
'$',
'\u001E',
'=',
'1',
'5',
'\u0006',
' ',
'1',
'$',
' ',
'"',
'\u001C',
'*',
'\u001F',
';',
'\n',
'`',
'\u001B',
'*',
'\u001F',
'd',
'\n',
'q'
});
}
public class EncryptUtils
{
public string Encrypt(string cleartext, string encKey)
{
string password = encKey;
byte[] bytes = Encoding.Unicode.GetBytes(cleartext);
using (Aes aes = Aes.Create())
{
Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, new byte[13]
{
(byte) 73,
(byte) 118,
(byte) 97,
(byte) 110,
(byte) 32,
(byte) 77,
(byte) 101,
(byte) 100,
(byte) 118,
(byte) 101,
(byte) 100,
(byte) 101,
(byte) 118
});
aes.Key = rfc2898DeriveBytes.GetBytes(32);
aes.IV = rfc2898DeriveBytes.GetBytes(16);
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
((Stream)cryptoStream).Write(bytes, 0, bytes.Length);
((Stream)cryptoStream).Close();
}
cleartext = Convert.ToBase64String(memoryStream.ToArray());
}
}
return cleartext;
}
public string Decrypt(string cipherText, string encKey)
{
string password = encKey;
cipherText = cipherText.Replace(" ", "+");
byte[] numArray = Convert.FromBase64String(cipherText);
using (Aes aes = Aes.Create())
{
Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, new byte[13]
{
(byte) 73,
(byte) 118,
(byte) 97,
(byte) 110,
(byte) 32,
(byte) 77,
(byte) 101,
(byte) 100,
(byte) 118,
(byte) 101,
(byte) 100,
(byte) 101,
(byte) 118
});
aes.Key = rfc2898DeriveBytes.GetBytes(32);
aes.IV = rfc2898DeriveBytes.GetBytes(16);
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
((Stream)cryptoStream).Write(numArray, 0, numArray.Length);
((Stream)cryptoStream).Close();
}
cipherText = Encoding.Unicode.GetString(memoryStream.ToArray());
}
}
return cipherText;
}
}
Flag
EPT{YouAreAReversingWizard}