题目:[SCTF2019]Who is he
解压之后发现是unity,但这不是最主要的,主要是。。。
预感到最后的flag肯定很有意思,以至于差点忘记了自己相对不擅长unity逆向这个事实。
我们进入正题:
正题
第一步当然是Reflector查看Assembly-CSharp.dll动态链接库文件。
我们现在定位加密函数的位置,查找一下字符串“Emmmm”
双击进入
public class TestClick : MonoBehaviour
{
// Fields
private string EncryptData = "1Tsy0ZGotyMinSpxqYzVBWnfMdUcqCMLu0MA+22Jnp+MNwLHvYuFToxRQr0c+ONZc6Q7L0EAmzbycqobZHh4H23U4WDTNmmXwusW4E+SZjygsntGkO2sGA==";
private static string encryptKey = "1234";
public Text Name;
// Methods
private string Decrypt(string str)
{
try
{
byte[] bytes = Encoding.Unicode.GetBytes(encryptKey);
byte[] buffer = Convert.FromBase64String(str);
DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
MemoryStream stream = new MemoryStream();
CryptoStream stream2 = new CryptoStream(stream, provider.CreateDecryptor(bytes, bytes), CryptoStreamMode.Write);
stream2.Write(buffer, 0, buffer.Length);
stream2.FlushFinalBlock();
byte[] buffer3 = stream.ToArray();
stream2.Close();
stream.Close();
return Encoding.Unicode.GetString(buffer3);
}
catch
{
return str;
}
}
private string Encrypt(string str)
{
try
{
byte[] bytes = Encoding.Unicode.GetBytes(encryptKey);
byte[] buffer = Encoding.Unicode.GetBytes(str);
DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
MemoryStream stream = new MemoryStream();
CryptoStream stream2 = new CryptoStream(stream, provider.CreateEncryptor(bytes, bytes), CryptoStreamMode.Write);
stream2.Write(buffer, 0, buffer.Length);
stream2.FlushFinalBlock();
byte[] inArray = stream.ToArray();
stream2.Close();
stream.Close();
return Convert.ToBase64String(inArray);
}
catch
{
return str;
}
}
public void OnClick()
{
Debug.Log("Button Clicked. TestClick.");
Debug.Log(this.Name.text);
//先把字符串base64解码再des解密
if (this.Name.text.Equals(this.Decrypt(this.EncryptData)))
{
Debug.Log("Right");
Messagebox.MessageBox(IntPtr.Zero, "Haha, same as you!", "Info:", 0);
}
else
{
Debug.Log("Wrong");
Messagebox.MessageBox(IntPtr.Zero, "Emmmmm,I don't think so.", "Info:", 0);
}
}
private void Start()
{
}
// Nested Types
public class Messagebox
{
// Methods
[DllImport("User32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int MessageBox(IntPtr handle, string message, string title, int type);
}
}
主要是看Decrypt函数:
private string Decrypt(string str)
{
try
{
byte[] bytes = Encoding.Unicode.GetBytes(encryptKey);
byte[] buffer = Convert.FromBase64String(str);
DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
MemoryStream stream = new MemoryStream();
CryptoStream stream2 = new CryptoStream(stream, provider.CreateDecryptor(bytes, bytes), CryptoStreamMode.Write);
stream2.Write(buffer, 0, buffer.Length);
stream2.FlushFinalBlock();
byte[] buffer3 = stream.ToArray();
stream2.Close();
stream.Close();
return Encoding.Unicode.GetString(buffer3);
}
catch
{
return str;
}
}
这个函数把字符串str先base64解码再des解密,注意,在C#中,字符串默认是Unicode字符串,所以转成字节数组,在每个字符字节后都要加一个"\x00",附上exp:
from pyDes import des,PAD_PKCS5,CBC
import base64
s=base64.b64decode('1Tsy0ZGotyMinSpxqYzVBWnfMdUcqCMLu0MA+22Jnp+MNwLHvYuFToxRQr0c+ONZc6Q7L0EAmzbycqobZHh4H23U4WDTNmmXwusW4E+SZjygsntGkO2sGA==')
key=''.join(['1','\x00','2','\x00','3','\x00','4','\x00'])
des_obj=des(key,CBC,key,padmode=PAD_PKCS5)
m=des_obj.decrypt(s)
print(m.decode('UTF-16'))
得到了这个flag,但显示错误就离谱。。又被出题人骗了
He_P1ay_Basketball_Very_We11!Hahahahaha!
参考别的博主的wp后,用CE查看
分别右键定位内存中的位置,发现得到两个新的密文:
第二个还把密钥变了,一个个解
from pyDes import des,PAD_PKCS5,CBC
import base64
s1=base64.b64decode('q+w89Y22rObfzxgsquc5Qxbbh9ZIAHET/NncmiqEo67RrDvz34cdAk0BalKWhJGl2CBYMlr8pPA=')
key1=''.join(['1','\x00','2','\x00','3','\x00','4','\x00'])
des_obj=des(key1,CBC,key1,padmode=PAD_PKCS5)
m=des_obj.decrypt(s1)
print(m.decode('UTF-16'))
s2=base64.b64decode('xZWDZaKEhWNMCbiGYPBIlY3+arozO9zonwrYLiVL4njSez2RYM2WwsGnsnjCDnHs7N43aFvNE54noSadP9F8eEpvTs5QPG+KL0TDE/40nbU=')
key2=''.join(['t','\x00','e','\x00','s','\x00','t','\x00'])
des_obj=des(key2,CBC,key2,padmode=PAD_PKCS5)
m=des_obj.decrypt(s2)
print(m.decode('UTF-16'))
一个个提交发现第二个是真正的flag
flag{She_P1ay_Black_Hole_Very_Wel1!LOL!XD!}