32位调用64位exe程序 #
在x64系统下,程序一般分为32位和64位程序,但是32位程序可以调用64位的代码,32位模式的时候,CS=0x23,64位的时候CS=0x33,如果要切换这两种模式,就需要汇编指令retf,所以32位程序调用64位代码的特征为0x33和retf,当存在这种情况时,不能正常识别成代码,只有16进制的数或者汇编,静态和动调都会不好弄,现在来做一个题目
查看sub_402420函数处的汇编,发现了retf和0x33,所以在这里调用了64位的程序,所以下面没有正确识别
010把它改成64的程序,试图---模板结果,找到程序的信息
然后再给他改成64位
修改之后,程序就变成了64位,就可以识别代码了,但是刚打开还是比较乱
rebase,把基址改成和原来程序一样的基址,然后定位到retf下面那里,可以看到,和原来的402176的内容是一样的
然后重新定义,就得到了加密的逻辑
是一个魔改xxtea
下一步,就是寻找enc,在原来的程序中比较好找,其实就是unk_42771C
查看sub_402480函数,正好是4个一组
得到加密后的值
0xF5, 0x58, 0xF7, 0xD8, 0xDB, 0x49, 0x68, 0x52, 0x63, 0x25,
0xD7, 0xE2, 0xAC, 0xEF, 0x5E, 0x48, 0xC6, 0x4B, 0x8F, 0x60,
0x6A, 0xF7, 0x59, 0x58, 0xA3, 0x65, 0x35, 0xB0, 0xC1, 0x91,
0x40, 0x3E, 0x9A, 0x5B, 0xDB, 0xD3
1
2
3
4
2
3
4
最后写出解密脚本
#include <stdio.h>
#include <stdint.h>
#include<iostream>
using namespace std;
void decrypt(unsigned int *v)
{
unsigned int z;
unsigned int sum;
unsigned int e;
int i;
unsigned int y;
uint32_t k[4] = {0xEFCDAB89, 0x10325476, 0x98BADCFE, 0xC3D2E1F0};
y = v[0];
sum = 0xD73DA40C;
do
{
for ( i = 8; i > 0; --i )
{
e = (sum >> 2) & 3;
z = v[i - 1];
y = v[i] -= (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (k[(i&3)^e] ^ z)));
}
z = v[8];
y = v[0] -= (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (k[(i&3)^e] ^ z)));
sum -= 0x67452301;
}
while (sum != 0 );
}
int main() {
uint32_t v[9] = {
0xD8F758F5, 0x526849DB, 0xE2D72563, 0x485EEFAC, 0x608F4BC6, 0x5859F76A, 0xB03565A3, 0x3E4091C1,
0xD3DB5B9A
};
decrypt(v);
printf("%s",v);
return 0;
}
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
flag
flag{529e3d91db48e084f76fca97b94499}
1