CanYouCrackIt Part 2
Part 2
Now I do feel bad about posting this... and I did once sign a bit of paper that said I could not make models of airfields but seeing as the cat is out of the bag with the aforementioned publicity I will continue... however if you have not seen the solution I urge you to try yourself... the fun is in the solving not the solution.
In Part 1 we took a program and some ciphertext and revealed a partial URL which we pretty obviously stick on the end of the main site URL giving...
http://canyoucrackit.co.uk/15b436de1f9107f3778aad525e5d0b20.js
Which in turn produces a document..
Building the VM
Although I know some JavaScript I'm no guru so I reverted to using Java instead (and since this is a VM it's pretty language agnostic). Everything went pretty well until I became unstuck with the last instructions of the top section which are 10 10. Now 10 is Opcode 0 i.e. JMP in Mode 1 which implies jmp r2:r1 instuction but operand 2 is 10 (i.e. 16 in decimal) which is way too big to be a register number. I spent a long time wrangling with this and eventually realised that it had to be a jump and that if it was not a register number it must be an immediate value. I then patched my code to imply that a number outside the register range should be an immediate and hey presto it worked. I blame a poor specification but perhaps this alludes to machine implementations not always following the specs that are intended to define them; hardware has bugs too.
Finally we also note the presence of unexplained baggage...
Anyway... time to move on to Step 3
Now I do feel bad about posting this... and I did once sign a bit of paper that said I could not make models of airfields but seeing as the cat is out of the bag with the aforementioned publicity I will continue... however if you have not seen the solution I urge you to try yourself... the fun is in the solving not the solution.
In Part 1 we took a program and some ciphertext and revealed a partial URL which we pretty obviously stick on the end of the main site URL giving...
http://canyoucrackit.co.uk/15b436de1f9107f3778aad525e5d0b20.js
Which in turn produces a document..
This seems to be pretty self-explanatory in that it appears to be a fragment of JavaScript alluding to a virtual machine. The machine instructions are defined in the comments so it is just a case of providing an implementation. A quick observation suggests a program at the top (IP 0000) and a block further down that presumeably is ciphertext. A Halt instruction is documented so the logical approach is build the machine, run the code until the Halt and then inspect memory for interesting bits and pieces.//--------------------------------------------------------------------------------------------------
//
// stage 2 of 3
//
// challenge:
// reveal the solution within VM.mem
//
// disclaimer:
// tested in ie 9, firefox 6, chrome 14 and v8 shell (http://code.google.com/apis/v8/build.html),
// other javascript implementations may or may not work.
//
//--------------------------------------------------------------------------------------------------
var VM = {
cpu: {
ip: 0x00,
r0: 0x00,
r1: 0x00,
r2: 0x00,
r3: 0x00,
cs: 0x00,
ds: 0x10,
fl: 0x00,
firmware: [0xd2ab1f05, 0xda13f110]
},
mem: [
0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50,
0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8,
0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9,
0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56,
0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9,
0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69,
0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60,
0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8,
0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d,
0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67,
0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a,
0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9,
0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e,
0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55,
0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3,
0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f,
0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d,
0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1,
0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94,
0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62,
0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b,
0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1,
0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61,
0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14,
0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2,
0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1,
0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
],
exec: function()
{
// virtual machine architecture
// ++++++++++++++++++++++++++++
//
// segmented memory model with 16-byte segment size (notation seg:offset)
//
// 4 general-purpose registers (r0-r3)
// 2 segment registers (cs, ds equiv. to r4, r5)
// 1 flags register (fl)
//
// instruction encoding
// ++++++++++++++++++++
//
// byte 1 byte 2 (optional)
// bits [ 7 6 5 4 3 2 1 0 ] [ 7 6 5 4 3 2 1 0 ]
// opcode - - -
// mod -
// operand1 - - - -
// operand2 - - - - - - - -
//
// operand1 is always a register index
// operand2 is optional, depending upon the instruction set specified below
// the value of mod alters the meaning of any operand2
// 0: operand2 = reg ix
// 1: operand2 = fixed immediate value or target segment (depending on instruction)
//
// instruction set
// +++++++++++++++
//
// Notes:
// * r1, r2 => operand 1 is register 1, operand 2 is register 2
// * movr r1, r2 => move contents of register r2 into register r1
//
// opcode | instruction | operands (mod 0) | operands (mod 1)
// -------+-------------+------------------+-----------------
// 0x00 | jmp | r1 | r2:r1
// 0x01 | movr | r1, r2 | rx, imm
// 0x02 | movm | r1, [ds:r2] | [ds:r1], r2
// 0x03 | add | r1, r2 | r1, imm
// 0x04 | xor | r1, r2 | r1, imm
// 0x05 | cmp | r1, r2 | r1, imm
// 0x06 | jmpe | r1 | r2:r1
// 0x07 | hlt | N/A | N/A
//
// flags
// +++++
//
// cmp r1, r2 instruction results in:
// r1 == r2 => fl = 0
// r1 < r2 => fl = 0xff
// r1 > r2 => fl = 1
//
// jmpe r1
// => if (fl == 0) jmp r1
// else nop
throw "VM.exec not yet implemented";
}
};
//--------------------------------------------------------------------------------------------------
try
{
VM.exec();
}
catch(e)
{
alert('\nError: ' + e + '\n');
}
//--------------------------------------------------------------------------------------------------
Building the VM
Although I know some JavaScript I'm no guru so I reverted to using Java instead (and since this is a VM it's pretty language agnostic). Everything went pretty well until I became unstuck with the last instructions of the top section which are 10 10. Now 10 is Opcode 0 i.e. JMP in Mode 1 which implies jmp r2:r1 instuction but operand 2 is 10 (i.e. 16 in decimal) which is way too big to be a register number. I spent a long time wrangling with this and eventually realised that it had to be a jump and that if it was not a register number it must be an immediate value. I then patched my code to imply that a number outside the register range should be an immediate and hey presto it worked. I blame a poor specification but perhaps this alludes to machine implementations not always following the specs that are intended to define them; hardware has bugs too.
Finally we also note the presence of unexplained baggage...
firmware: [0xd2ab1f05, 0xda13f110]The VM in Java
So we run the machine and we get....public class Part2 {
int[] mem =
{
0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50,
0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8,
0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9,
0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56,
0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9,
0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69,
0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60,
0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8,
0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d,
0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67,
0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a,
0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9,
0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e,
0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55,
0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3,
0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f,
0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d,
0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1,
0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94,
0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62,
0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b,
0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1,
0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61,
0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14,
0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2,
0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1,
0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int eip=0;
int fl=0x00;
final int CS=4; final int DS=5;
int[] regs = new int[] { 0x00, 0x00, 0x00, 0x00,0x00,0x10};
public static void main(String[] args) {
Part2 p2 = new Part2();
p2.run();
}
private void run() {
while (machineRunning)
singleStep();
// Search for GET
for (int i=0; i<mem.length; i++)
{
if ((mem[i]=='G')&&(mem[i+1]=='E')&&(mem[i+2]=='T'))
{
System.out.println("Found GET!");
while (mem[i] != 0)
{
System.out.print((char)mem[i]);
i++;
}
System.out.println();
break;
}
}
}
private void singleStep() {
int currentInstruction = mem[eip];
int followingInstruction = mem[eip+1];
int opcode = currentInstruction >> 5;
int mod = (currentInstruction >> 4) & 0x01;
int op1 = currentInstruction & 0x0f;
int op2 = followingInstruction;
// Funny stuff here... if more than >=6 then assume intermediate
int r1 = (op1<6) ? regs[op1] : op1;
boolean oneByteInstruction =
(((opcode == 0x00) || (opcode == 0x06)) && (mod == 0)) || (opcode == 0x07);
System.out.print(String.format("%04x ", eip));
System.out.print(String.format("%02x", currentInstruction));
if (!oneByteInstruction)
{
System.out.print(String.format("%02x", followingInstruction));
}
else
{
System.out.print(" ");
}
System.out.print(" ");
// Advance
eip += (oneByteInstruction) ? 1 : 2;
switch (opcode) {
// 0x06 | jmpe | r1 | r2:r1
case 0: //jmp
case 6: //jmpe
{
System.out.print((opcode==0)?"jmp ":"jmpe ");
boolean conditionSatisfied = ((opcode == 0x0) ? true : (fl == 0));
// 0x00 | jmp | r1 | r2:r1
// 0x06 | jmpe | r1 | r2:r1
if (mod == 0) {
System.out.print("r"+op1);
} else {
System.out.print("r"+op2+":r"+op1);
}
if (conditionSatisfied) {
if (mod == 1) {
// Seems to be a bug here... we can get a 10 10 which implies r16 but clearly that
// isn't possible... assume numbers over 6 are immediate values
regs[CS] = (op2<6) ? regs[op2] : op2;
}
eip = regs[CS]*16+r1;
}
break;
}
// 0x01 | movr | r1, r2 | rx, imm
// * movr r1, r2 => move contents of register r2 into register r1
case 1: //movr
{
System.out.print("movr ");
if (mod==0)
{
System.out.print("r"+op1+",r"+op2);
regs[op1] = regs[op2];
}
else
{
System.out.print("r"+op1+",0x"+String.format("%02x", op2));
regs[op1] = op2;
}
break;
}
// 0x02 | movm | r1, [ds:r2] | [ds:r1], r2
case 2: //movm
{
System.out.print("movm ");
if (mod == 0) {
System.out.print("r"+op1+", ["+String.format("%02x",regs[DS])+":r"+op2+"="+String.format("%02x",regs[op2])+"]");
regs[op1] = mem[(regs[DS] << 4) + regs[op2]];
} else {
System.out.print("["+String.format("%02x",regs[DS])+":r"+op1+"="+String.format("%02x",regs[op1])+"], r"+op2);
mem[(regs[DS] << 4) + r1] = regs[op2];
}
break;
}
// 0x03 | add | r1, r2 | r1, imm
case 3: //add
{
System.out.print("add ");
if (mod == 0) {
System.out.print("r"+op1+",r"+op2);
regs[op1] = r1 + regs[op2];
} else {
System.out.print("r"+op1+",0x"+String.format("%02x",op2));
regs[op1] = r1 + op2;
}
// Ensure we wrap on overflow...
regs[op1] &= 0xFF;
break;
}
// 0x04 | xor | r1, r2 | r1, imm
case 4: //xor
{
System.out.print("xor ");
if (mod == 0) {
System.out.print("r"+op1+",r"+op2);
regs[op1] = r1 ^ regs[op2];
} else {
System.out.print("r"+op1+",0x"+String.format("%02x",op2));
regs[op1] = r1 ^ op2;
}
// Ensure we stay in 8 bits
regs[op1] &= 0xFF;
break;
}
// 0x05 | cmp | r1, r2 | r1, imm
// cmp r1, r2 instruction results in:
// r1 == r2 => fl = 0
// r1 < r2 => fl = 0xff
// r1 > r2 => fl = 1
case 5: //cmp
{
System.out.print("cmp ");
int arg2;
if (mod == 0) {
System.out.print("r"+op1+",r"+op2);
arg2=regs[op2];
} else {
System.out.print("r"+op1+",0x"+String.format("%02x",op2));
arg2 = op2;
}
fl = ((r1==arg2) ? 0 : ((r1<arg2) ? 0xff : 0x01));
break;
}
case 7: //hlt
{
System.out.print("halt");
machineRunning = false;
break;
}
}
System.out.println();
System.out.print(" eip="+String.format("%04x", eip));
System.out.print(",fl="+String.format("%02x", fl));
System.out.print(",ds="+String.format("%02x", regs[DS]));
System.out.print(",cs="+String.format("%02x", regs[CS]));
System.out.print(",r0="+String.format("%02x", regs[0]));
System.out.print(",r1="+String.format("%02x", regs[1]));
System.out.print(",r2="+String.format("%02x", regs[2]));
System.out.print(",r3="+String.format("%02x", regs[3]));
System.out.println();
}
boolean machineRunning = true;
}
GET /da75370fe15c4148bd4ceec861fbdaa5.exe HTTP/1.0Interestingly along the line we notice that the program indeed started at the top but unencrypted another program section in the middle before subsequently executing that part and decoding the ciphertext. Nice example of self modifying code.
Anyway... time to move on to Step 3

0 Comments:
Post a Comment
<< Home