2022HGAME中REVERSE的creakme2
下载附件:
.
.
照例扔入 exeinfope 中查看信息:
.
.
照例扔入 IDA64 中查看伪代码,有 main 函数看 main 函数:
.
.
F5 未生成的异常与回调函数处理:
但是常规的 XTEA 解密算法并不对,一开始怀疑题目错了,果然还是自己太菜了,出人意料的结果都是表明中间存在未分析的操作啊!
(这里是除 0 异常和异常处理回调函数,虽然不知道那里限定了 loc_140001141 就是回调函数)
.
.
修改一下 XTEA 加密算法拿到 sum 的值先:
#include<stdio.h>
#include<stdint.h>
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]){
unsigned int i;
uint32_t v0=v[0],v1=v[1],sum=0,delta=0x9E3779B1;
for(i=0;i<num_rounds;i++){
v0+=(((v1<<4)^(v1>>5))+v1)^(sum+key[sum&3]);
sum+=delta;
if(sum>>31==0)
sum^=0x1234567;
v1+=(((v0<<4)^(v0>>5))+v0)^(sum+key[(sum>>11)&3]);
}
v[0]=v0;v[1]=v1;
printf("%x\n",sum);
printf("%lu\n",sum);
printf("%d",sum);
}
int main(){
uint32_t v[2]={1,2};
uint32_t const k[4]={2,2,3,4};
unsigned int r=32; //这里是加密轮数,自己设置
printf("加密前原始数据:%u %u\n",v[0],v[1]);
encipher(r,v,k);
return 0;
}
.
.
拿到 sum 值后编写解密代码:
#include <stdio.h>
#include <stdint.h>
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=-946975483, i; //这里的sum=32*delta,但是注意溢出的截取,否则就错了
uint32_t delta=0x9E3779B1;
//uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
for (i=0; i<32; i++) {
//v1-=(((v0<<4)^(v0>>5))+v0)^(sum+k[4*((sum>>11)&3)]);
v1-=(((v0<<4)^(v0>>5))+v0)^(sum+k[(sum>>11)&3]);
if (sum >> 31 == 0)
sum ^= 0x1234567;
sum-=delta;
//v0-=(((v1<<4)^(v1>>5))+v1)^(sum+k[4*(sum&3)]);,IDA 的地址都是单个的,对于 DWORD 类型要 IDA 会自己乘以 4,形成我们看到的 *(DWORD)(a3+4*i),而不像我们C语言中直接的 (a3+i) 就是跨越 a3 大小类型的 i
v0-=(((v1<<4)^(v1>>5))+v1)^(sum+k[sum&3]);
}
v[0]=v0; v[1]=v1;
}
int main()
{
uint32_t v[4][2]={{1165910735,-1791522452},{528383858,-140479528},{-1902548888,1085255577},{261688884,426721414}};
//uint32_t k[10]={1,2,3,4,5,6,7,8,9,0};
uint32_t k[4]={1,2,3,4};//虽然题目密钥给了10个,但其实我们只要前128位的4个就可以了
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
printf("加密前原始数据:%u %u\n",v[0],v[1]);
for(int i=0;i<4;i++)
decrypt(v[i],k);
for (int a = 0; a < 4; a++)
{
for (int b = 0; b < 2; b++)
{
for(int c=0; c<4; c++)
printf("%c", (v[a][b] >> (c * 8)) & 0xFF); //C语言32位数字符拼接
}
}
return 0;
}
.
.
解毕!
敬礼!