In the previous post, we found the following url:
(In case link disappears, I’ve put a copy here).
Having never written an emulator/VM before, I thought it would be fun to give it a go. The file gives a pretty concise description of how the processor works. However, there are a few points which, with clarification, make the problem easier:
- Operand 1 is always an index to a register.
- Operand 2 is an index to a register if mod = 0, else it is an immediate value or segment number.
- A mod0 JMP, mod0 JMPE and HLT are all one byte long.
- In the table, r1 means ‘register pointed to by operand 1′ and r2 means ‘register pointed to by operand 2′.
- The specification for a long JMP and JMPE (mod1) is wrong. It should read imm:r1 and not r2:r1. Or, if the specification is right, the code in the memory provided is wrong, as instruction at 0×16 is invalid for the provided specification. Using imm:r1 as the actual specification results in a correct solution!
- Finally, the bit that got me stuck the longest: a long JMP (mod1 JMP and mod1 JMPE) must change the value of CS (code segment). Then a near JMP (mod0 JMPs) jumps to CS*16 + operand 1. This is kind of obvious in retrospect!
Here’s my solution, written in C.
Here’s me stepping through the output of my ‘decompiler’ (by ‘decompiler’, I mean a small modification to my VM where jumps don’t change the instruction pointer!):
This first loop decodes (XORs with 170) some executable code, starting at location 0×100. The command at 0×16 (not shown), then jumps to this new code. The new code then decodes the hidden string.
My VM executes until the HLT command and then dumps the memory. In the memory is the decoded link to the final part of the problem:
GET /da75370fe15c4148bd4ceec861fbdaa5.exe HTTP/1.0
Time to start the next part!