Solves: 24 Easy
I just found a repo of a chip-8 emulator, it may be vulnerable but I didn’t had enough time to report the vulnerability with a working PoC.
You must find a way to get the flag in memory on the remote service !
Remote service at : nc 220.127.116.11 1337
This challenge is based on an emulator called c8emu that is updated with these lines of code:
diff --git a/include/Machine.hpp b/include/Machine.hpp
As you can see above, the prints that can leak informations about the program execution are removed, and an array named
flag (on the heap) is inserted right after the memory mapping of length
0x1000 (on the heap) of the chip8 program. This way the goal would be to be able to leak the content of
flag onto the screen.
To get a quick overview of the chip8 arch, I advice you to read this. Here are the most important informations from the technical reference:
- Chip-8 is a simple, interpreted, programming language which was first used on some do-it-yourself computer systems in the late 1970s and early 1980s. The COSMAC VIP, DREAM 6800, and ETI 660 computers are a few examples. These computers typically were designed to use a television as a display, had between 1 and 4K of RAM, and used a 16-key hexadecimal keypad for input. The interpreter took up only 512 bytes of memory, and programs, which were entered into the computer in hexadecimal, were even smaller.
- Chip-8 has 16 general purpose 8-bit registers, usually referred to as Vx, where x is a hexadecimal digit (0 through F). There is also a 16-bit register called I. This register is generally used to store memory addresses, so only the lowest (rightmost) 12 bits are usually used.
- Here are the instruction we need:
LD I, addr. Set I = nnn. The value of register I is set to nnn.
LD Vx, byte, Set Vx = kk. The interpreter puts the value kk into register Vx.
ADD I, Vx. Set I = I + Vx. The values of I and Vx are added, and the results are stored in I.
DRW Vx, Vy, nibble. Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision. The interpreter reads n bytes from memory, starting at the address stored in I. These bytes are then displayed as sprites on screen at coordinates (Vx, Vy). Sprites are XORed onto the existing screen. If this causes any pixels to be erased, VF is set to 1, otherwise it is set to 0. If the sprite is positioned so part of it is outside the coordinates of the display, it wraps around to the opposite side of the screen. See instruction 8xy3 for more information on XOR, and section 2.4, Display, for more information on the Chip-8 screen and sprites.
n or nibble - A 4-bit value, the lowest 4 bits of the instruction
The bug lies into the implementation around the instruction that use the
I register. Indeed, as you read above, the
I register is 16 bits wide. Thus we could we print onto the screen with the help of the
DRW instruction data stored from
memory[I=0] up to
memory[I=2^16 - 1]. Let’s see how does it handle the
The first and the second argument are the begin and the end of the location where data to print are stored.
(op & 0x000f) represents the amount of bytes we’d like to print. As you can see no checks are performed, this way we able to get a read out of bound from from
memory[I=0] up to
memory[I=2^16 - 1].
Now we now how we could exfiltrate the flag we can write this tiny chip8 program:
code = [
We read the flag from
memory is adjacent to the
memory[0x1000] == begin of the chunk
flag within the heap), and we add
0x10 to read the chunk content which is right after the header (prev_sz and chunk_sz). Once we launch it we get:
python3 exploit.py REMOTE HOST=18.104.22.168 PORT=1337
If we decode chars by hand (each byte is a line for which white is 1 and black zero), we get:
If we repeat this step 4 times (by incrementing the value of V1), we finally managed to get the flag: