Anyone got far?
Just thought I'd hacked it and found there's now a level 2 (of 3)!
Not sure I'm going to have time as there's an assignment I need to post next week.
I'll post details when it ends if anyone's interested...
Anyone got far?
Just thought I'd hacked it and found there's now a level 2 (of 3)!
Not sure I'm going to have time as there's an assignment I need to post next week.
I'll post details when it ends if anyone's interested...
Now on Stage 3....
you mean can not copy this ?
look inside the picture.
recognize that encryption type in the comments ?File Name : cyber.png
Directory : .
File Size : 61 kB
File Modification Date/Time : 2011:12:05 13:07:54-08:00
File Permissions : rw-rw-rw-
File Type : PNG
MIME Type : image/png
Image Width : 740
Image Height : 260
Bit Depth : 8
Color Type : RGB
Compression : Deflate/Inflate
Filter : Adaptive
Interlace : Noninterlaced
SRGB Rendering : Perceptual
Pixels Per Unit X : 2835
Pixels Per Unit Y : 2835
Pixel Units : Meters
Modify Date : 2011:08:05 14:18:51
Comment : QkJCQjIAAACR2PFtcCA6q2eaC8SR+8dmD/zNzLQC+td3t
Q4qx8O447TDeuZw5P+0SsbEcYR.78jKLw==
Image Size : 740x260
Last edited by kryptkat; 12-05-2011 at 01:08 PM.
Hey, dont ask for help, just keep at it!
steganography meow. and generally it is removing the lsb in bin then replacing that with the data or another file. but that works. knew that about the decryption in the comments. was not asking for help just pointing the cipher text out.
having fun yet ?
Finished stage 3.
There's job, but I thought James Bond would get more than that. I bet filling up his Aston Martin at the pump nearly kills him!
I'll do a post on all three stages after the deadline, if I can get around to it...Vacancy Details
CYBER SECURITY SPECIALIST
....
Salary £25,446 (GC10) £31,152 (GC9)
....
There are quite a few people here that know far more than I will ever care to. Hat's off.
Quzah.
Hope is the first step on the road to disappointment.
hmm, what about running the code with the image itself as input?
I ran the secret code and my microwave turned on. This code is beyond my tiny brain.
Spent a few hours on this... all it did was give me a headache...
Good luck... and congratulations to whoever cracks it!
(Probably some 12 year old autistic kid with a penchant for puzzles... ala "Mercury Rising" )
oh fudge. got low drive error. 1.8 terabytes and brute forcer stopped writing to the file. notepad said it was to large a file. and the recyclebin said it was to large and wanted to know if it should be deleted directly and permanently. done the freq annalist . should have done that first.
Well, its over, here's the answer to the first stage:
A keyword is asked for by the site with very little else as a clue. It doesn't take much to see that this is x86 opcode - run it through ndisasm and you get this:
Code:jmp short 0x6 ;EB04 scasd ;AF ret 0xa3bf ;C2BFA3 sub esp,0x100 ;81EC00010000 xor ecx,ecx ;31C9 mov [esp+ecx],cl ;880C0C inc cl ;FEC1 jnz 0xe ;75F9 xor eax,eax ;31C0 mov edx,0xdeadbeef ;BAEFBEADDE add al,[esp+ecx] ;02040C add al,dl ;00D0 ror edx,0x8 ;C1CA08 mov bl,[esp+ecx] ;8A1C0C mov bh,[esp+eax] ;8A3C04 mov [esp+eax],bl ;881C04 mov [esp+ecx],bh ;883C0C inc cl ;FEC1 jnz 0x1c ;75E8 jmp dword 0x95 ;E95C000000 mov ebx,esp ;89E3 add ebx,0x4 ;81C304000000 pop esp ;5C pop eax ;58 cmp eax,0x41414141 ;3D41414141 jnz 0x8d ;7543 pop eax ;58 cmp eax,0x42424242 ;3D42424242 jnz 0x8d ;753B pop edx ;5A mov ecx,edx ;89D1 mov esi,esp ;89E6 mov edi,ebx ;89DF sub edi,ecx ;29CF rep movsb ;F3A4 mov esi,ebx ;89DE mov ecx,edx ;89D1 mov edi,ebx ;89DF sub edi,ecx ;29CF xor eax,eax ;31C0 xor ebx,ebx ;31DB xor edx,edx ;31D2 inc al ;FEC0 add bl,[esi+eax] ;021C06 mov dl,[esi+eax] ;8A1406 mov dh,[esi+ebx] ;8A341E mov [esi+eax],dh ;883406 mov [esi+ebx],dl ;88141E add dl,dh ;00F2 xor dh,dh ;30F6 mov bl,[esi+edx] ;8A1C16 mov dl,[edi] ;8A17 xor dl,bl ;30DA mov [edi],dl ;8817 inc edi ;47 dec ecx ;49 jnz 0x6b ;75DE xor ebx,ebx ;31DB mov eax,ebx ;89D8 inc al ;FEC0 int 0x80 ;CD80 nop ;90 nop ;90 call dword 0x39 ;E89DFFFFFF inc ecx ;41 inc ecx ;41 inc ecx ;41 inc ecx ;41
All rather promising, but there's a few things to note:
It was strange that the code was presented as an image, not as text, or as a binary. This might just be as a way to annoy you in having to type the information before using it, but I guessed a little stenanography was involved. Opening up the file in a hex editor gives us this:
- The first instruction jumps over the next two. These jumped instructions look pretty suspicious so perhaps they aren't code. If they are data, then this can be recoded as the DWORD 0xa3bfc2af. This isn't relevant now though
- Almost at the end of the code there's a relative 'call', but no matching 'ret' (at least in the reachable code). The following instructions seem like nonsense, so it seems likely that the code uses an old trick to embed data within code. The 'call' puts the address of the following instruction on the stack, then branches the execution. The code does later check that a value popped from the stack (0x41414141) so it seems that everything after the call is in fact data, not code. Later, it also checks this area of memory for the value 0x42424242 but that is nowhere to be seen!
Notice the iTXt section? A quick look at the libpng site shows that this section should hold text, not the garbled junk that's actually there. The text looks hard to recognise, but the two '=' signs at the end is a dead give away for Base64 encoding. Sure enough, a little ipython work and the output was saved to a file. Running it through ndisasm gives a load of junk so its not more code, but the first four bytes are the ascii character 'B' or 42 in hex! That means that this is what's missing from the code - maybe not actual code but embedded data.
Adding this to the code (and fixing the relative offsets) gives us:
Forgive the silly code labels - I wasn't going for production code here! Running the resulting binary through a debugger shows that the code copies the data after 0x42424242 and does a lot of bit fiddling with it. Follow the code and watch the memory it's messing with and you will end up with:Code:[BITS 32] section .text global main main: call code_fragment mov eax, 1 xor ebx, ebx int 0x80 code_fragment: jmp short setup_stack ;EB04 scasd ;AF ret 0xa3bf ;C2BFA3 setup_stack: sub esp,0x100 ;81EC00010000 xor ecx,ecx ;31C9 next_byte: mov [esp+ecx],cl ;880C0C inc cl ;FEC1 jnz next_byte ;75F9 xor eax,eax ;31C0 mov edx,0xdeadbeef ;BAEFBEADDE do_stuff: add al,[esp+ecx] ;02040C add al,dl ;00D0 ror edx,0x8 ;C1CA08 mov bl,[esp+ecx] ;8A1C0C mov bh,[esp+eax] ;8A3C04 mov [esp+eax],bl ;881C04 mov [esp+ecx],bh ;883C0C inc cl ;FEC1 jnz do_stuff ;75E8 jmp nop_start ;E95C000000 back_in: mov ebx,esp ;89E3 add ebx,0x4 ;81C304000000 pop esp ;5C pop eax ;58 cmp eax,0x41414141 ;3D41414141 jnz bail_out ;7543 pop eax ;58 cmp eax,0x42424242 ;3D42424242 jnz bail_out ;753B pop edx ;5A mov ecx,edx ;89D1 mov esi,esp ;89E6 mov edi,ebx ;89DF sub edi,ecx ;29CF rep movsb ;F3A4 mov esi,ebx ;89DE mov ecx,edx ;89D1 mov edi,ebx ;89DF sub edi,ecx ;29CF xor eax,eax ;31C0 xor ebx,ebx ;31DB xor edx,edx ;31D2 go_again: inc al ;FEC0 add bl,[esi+eax] ;021C06 mov dl,[esi+eax] ;8A1406 mov dh,[esi+ebx] ;8A341E mov [esi+eax],dh ;883406 mov [esi+ebx],dl ;88141E add dl,dh ;00F2 xor dh,dh ;30F6 mov bl,[esi+edx] ;8A1C16 mov dl,[edi] ;8A17 xor dl,bl ;30DA mov [edi],dl ;8817 inc edi ;47 dec ecx ;49 jnz go_again ;75DE bail_out: xor ebx,ebx ;31DB mov eax,ebx ;89D8 inc al ;FEC0 int 0x80 ;CD80 nop_start: nop ;90 nop ;90 call back_in ;E89DFFFFFF inc ecx ;41 inc ecx ;41 inc ecx ;41 inc ecx ;41 decoded_code: db 0x42 db 0x42 db 0x42 db 0x42 db 0x32 db 0x00 db 0x00 db 0x00 db 0x91 db 0xd8 db 0xf1 db 0x6d db 0x70 db 0x20 db 0x3a db 0xab db 0x67 db 0x9a db 0x0b db 0xc4 db 0x91 db 0xfb db 0xc7 db 0x66 db 0x0f db 0xfc db 0xcd db 0xcc db 0xb4 db 0x02 db 0xfa db 0xd7 db 0x77 db 0xb4 db 0x54 db 0x38 db 0xab db 0x1f db 0x0e db 0xe3 db 0x8e db 0xd3 db 0x0d db 0xeb db 0x99 db 0xc3 db 0x93 db 0xfe db 0xd1 db 0x2b db 0x1b db 0x11 db 0xc6 db 0x11 db 0xef db 0xc8 db 0xca db 0x2f
Now at this point I was expecting the whole solution of the challenge, so a http GET request was not very rewarding! Nevertheless, the resulting javascript file was now available and it was time to move onto stage 2.
So after the let-down of having to complete another test after the last one, I found myself with the following javascript file:
So we have the details of an instruction set, three segments of memory and some variables that represent registers (oh...and some suspicious looking firmware values!).Code://-------------------------------------------------------------------------------------------------- // // 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'); } //--------------------------------------------------------------------------------------------------
The task here is to write a simple disassembler, be able to store a set of decoded instructions and to then execute them as part of a virtual machine. The tricky part is that the first section of code decodes the next one, so you must disassemble, build the instructions, run, disassemble, build more instructions then run again. After this you find the following in the second segment of memory:
'G' , 'E' , 'T' , ' ' , '/' , 'd' , 'a' , '7' , '5' , '3' , '7' , '0' , 'f' , 'e' , '1' , '5' ,
'c' , '4' , '1' , '4' , '8' , 'b' , 'd' , '4' , 'c' , 'e' , 'e' , 'c' , '8' , '6' , '1' , 'f' ,
'b' , 'd' , 'a' , 'a' , '5' , '.' , 'e' , 'x' , 'e' , ' ' , 'H' , 'T' , 'T' , 'P' , '/' , '1' ,
This is the address for the next stage of the challenge.
Interestingly, the third segment seems unchanged - very suspicious as there's not much spare information in any of these challenges.
My final code for this stage:
Code://-------------------------------------------------------------------------------------------------- // // 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 ], decoded_instructions: {}, decode_mem: function() { var pos = this.decode_pos; var b1 = this.mem[(this.decode_offset * 16) + this.decode_pos]; var b2 = this.mem[(this.decode_offset * 16) + this.decode_pos + 1]; var operand2 = b2; var mod = ((0x10 & b1) >> 4); var operand1 = (0x07 & b1); var instruction = ((0xE0 & b1) >> 5); if(instruction == 0x07){ //hlt this.decoded_instructions[pos] = ["htl"]; return false; } if(mod == 0){ switch(instruction){ case 0x00: //"jmp" this.decode_pos += 1; this.decoded_instructions[pos] = ["jmp", "r" + String(operand1)]; return true; case 0x01: //"movr" this.decode_pos += 2; this.decoded_instructions[pos] = this.swap_out_segment_registers(["movr", "r" + String(operand1), "r" + String(operand2)]); return true; case 0x02: //"movm" this.decode_pos += 2; this.decoded_instructions[pos] = this.swap_out_segment_registers(["movm", "r" + String(operand1), "ds:r" + String(operand2)]); return true; case 0x03: //"add" this.decode_pos += 2; this.decoded_instructions[pos] = this.swap_out_segment_registers(["add", "r" + String(operand1), "r" + String(operand2)]); return true; case 0x04: //"xor" this.decode_pos += 2; this.decoded_instructions[pos] = this.swap_out_segment_registers(["xor", "r" + String(operand1), "r" + String(operand2)]); return true; case 0x05: //"cmp" this.decode_pos += 2; this.decoded_instructions[pos] = this.swap_out_segment_registers(["cmp", "r" + String(operand1), "r" + String(operand2)]); return true; case 0x06: //"jmpe" this.decode_pos += 1; this.decoded_instructions[pos] = ["jmpe", "r" + String(operand1)]; return true; } } else { //mod == 1 switch(instruction){ case 0x00: //"jmp" this.decode_pos += 2; this.decode_offset = operand2 * 16; this.decoded_instructions[pos] = ["jmp", "s" + String(operand2) + ":r" + String(operand1)]; return false; case 0x01: //"movr" this.decode_pos += 2; this.decoded_instructions[pos] = this.swap_out_segment_registers(["movr", "r" + String(operand1), operand2]); return true; case 0x02: //"movm" this.decode_pos += 2; this.decoded_instructions[pos] = this.swap_out_segment_registers(["movm", "ds:r" + String(operand1), "r" + String(operand2)]); return true; case 0x03: //"add" this.decode_pos += 2; this.decoded_instructions[pos] = this.swap_out_segment_registers(["add", "r" + String(operand1), operand2]); return true; case 0x04: //"xor" this.decode_pos += 2; this.decoded_instructions[pos] = this.swap_out_segment_registers(["xor", "r" + String(operand1), operand2]); return true; case 0x05: //"cmp" this.decode_pos += 2; this.decoded_instructions[pos] = this.swap_out_segment_registers(["cmp", "r" + String(operand1), operand2]); return true; case 0x06: //"jmpe" this.decode_pos += 2; this.decode_offset = operand2 * 16; this.decoded_instructions[pos] = ["jmpe", "s" + String(operand2) + ":r" + String(operand1)]; return false; } } }, run_instructions: function(){ document.write("<table border=\"1\">"); var looping = true; while(looping && this.cpu.ip < 256){ if(!(this.cpu.ip in this.decoded_instructions)){ this.cpu.ip++; continue; } var instruction = this.decoded_instructions[this.cpu.ip]; switch(instruction[0]){ case "jmp": if(instruction[1][0] == "s"){ var re = /s(\d*):(r\d)/; var vals = instruction[1].match(re); this.cpu.cs = Number(vals[1]); this.cpu.ip = eval("this.cpu." + vals[2]) - 1; looping = false; } else { this.cpu.ip = eval("this.cpu." + instruction[1]) - 1; } break; case "jmpe": if(this.cpu.fl != 0){ break; } if(instruction[1][0] == "s"){ var re = /s(\d*):(r\d)/; var vals = instruction[1].match(re); this.cpu.cs = Number(vals[1]); this.cpu.ip = eval("this.cpu." + vals[2]) - 1; looping = false; } else { this.cpu.ip = eval("this.cpu." + instruction[1]) - 1; } break; case "movr": if(instruction[2][0] == "r" || instruction[2][0] == "c" || instruction[2][0] == "d"){ eval("this.cpu." + instruction[1] + " = this.cpu." + instruction[2]) } else { eval("this.cpu." + instruction[1] + " = " + instruction[2]); } break; case "movm": var re = /ds:(r\d*)/; if(instruction[1][0] == "d"){ //mod 1 var vals = instruction[1].match(re); var r = eval("this.cpu." + vals[1]); this.mem[r + (this.cpu.ds * 16)] = eval("this.cpu." + instruction[2]); } else { var vals = instruction[2].match(re); var r = eval("this.cpu." + vals[1]); eval("this.cpu." + instruction[1] + " = this.mem[r + " + (this.cpu.ds * 16) + "]"); } break; case "add": if(instruction[2][0] == "r" || instruction[2][0] == "c" || instruction[2][0] == "d"){ eval("this.cpu." + instruction[1] + " += this.cpu." + instruction[2]); } else { eval("this.cpu." + instruction[1] + " += " + instruction[2]); } break; case "xor": if(instruction[2][0] == "r"){ eval("this.cpu." + instruction[1] + " ^= this.cpu." + instruction[2]); } else { eval("this.cpu." + instruction[1] + " ^= " + instruction[2]); } break; case "cmp": if(instruction[2][0] == "r"){ if(eval("this.cpu." + instruction[1]) == eval("this.cpu." + instruction[2])){ this.cpu.fl = 0; } else if(eval("this.cpu." + instruction[1]) > eval("this.cpu." + instruction[2])){ this.cpu.fl = 1; } else{ this.cpu.fl = 0xFF; } } else { if(eval("this.cpu." + instruction[1]) == instruction[2]){ this.cpu.fl = 0; } else if(eval("this.cpu." + instruction[1]) > instruction[2]){ this.cpu.fl = 1; } else{ this.cpu.fl = 0xFF; } } break; case "hlt": looping = false; break; } this.cpu.ip++; document.write("<tr>"); document.write("<td>" + this.get_instruction_text(instruction)); document.write("</td><td>" + this.get_state() + "</td></tr>"); } document.write("</table></p>"); this.decoded_instructions = {} this.decode_offset = this.cpu.cs; this.decode_pos = 0; }, swap_out_segment_registers: function(instruction){ for(var i = 0; i < instruction.length;i++){ if(instruction[i] == "r4"){instruction[i] = "cs";} if(instruction[i] == "r5"){instruction[i] = "ds";} } return instruction; }, print_mem: function(){ document.write("Memory Dump<br />"); for(var i = 0; i < this.mem.length; i++){ if(this.mem[i] < 0x20 || this.mem[i] > 0x7E){ var v = this.mem[i].toString(16); if(v.length == 1){ v = "0x0" + v; } else { v = "0x" + v; } document.write(v + ", "); } else { document.write("'" + String.fromCharCode(this.mem[i]) + "' , "); } if(((i + 1) % 16) == 0){ document.write("<br />"); } if(((i + 1) % 256) == 0){ document.write("<br />"); } } }, get_state: function(){ var state = "ip = " + this.cpu.ip + ", "; state += "cs = " + this.cpu.cs + ", "; state += "ds = " + this.cpu.ds + ", "; state += "r0 = " + this.cpu.r0 + ", "; state += "r1 = " + this.cpu.r1 + ", "; state += "r2 = " + this.cpu.r2 + ", "; state += "r3 = " + this.cpu.r3 + ", "; state += "fl = " + this.cpu.fl + "."; return state; }, get_instruction_text: function(instruction){ var text = instruction[0]; if(instruction.length == 2){ text += " " + instruction[1]; } if(instruction.length == 3){ text += " " + instruction[1] + ", " + String(instruction[2]); } return text; }, print_instructions: function(){ document.write("<p>"); document.write("Decoded instructions:<br />"); document.write("<table border=\"1\">"); for(var i = 0; i < 256 ; i++){ if(!(i in this.decoded_instructions)){ continue; } document.write("<tr>"); var instruction = this.decoded_instructions[i]; document.write("<td>At pos " + i + "</td>"); document.write("<td>" + this.get_instruction_text(instruction)); document.write("</td><td>"); } document.write("</table></p>"); }, decode_pos : 0x00, decode_offset: 0x00, decode: function() { while(this.decode_mem()){ } this.print_instructions() this.run_instructions() this.print_mem() while(this.decode_mem()){ } this.print_instructions() this.run_instructions() this.print_mem() /* this.decode_offset = 22; this.decode_pos = 0; while(this.decode_mem()){ } this.print_instructions() this.print_mem() */ }, instructions: ["jmp", "movr","movm", "add","xor","cmp","jmpe","hlt"], 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.decode(); // VM.exec(); } catch(e) { alert('\nError: ' + e + '\n'); }
Use the following html file and load it in Chrome or Firefox to see it work:
<html>
<head>
<script type="text/javascript" src="stage2.js">
</script>
</head>
<body>
</body>
</html>
I'll try to post stage 3 later...