Last updated on 2021年7月4日
题目来源:2021 虎符ctf
初步分析
这是一个.exe文件,我们用Exeinfo PE打开
发现这是一个Go语言编写的64位程序
我们运行一下查看它的功能:
它读取一行输入作为flag,然后进行判断
逆向分析
我们在IDA中打开它,直接找到main_main
函数
程序的逻辑主要在如下几个函数:main_check
,main_NewCipher
,main__myCipher__Encrypt
,internal_bytealg_Equal
main_check
这个函数要求输入长度为42,并且格式为flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
。
main__myCipher__Encrypt
很明显,是delta
值为0x12345678
的XTEA算法。
main_end是一个函数数组,main_end[4]为encoding_binary__bigEndian__PutUint32,这里它将XTEA加密的输出转为大端序。
internal_bytealg_Equal
该函数将输入的加密值与真正的值进行对比
静态key和cipher
到了这一步,我们还有这几项未知:XTEA加密使用的key,用于对比的真正的cipher
回到main_main函数,我们发现这里从堆上读取了两个静态数据,并且一个用于加密的初始化,另一个用于对比,并且数据长度均为128-bit,于是我们可以合理猜测这两个值分别是加密使用的key和真正的密文,这里我把它命名为key和cipher。
main_NewCipher
128-bit key刚好是4个32-bit无符号整型,main_end[8] 为encoding_binary__bigEndian_Uint32,将key中每个32-bit无符号整型转为大端序。
flag代码
#include
const int delta = 0x12345678;
unsigned int key[4] = {0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F};
unsigned int cipher[4] = {0x0EC311F0, 0x45C79AF3, 0xEDF5D910, 0x542702CB};
void decrypt(unsigned int *v, unsigned int *key)
{
unsigned int l = v[0], r = v[1], sum = 0;
sum = delta * 32;
for (int i = 0; i < 32; i++)
{
r -= (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
l -= (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]);
}
v[0] = l;
v[1] = r;
}
int main()
{
decrypt(cipher, key);
decrypt(cipher + 2, key);
for(int i = 0; i < 4; ++i) printf("%x", cipher[i]);
}
我们再将输出按照格式进行排布
flag
flag{3bbcf9ea-2918-4fee-8a2e-201b47dfcb4e}