附件下载下来,并没有壳,直接拖入IDA,进行分析,F5一按,发现函数非常的短,被花指令干扰了,进入汇编查看

上面就是废话语句

下面就是错误语句

上面的nop掉,下面的就Uncode

其实这里就能发现第一条mov语句的操作数并不是和下面一样,推测也是识别错误

除开0E8h进行组合,就能恢复原样:

在把0E8h nop掉就好

反汇编就恢复正常了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if ( Size == 40 )
{
v5[0] = 0x673AF04AEFE18A5CLL;
v5[1] = 0xDCBAFF24A65D456LL;
v5[2] = 0xCFD8B1539076E546uLL;
v5[3] = 0xFD469B79EF8A33B7uLL;
v5[4] = 0x5985D24E20980BECLL;
v9 = (char *)KeyGen(v3);
v8 = strlen(v9);
rc4_init(v6, v9, v8);
memcpy(v7, Str, (int)Size);
rc4_crypt(v6, v7, Size);
for ( i = 0; i < (int)Size; ++i )
{
if ( v7[i] != *((_BYTE *)v5 + i) )
{
printf(&Format_);
free(Str);
return 0;
}
}
printf(&Format__0);
free(Str);
return 0;
}

查看代码逻辑可以知道,输入flag,进行rc4加密后与v5进行比较,那么反过来,v5就是flag加密后的数据。

rc4是对称加密,因此可以自己把v5输入再取出flag

现在来看KeyGen函数,猜测应该是生成的密码

毫不意外这个函数也是花指令干扰了的:

汇编代码的长度比较短

主要的代码废话在这里:

上面两句直接nop掉,下面取消编码,之后除开0e8h 再进行编码:

这个48h其实是蛮奇怪的,但是观察可以看到,上下操作的都是rax,中间出现了一个eax,尝试将其合并:

本质上就是返回这个字符串

后面就是一个rc4_init 和 rc4_encrypt ,里面也是混淆,也可以直接去除

然后就得到了正常的代码:

这个和普通的rc4还是有所区别的,就是在S表的填充上。

加密函数也是有所区别的,就是后面进行了加的操作(花指令去除比较简单就不写了):

这个就很坑爹啊,后面解密的时候要先把flag_encode进行一次自减操作,然后再来进入解密,然后再来一次自减操作

我们先把函数原封不动拖入Vs进行编译尝试,发现实现的结果跟源程序是一样的

那么加密就很简单了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int64_t key_stream[32] = { NULL };
BYTE crypt_result[40] = {
0x5C,0x8A,0xE1,0xEF,0x4A,0xF0,0x3A,0x67,0x56,0xD4,0x65,0x4A,0xF2,0xAF,0xCB,0x0D,
0x46,0xE5,0x76,0x90,0x53,0xB1,0xD8,0xCF,0xB7,0x33,0x8A,0xEF,0x79,0x9B,0x46,0xFD,
0xEC,0x0B,0x98,0x20,0x4E,0xD2,0x85,0x59
};

/*
0000000518BFF7B0 5C 8A E1 EF 4A F0 3A 67 56 D4 65 4A F2 AF CB 0D \.áïJð:gVÔeJò¯Ë.
0000000518BFF7C0 46 E5 76 90 53 B1 D8 CF B7 33 8A EF 79 9B 46 FD Fåv.S±ØÏ·3.ïy.Fý
0000000518BFF7D0 EC 0B 98 20 4E D2 85 59 10 F9 BF 18 05 00 00 00 ì.. NÒ.Y.ù¿.....
*/

rc4_init((int64_t) key_stream, (int64_t)"PickingUpFlowers", 16);
for (size_t i = 0; i != 40; ++i) {
crypt_result[i] -= i;
}
crypt((int64_t)key_stream, (int64_t)crypt_result, 40);
for (size_t i = 0; i != 40; ++i) {
crypt_result[i] -= i;
}
//flag{WO0o0O0w_So0Oo0o_m4Ny_F1oO0o0oW3R5}
return 0;

解出flag