一
Snake
简单的把代码扔给在线解密网站就可以看出来是个RC4,只是最后异或加了一个和循环次数异或。略过不提了。
但是有一点是,我本来是想试试用CE把分数改成9999来出的,但是,这游戏没法暂停的话我没时间去修改。一死亡就会结束。对于这一点想的是用IDA调试把它的进程挂起,但终归还是有点拼手速而且好像新建的进程也不属于它了,不会在IDA UI的右下角显示。
总之,最后还是选择去常规逆向了。
二
HardSignin
手脱的话ESP断点没断住,于是就没有再深挖,做完后来看的话,可能是被反调结束了吗?不知道有没有师傅解答一下。
脱掉后放进IDA会发现一个很明显的TLS_3,于是转过去,查看调用,发现其他的tls。
但是这个main异或似乎有点问题,就是没有实现它正常来说的作用,我调试的话每次都会挂掉,main函数被修正后并不能很好地运行。
所以我把这里的异或改成了0。
#include <idc.idc>
static main()
{
auto x,Fbin,ProcRange;
for (x=0x401890;x<0x40193A;x=x+1)
{ Fbin=Byte(x);
PatchByte (x,Fbin^0x66);//nop掉
}
}
然后就是常规解密。我的解密脚本没放一起,base64和rc4都是常规,这里只放一个容易出错的tea吧。
#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 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 = 0x61C88647;
for (i = 0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = v0; v[1] = v1;
}
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 1640531527, sum = 0 - delta * num_rounds;
for (i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum += delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}
int main()
{
//uint32_t v[2] = { 1,2 };
//uint32_t const k[4] = { 2,2,3,4 };
//unsigned int r = 32;//num_rounds建议取值为32
//// v为要加密的数据是两个32位无符号整数
//// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
//printf("加密前原始数据:%u %un", v[0], v[1]);
//encipher(r, v, k);
//printf("加密后的数据:%u %un", v[0], v[1]);
//decipher(r, v, k);
//printf("解密后的数据:%u %un", v[0], v[1]);
//return 0;
int i, len, j;
//密文或明文
unsigned char eninput[] = { 0x59, 0x1B, 0xFD, 0xB4, 0x6B, 0xB8, 0xBE, 0xD9, 0xB3, 0xD3, 0x77, 0xD6, 0xF0, 0x65, 0x5F, 0x18,
0xA0, 0x9D, 0x3A, 0x53, 0x6D, 0x4A, 0x7B, 0x26, 0x74, 0x3A, 0x9C, 0x4E, 0x20, 0x43, 0x19, 0xD8,
0x72, 0xED, 0x95, 0xB5, 0x9C, 0x05, 0x22, 0x56, 0xCB, 0x7A, 0x11, 0x91, 0x9F, 0x7A, 0xBC, 0x0C,
0x4A, 0x69, 0x6D, 0xCE, 0x3D, 0xB4, 0xAB, 0x29, 0x61, 0xFA, 0x62, 0x32, 0xB4, 0xEC, 0x4C, 0xB6,0x00 };
len = strlen(eninput);
eninput[len] = 0;
int r = 100;//加解密轮数
//4yZRiNP8LoK/GSA5ElWkUjXtJCz7bMYcuFfpm6+hV0rxeHIdwv32QOTnqg1BDsa9
//0x49338976, 0xC7C31319, 0x68E4D8AD, 0xBC0448FC
//0x0CAA5BDD, 0xD6846924, 0x51041EB8, 0x8B2AAB06
for (i = 0; i < len / 8; i++)
{
int* v = (int*)eninput + i * 2, k[] = { 0x0CAA5BDD, 0xD6846924, 0x51041EB8, 0x8B2AAB06 };
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
/* encrypt(v, k);
printf("加密后的数据:%u %un", v[0], v[1]);*/
decipher(r, v, k);
}
//printf("%s", eninput);
for (int g = 0; g < 64; g++)
printf("0x%x,", eninput[g]);
return 0;
}
三
Bedtea
这个值会用来生成tea的密钥,生成规律应该是斐波那契数列。
然后就是最后的比较了。
只是这个语言的原因有点难看。
#include <stdio.h>
#include <stdint.h>
#include<string.h>
//加密函数
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum =0, i; /* set up */
unsigned int delta = 0x61CBB648; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
i = 0;/* cache key */
printf("0x%x,0x%xn", v0, v1);
do { /* basic cycle start */
sum -= delta;
v0 += ((v1 >> 4) + k1) ^ (v1 + sum) ^ ((v1*32) + k0);
v1 += ((v0 >> 4) + k3) ^ (v0 + sum) ^ ((v0*32) + k2);
} while (sum != 0x987E55D0);
v[0] = v0; v[1] = v1;
}
//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], i; /* set up */
uint32_t delta = 0x61CBB648; /* a key schedule constant */
unsigned int sum =0x987E55D0;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
i = 0;/* cache key */
do { /* basic cycle start */
v1 -= ((v0 >> 4) + k3) ^ (v0 + sum) ^ ((v0*32) + k2);
v0 -= ((v1 >> 4) + k1) ^ (v1 + sum) ^ ((v1*32) + k0);
sum += delta;
} while (sum != 0);
v[0] = v0; v[1] = v1;
}
int main()
{
int i, len, j;
//密文或明文
unsigned char ddd[] = { 0x0076, 0x0071, 0x009D, 0x00E7, 0x0070, 0x0077, 0x003F, 0x00A3,
0x0002, 0x00F1, 0x008D, 0x00C9, 0x0002, 0x00C6, 0x00A2, 0x004B,
0x00BA, 0x0019, 0x0056, 0x0005, 0x00F2, 0x0089, 0x005E, 0x00E0,0x00 };
unsigned char eninput[25];
for (int i = 0; i < 24; i++)
{
ddd[i] ^= 0x33;
}
for (int i = 0; i < 24; i++)
{
eninput[i] = ddd[23 - i];
printf("0x%x,", eninput[i]);
}
printf("nn");
unsigned char input[] = "123456789012345678901234";
// unsigned char eninput[] = { 0xd3,0x6d,0xba,0xc1,0x36,0x65,0x2a,0x89,0x78,0x91,0xf5,0x31,0xfa,0xbe,0xc2,0x31,0x90,0xc,0x44,0x43,0xd4,0xae,0x42,0x45,0x00 };
len = 24;
eninput[len] = 0;
for (i = 0; i < len / 8; i++)
{
unsigned int* v = (int*)eninput + i * 2, k[] = { 0x3, 0x5, 0x8, 0xD };
unsigned int k1[] = {0x15,0x22,0x37,0x59};
unsigned int k2[] = { 0x00000090, 0x000000E9, 0x00000179, 0x00000262 };
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
/* encrypt(v, k);
printf("加密后的数据:%u %un", v[0], v[1]);*/
if(i==0)
decrypt(v, k);
if(i==1)
decrypt(v, k1);
if (i==2)
decrypt(v, k2);
//encrypt(v, k);
}
printf("%s",eninput);
return 0;
}
//k={8,0xD,0x15,0x22}
//k={0x37,0x59,0x90,0xE9}
看雪ID:螺丝兔
https://bbs.kanxue.com/user-home-992277.htm
# 往期推荐
2、恶意木马历险记
球分享
球点赞
球在看
点击阅读原文查看更多
原文始发于微信公众号(看雪学苑):春秋杯Re 2024 赛题解析