cd ../../CrackMe Solutions

Reverse Engineering simple VM crackme

3 minutes read

The crackme is created by @MalwareTechLab, you can download the sample from here.

We have three files, vm1.exe, ram.bin and README.txt:

1

click here for larger version.

This malware has stolen a flag and encrypted it with a very simple encryption algorithm; unfortunately, the decrypter is coded in a custom 8-bit assembly language which it runs using a minimalistic virtual machine. Your job is to reverse egineer the malware and figure out the instruction set used by the VM, once you've done this you should write your own VM in Python which will run the decrypter and recover the flag.

Before continue, I recommend you to read the paper Introduction to Modern Code Virtualization and the post Tutorial for Building and Reverse Engineering Simple Virtual Machine Protection, because in this post, I don’t explain how Virtual Machines and a Virtulized code works in general, above-mentioned posts do a great job for introduction.

Let’s open the IDA and see what we have. The crackme copies 0x1FB bytes from VM_code into VM_ram (the copied data is the same as ram.bin file’s content) and calls VM_run:

2

The following is Python implementation of the code fragment:

3

Inside VM_run, it fetches opcode and two operands and calls VM_decode. As we see it fetches opcode from the second part of VM_ram (actually from VM_ram + 0xff), we can guess that code section starts from there.

NOTE: For example, in MOV eax, 1 instruction, MOV is opcode, eax and 1 are operands.

4

Python implementation:

5

VM_decode executes a different code block based on the fetched opcode:

6

click here for larger version.

  • If opcode is 1, it writes the second operand to the data section at position pointed by the first operand (MOV VM_data[operand_1], operand_2).

  • If opcode is 2, it saves the data pointed by the first operand into the global variable, I renamed it as R0 - register 0 (MOV R0, operand_2).

  • If opcode is 3, it XORs data pointed by the first operand with R0 (XOR VM_data[operand_1], R0).

That’s whole instruction set, so simple.

Python implementation of VM_decode function:

7

That’s all, we know that the first part of the ram.bin file is data section, the second one is code section and we have just three instructions.

After running the Python implementation, we get the flag: FLAG{VMS-ARE-FOR-MALWARE}

8

Whole Python script: