The worlds smallest self aware puzzle game
tutorial – Difficulty: Easiest – Full walkthrough below
magicbyte – Difficulty: Easy
magicwindow – Difficulty: Easy
muchwin – Difficulty: Easy-Medium
yolojmp – Difficulty: Easy-Medium – Game will break and bug out with wrong answers!
diallock – Medium – Game will break and bug out with wrong answers!
How To Play
Run the game by using Qemu
where ‘tutorial’ is the name of the level
When the game starts, you will see a ‘>‘ prompt. You can only enter ‘d‘ or ‘i‘ as the input. All of the levels have this same interface.
–d: This performs a memory (hex) dump of it’s entire self (the program you’re running). Press enter/return when ready for prompt again.
–i: Input mode. When in this mode, two hex characters will be accepted (a full byte). Press enter/return when ready for prompt again. It should be noted that input validation isn’t carefully done, you can enter any two characters. This alone wont make the program crash, you’ll just get unintended data back into the program. Capital letters are recommended for the A-F hex.
What the program does with these 2 bytes is up to you to decide. Try to spot the differences in the dump to try and strategize what happened to your input data. Use this information to attempt to redirect the flow of the program to the ‘win’ screen.
All source files use ‘org 0x7c00’ to set the base ds: code section at a base address of 0x7c00
If you enter the wrong input, the game might fuck up (doesn’t apply to the tutorial though), after all, some of this is self modifying code, and you are the modifier…modify responsibly.
The only ways to cheat (don’t) are if you statically patch the program before playing or change things dynamically with a debugger while debugging (without the intended input method). The binary is intended to be ran as-is as a boot sector program. pretend this was your boot sector or it was on your floppy and you booted from it. With only your keyboard as input to this ‘computer,’ win the game.
Also, the winning screen is very distinct and ‘animated.’ If you only see the text message that you won, but without the background animations, you didn’t really win (this applies to some levels where there are many configurations to get the win message, but not the full win screen).
That said, external resources for research are encouraged.
You can use objdump on the full game for a disassembly (objdump -D -b binary -mi386 -Maddr16,data16 tutorial), where ‘tutorial’ is the name of the level.
You can use the m2elf.pl script (link) to disassemble only a few bytes at a time in interactive mode (perl m2elf –interactive). Do note that this script is intended for x86-32, so some 16 bit code wont be represented correctly. If you really wanted the accurate disassembly, you could use xxd and objdump: Say that you wanted to disassemble ’31c0′. first echo ’31c0′ | xxd -r -p > temp. Then objdump -D -b binary -mi386 -Maddr16,data16 temp.
You can also use the nasm_shell.rb script found on Kali Linux to assemble assembly instructions to see what machine code nasm would turn it into.
You could also attach gdb to qemu running the program. Hopefully the below instructions (run inside gdb) help you get started:
target remote | qemu -S -gdb stdio -m 16 -boot c -hda tutorial
set architecture i8086
display /i ($cs*16)+$pc
This is a walkthrough for the tutorial. If you want to try to play the tutorial without help, don’t read this.
Questions to help guide you:
When you entered data, what data changed in the dump?
What is the memory address of the modified data?
If you do a dissasembly dump (objdump) of the file, can you find that address anywhere in the code?
If no, did you try adding 0x7c00 (offset) to it first?
After adding the offset, now can you find this address anywhere in the code?
When you find it, what is the signifigance of this instruction and the one after it?
What data does this instruction imply it’s looking for?
Press d and look at the dump. Take note of the last data before all the nulls (13 01 00 00 00), then hit enter
Press i and enter two hex characters, for this example, I will use ‘FF’ and hit enter.
Press d again. Note that the last part of the data has now changed to 13 01 00 0F FF. It is possible that your data has been placed there in the program.
If we count how many bytes into the program that this is, we will end up at 0x167 (hex). Knowing that ds: starts at 7c00, the address of this byte would be 0x7d67. So if we were to do a dissassembly (objdump) of this program, the most interesting address to us would be 0x7d67. We actually find some interesting insctructions:
11: 80 3e 67 7d 42 cmp BYTE PTR ds:0x7d67,0x42
16: 0f 84 01 01 je 0x11b
It compares that location to 0x42, and if it is equal, jumps to a location somewhere else in the program.
Knowing this, press i again, type 42, then hit enter