题目分析
使用.net编写,用Reflector反编译看一下:
private static void Main(string[] A_0)
{
Console.WriteLine("Please Input Serial:");
if (B(Console.ReadLine(), "Kanxue2019") == "4RTlF9Ca2+oqExJwx68FiA==")
{
Console.WriteLine("Congratulations! : )");
Console.ReadLine();
}
}
如果a函数的返回值为 “4RTlF9Ca2+oqExJwx68FiA==”表示成功。看一下a函数,如下:
public static string B(string A_0, string A_1)
{
byte[] bytes = Encoding.UTF8.GetBytes("Kanxue2019CTF-Q1");//将 “Kanxue2019” 转换为utf8字节数据。 (bytes)
byte[] bytes2 = Encoding.UTF8.GetBytes(A_0);//将用户输入转换为utf8字节数据。
byte[] bytes3 = new PasswordDeriveBytes(A_1, null).GetBytes(32);//调用 PasswordDeriveBytes函数产生一个rgbKey
ICryptoTransform transform = new RijndaelManaged
//使用 bytes与 rgbKey 作为输入调用RijndaelManaged产生一个 ICryptoTransform transform
{
Mode = CipherMode.CBC
}.CreateEncryptor(bytes3, bytes);// 使用指定的密钥和初始化向量(IV) 创建对称加密器对象。
MemoryStream memoryStream = new MemoryStream();//new 一个 MemoryStream()
CryptoStream expr_4F = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write);
//new RijndaelManaged,调用CryptoStream 的write进行数据加密
expr_4F.Write(bytes2, 0, bytes2.Length);
expr_4F.FlushFinalBlock();
byte[] inArray = memoryStream.ToArray();
memoryStream.Close();
expr_4F.Close();
//return Convert.ToBase64String(inArray);
return Convert.ToBase64String(inArray);//将加密后的数据转换成base64,返回
}
看起来是使用标准的.net加密算法进行加密。其中“Kanxue2019”作为秘钥,用户输入作为被加密的数据。
1、将 “Kanxue2019” 转换为utf8字节数据。 (bytes)
2、 将用户输入转换为utf8字节数据。
3、调用 PasswordDeriveBytes函数产生一个rgbKey
4、使用 bytes与 rgbKey 作为输入调用RijndaelManaged产生一个 ICryptoTransform transform
5、new 一个 MemoryStream()
6、new RijndaelManaged,调用CryptoStream 的write进行数据加密
7、将加密后的数据转换成base64,返回。
8、结果为“ “4RTlF9Ca2+oqExJwx68FiA== ”即可。
整个程序都使用标准的.net库实现,在微软官方中找到一个相关的加解密算法:点我
解密脚本
C#解密算法如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
class RijndaelExample
{
static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
static void Main()
{
byte[] text = Convert.FromBase64String("4RTlF9Ca2+oqExJwx68FiA==");
byte[] iv = Encoding.UTF8.GetBytes("Kanxue2019CTF-Q1");
byte[] rgbKey = new PasswordDeriveBytes("Kanxue2019", null).GetBytes(0x20);
string str = DecryptStringFromBytes(text, rgbKey, iv);
Console.WriteLine(str);
}
}
用python写解密脚本会容易一些,分析程序可以明显发现是一个标准的AES-CBC加密,密钥和向量都可以提取出来,下断点可以看到 AES的各解密参数:CBC key 密文 偏移
python解密脚本如下:
(注意安装加解密模块pip3 install pycryptodome)
import base64
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
data = "4RTlF9Ca2+oqExJwx68FiA=="
cipher_data=base64.b64decode(data)
H = b'\xE1\x14\xE5\x17\xD0\x9A\xDB\xEA\x2A\x13\x12\x70\xC7\xAF\x05\x88'
key= b'\x6D\xDE\xF7\xA4\x3C\x00\x4F\x7D\x69\x83\x04\x4B\x1E\x36\xA9\x34\x59\xF1\x8B\xC8\x37\xC4\x6E\xAF\x32\x11\x32\x73\x41\x63\xA0\xB4'
IV=b'Kanxue2019CTF-Q1'
aes=AES.new(key,AES.MODE_CBC,IV)
r=aes.decrypt(H)
print(r)
题目源码
题目完整源码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace pda_demo
{
class Program
{
private static void Main(string[] A_0)
{
Console.WriteLine("Please Input Serial:");
if (B(Console.ReadLine(), "Kanxue2019") == "4RTlF9Ca2+oqExJwx68FiA==")
{
Console.WriteLine("Congratulations! : )");
Console.ReadLine();
}
}
public static string B(string A_0, string A_1)
{
byte[] bytes = Encoding.UTF8.GetBytes("Kanxue2019CTF-Q1");//将 “Kanxue2019” 转换为utf8字节数据。 (bytes)
byte[] bytes2 = Encoding.UTF8.GetBytes(A_0);//将用户输入转换为utf8字节数据。
byte[] bytes3 = new PasswordDeriveBytes(A_1, null).GetBytes(32);//调用 PasswordDeriveBytes函数产生一个rgbKey
ICryptoTransform transform = new RijndaelManaged
//使用 bytes与 rgbKey 作为输入调用RijndaelManaged产生一个 ICryptoTransform transform
{
Mode = CipherMode.CBC
}.CreateEncryptor(bytes3, bytes);// 使用指定的密钥和初始化向量(IV) 创建对称加密器对象。
MemoryStream memoryStream = new MemoryStream();//new 一个 MemoryStream()
CryptoStream expr_4F = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write);
//new RijndaelManaged,调用CryptoStream 的write进行数据加密
expr_4F.Write(bytes2, 0, bytes2.Length);
expr_4F.FlushFinalBlock();
byte[] inArray = memoryStream.ToArray();
memoryStream.Close();
expr_4F.Close();
//return Convert.ToBase64String(inArray);
return Convert.ToBase64String(inArray);//将加密后的数据转换成base64,返回
}
}
}
源码下载
动手能力差的小伙伴直接下载下面的附件即可
完整的VScode解题源码,题目源码,python脚本,如下: