逆向一个简单的VM crackme

其实这个比较简单了,ida的f5都能清晰地看出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void __noreturn start()
{
int v0; // eax@1
char *v1; // ST1C_4@1
char v2; // [sp+4h] [bp-90h]@1

MD5::MD5(&v2);
v0 = GetProcessHeap(0, 507);
dword_40423C = (char *)HeapAlloc(v0); // 分配一段内存
memcpy(dword_40423C, &unk_404040, 0x1FBu); // 将VM Code复制到这段内存
sub_4022E0(); // 这个函数里面是对40423c这段VM Code进行处理(虚拟执行)
v1 = MD5::digestString((MD5 *)&v2, dword_40423C);// 对其md5并输出
MessageBoxA(0, v1, "We've been compromised!", 48);
ExitProcess(0);
}

我们看看sub_4022E0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
char sub_4022E0()
{
int one; // ST0C_4@2
unsigned __int8 v1; // ST1B_1@2
int two; // ST10_4@2
char three; // ST14_1@2
char result; // al@2
unsigned __int8 i; // [sp+Fh] [bp-1h]@1

i = 0;
do
{ // 可以看到处理是从255开始的
one = (unsigned __int8)dword_40423C[i + 255];// 取第一个字节
v1 = i + 1;
two = (unsigned __int8)dword_40423C[v1++ + 255];// 接着取第二个字节
three = dword_40423C[v1 + 255]; // 上面取完后++了,这里是取第三个
i = v1 + 1;
result = sub_402270(one, two, three); // 对传入的3个字节进行处理
}
while ( result );
return result;
}

我们再看sub_402270,这里就比较简单了,就是对第一个字节进行判断,跟着利用2,3个字节对dword_40423C后面的数据进行操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
char __stdcall sub_402270(int a1, int a2, char a3)
{
if ( a1 == 1 )
{
dword_40423C[a2] = a3;
}
else if ( a1 == 2 )
{
byte_404240 = dword_40423C[a2];
}
else
{
if ( a1 != 3 )
return 0;
dword_40423C[a2] ^= byte_404240;
}
return 1;
}

写代码

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
class VM:
def __init__(self, VM_ram):
self.VM_Data = (bytearray)(VM_ram[:255])
self.VM_Code = VM_ram[255:]

def VM_Run(self):
ret = 1
i = 0
while ret:
opcode = ord(self.VM_Code[i])
operand1 = ord(self.VM_Code[i + 1])
operand2 = ord(self.VM_Code[i + 2])
ret = self.decode(opcode, operand1, operand2)
i = i + 3

def decode(self, opcode, operand1, operand2):
if opcode == 1:
self.VM_Data[operand1] = operand2
elif opcode == 2:
self.tmp = self.VM_Data[operand1]
else:
if opcode != 3:
return 0
self.VM_Data[operand1] = self.VM_Data[operand1] ^ self.tmp
return 1

with open("ram.bin", 'rb') as f:
VM_ram = f.read()

vm = VM(VM_ram)
vm.VM_Run()
print vm.VM_Data

结果

reference

https://secrary.com/CrackMe/VM_1_MalwareTech/

打赏专区