这道题比赛的时候没有做出来,现在来复盘一下
主函数逻辑比较简单,xtea加密,加密后的结果已经给出了:
其中xtea加密的delta值改变了,是dword_7FF7FAEF3034,其值为0x9E3779B1
本来以为就这么简单,调试之后发现程序中有除0异常,也就是SEH反调试,分析汇编代码:
sum的值存在了eax寄存器中,然后右移31位,如果右移后的结果为0,则触发除0异常,程序会跳转到__except(loc_7FF7FAEF1DF6)去执行,即判断sum的最高位是否为0,如果为0,则sum异或0x1234567,综上所述,可以得到实现的脚本:
#include <stdio.h>
#include <stdint.h>
/* take 64 bits of data in v[0] and v[1] and */
/* 128 bits of key[0] - key[3] */
void encrypt(unsigned int num_rounds, uint32_t v[2], uint32_t key[4]){
uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B1;//delta的值变化其他不变
int i;
for(i=0; i<num_rounds; i++){
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;//sum加上delta之后才进行的判断
if (sum>>31==0)
{
sum ^= 0x1234567;
}
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
//printf("%#x %#x\n",v0,v1);
}
v[0] = v0;
v[1] = v1;
}
void decrypt(unsigned int num_rounds, uint32_t v[2], uint32_t key[4]){
uint32_t v0=v[0], v1=v[1], delta=0x9E3779B1, sum=0xc78e4d05;
int i;
for(i=0; i<num_rounds; i++){
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11)&3]);
if (sum>>31==0)//解密过程是加密过程的逆过程,所以要先进行判断再减去delta的值
{
sum ^= 0x1234567;
}
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0;
v[1] = v1;
}
int main(void){
uint32_t v[2]={0xF990E34,0x196F4086};
//0x457E62CF,0x9537896C
//0x1F7E7F72,0xF7A073D8
//0x8E996868,0x40AFAF99
//0xF990E34,0x196F4086
uint32_t k[4]={1,2,3,4};//密钥为1234而不是123456789
unsigned int r=32;//num_rounds建议取值为32
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
printf("%#x %#x\n",v[0],v[1]);
//encrypt(r, v, k);
printf("%#x %#x\n",v[0],v[1]);
decrypt(r, v, k);
printf("%#x %#x\n",v[0],v[1]);
return 0;
}
最后得到的值一个一个转化为字符即可得到flag:
hgame{SEH_s0und5_50_1ntere5ting}