2022 美团MTCTF初赛 small

分析

首先查壳,知道是64为无壳

image-20220921202048519

然后放入相对应的IDA,但是这里要注意一下要以Binary的方式打开,我之前用7.7版本尝试直接打开文件,发现解析不出来,这里建议用二进制方式打开

image-20220921202232501

然后就会看到一堆数据

image-20220921202310150

这里我有直接全选然后按C转换为汇编代码过,但是发现会出错,并且找不到我想要的,然后去观察

image-20220921202451223

这个0C3代表的是ret也就是一个结束,然后就从6A开始选中去按C

image-20220921202552503

发现这个unk_64函数有点点不对,然后就选中68,69这两行然后强行转换为汇编代码就成了一个对的函数

然后进行分析一下这个函数在干嘛

image-20220922193113882

这里的shl的移位和4,5的出现,能联想到这是一个tea的魔改,然后这里循环是23次,我写脚本发现不对,然后就声明了一下函数才知道是循环了35次(可能前面按C变成汇编代码的时候弄错了才导致循环次数不对,但也不怎么影响)

image-20220922193305357

接着就是去找密文

这里找密文其实挺艰难的(对我来说),首先在魔改tea函数的后面还有几个函数

image-20220922211350452

这个sub_C0函数有一个跳转与loc_EA函数有关,这两个函数好像没什么多大用,然后F1行这里有一个endp代表结束了。这里F3行开始后面的汇编代码都很不常见,还有很多花,我就把它们全选按U转换成了数据

image-20220922211703336

然后有一个good,那么就猜测good后面的应该是所需要的密文了,然后就是写脚本了

脚本

#include <stdio.h>
#include <stdint.h>
//解密函数
void decrypt(unsigned int num_rounds, uint32_t* v, uint32_t* k)
{
uint32_t v0 = v[0], v1 = v[1], i;
uint32_t delta = 0x67452301,sum = delta*num_rounds; //sum是之前加了n次的所以这里是乘以n
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i<num_rounds; i++)
{
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0;
v[1] = v1;
}
void dump_data(uint32_t * v,int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%c", (v[i] >> (j * 8)) & 0xFF);
}
}
printf("\n");
return;
}
int main()
{
uint32_t v[] = {0xde087143,0xc4f91bd2,0xdaf6dadc,0x6d9ed54c,0x75eb4ee7,0x5d1ddc04,0x511b0fd9,0x51dc88fb};//密文 (必须是8字节的倍数,且这里要注意大小端序)
uint32_t k[4] = {0x01,0x23,0x45,0x67};//4个32位无符号整数,密钥长度为128组成key
unsigned int r = 35;
int n = sizeof(v) / sizeof(uint32_t);//循环四次
for(int i=0;i<n/2;i++)
{
decrypt(r,&v[i*2],k);//一次两个 v[i]和v[i+1]
}
printf("解密后明文字符:");
dump_data(v,n);
return 0;
}
//flag{327a6c4304ad5938eaf0efb6cc3e53dc}

总结

比赛的时候是全部按C没有去想那么多,如果有去想字节码估计还是能做出来的。还有就是密文的找到方式我也不知道还有没有其他更好的方法,希望有大佬指点!!!