提示:MD5(rctf{your answer}) == 5f8243a662cf71bf31d2b2602638dc1d
首先看主函数:
逻辑很清晰,首先提示,输入正确的flag会得到Bingo!的提示
接收输入,输入长度要求是16字符
然后三个函数调用:
sub_C00:将输入转换成十六进制保存
sub_1180:使用xxtea算法解密,然后使用长度减去最后一个字节的值,截断出这么多字节的内容
sub_13D0:CRC16算法校验,CRC16的特征:根据首位是不是1来进行异或0x1021
根据提示,最后输出的应该是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}