roger 发表于 2019-5-17 09:49:33

ReRijndael解题writeup

#题目分析
使用.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);
            //newRijndaelManaged,调用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、newRijndaelManaged,调用CryptoStream 的write进行数据加密
7、将加密后的数据转换成base64,返回。
8、结果为“ “4RTlF9Ca2+oqExJwx68FiA== ”即可。
整个程序都使用标准的.net库实现,在微软官方中找到一个相关的加解密算法:[点我](https://docs.microsoft.com/zh-cn/dotnet/api/system.security.cryptography.rijndaelmanaged?redirectedfrom=MSDN&view=netframework-4.7.2)
#解密脚本
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 密文 偏移
![](data/attachment/album/201905/17/094515tt7x2qeur4r4647x.jpg)
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);
            //newRijndaelManaged,调用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脚本,如下:




页: [1]
查看完整版本: ReRijndael解题writeup