selph
selph
Published on 2022-11-30 / 221 Visits
0
0

RCTF 2019 Writeup Re-babyre1

提示:MD5(rctf{your answer}) == 5f8243a662cf71bf31d2b2602638dc1d

首先看主函数:

image

逻辑很清晰,首先提示,输入正确的flag会得到Bingo!的提示

接收输入,输入长度要求是16字符

然后三个函数调用:

sub_C00:将输入转换成十六进制保存

sub_1180:使用xxtea算法解密,然后使用长度减去最后一个字节的值,截断出这么多字节的内容

image

sub_13D0:CRC16算法校验,CRC16的特征:根据首位是不是1来进行异或0x1021

image

根据提示,最后输出的应该是Bingo!​所以,这里的长度v9应该是6,最后一个字符是02

上面的校验通过之后,接下来,对v6字符数组进行异或解密,然后打印

根据提示,这里打印的内容是Bingo!

通过对该字符异或加密,可以得到xxtea解密后的结果序列:55 7e 79 70 78 36 XX 02(XX表示未知)

只有1个字节的值不知道,可以爆破处理,向该位置填充不同的值,然后XXTEA加密之后生成flag的格式进行md5加密,和提示中的信息进行比对

生成flag:

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cryptopp/md5.h>
#include <cryptopp/hex.h>

#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t* v, int n, uint32_t const key[4])
{
    uint32_t y, z, sum;
    unsigned p, rounds, e;
    if (n > 1)            /* Coding Part */
    {
        rounds = 6 + 52 / n;
        sum = 0;
        z = v[n - 1];
        do
        {
            sum += DELTA;
            e = (sum >> 2) & 3;
            for (p = 0; p < n - 1; p++)
            {
                y = v[p + 1];
                z = v[p] += MX;
            }
            y = v[0];
            z = v[n - 1] += MX;
        } while (--rounds);
    }
    else if (n < -1)      /* Decoding Part */
    {
        n = -n;
        rounds = 6 + 52 / n;
        sum = rounds * DELTA;
        y = v[0];
        do
        {
            e = (sum >> 2) & 3;
            for (p = n - 1; p > 0; p--)
            {
                z = v[p - 1];
                y = v[p] -= MX;
            }
            z = v[n - 1];
            y = v[0] -= MX;
            sum -= DELTA;
        } while (--rounds);
    }
}



int main()
{
    uint32_t key[] = { 0xe0c7e0c7   ,   0xc6f1d3d7     , 0xc6d3c6d3      ,0xc4d0d2ce };
    //char key_[9] = "Bingo!";
    //for (int i = 0; i < 6; i++)
    //{
    //    key_[i] ^= 0x17;
    //}

    for (int i = 0; i < 256; i++)
    {
        uint8_t data[] = { 0x55, 0x7e , 0x79 , 0x70 , 0x78 , 0x36 , 0x00 , 0x02 };
        data[6] = i;
        btea((uint32_t*)data, 2, key);
        //btea((uint32_t*)data, -2, key);
      

        std::string flag = "rctf{";
        char tmp[20] = { 0 };
        for (int i = 0; i <8; i++) sprintf(&tmp[i*2], "%02x", data[i]);
        flag += tmp;
        flag += "}";

        std::string digest;
        CryptoPP::Weak1::MD5 hash;
      
        hash.Update((const CryptoPP::byte*)&flag[0],flag.size());
        digest.resize(hash.DigestSize());
        hash.Final((CryptoPP::byte*)&digest[0]);

        CryptoPP::HexEncoder encoder(nullptr,false);
        encoder.Put((CryptoPP::byte*)&digest[0], digest.size());
        encoder.MessageEnd();

        std::string encoded;
        CryptoPP::word64 size = encoder.MaxRetrievable();
        encoded.resize(size);
        encoder.Get((CryptoPP::byte*)&encoded[0], encoded.size());

        if (!strcmp(encoded.c_str(),"5f8243a662cf71bf31d2b2602638dc1d")) {
            std::cout << flag;
        }
      
    }
    return 0;

}

附上一份别人写的python脚本:(python写这种东西是真的快捷方便…也许我应该转python来写题解之类的)

import xxtea
import hashlib
key = [0xc7,0xe0,0xc7,0xe0,0xd7,0xd3,0xf1,0xc6,0xd3,0xc6,0xd3,0xc6,0xce,0xd2,0xd0,0xc4]
key = "".join(chr(m) for m in key)
text = [0x55,0x7e,0x79,0x70,0x78,0x36,0x0,0x0]
for i in range(0xff):
    for j in range(4):
        text[6] = i
        text[7] = j
        encrypt_data = xxtea.encrypt("".join(chr(n) for n in text),key)
        encrypt_data = encrypt_data.hex()
flag = "rctf{"+ encrypt_data +"}"
hl = hashlib.md5()
hl.update(flag.encode(encoding='utf-8'))
if hl.hexdigest() == '5f8243a662cf71bf31d2b2602638dc1d':
    print("yesyes")
    print(encrypt_data)
 
#rctf{05e8a376e4e0446e}

Comment