Challenge 2 - Pixel Poker
Description
I said you wouldn’t win that last one. I lied. The last challenge was basically a captcha. Now the real work begins. Shall we play another game?
Download (password: flare
) - 02_PixelPoker.7z
Contents
- CLI
- CFF Explorer
- Ghidra
- x64dbg
Solution
Intro
In this challenge, we’re given two files:
- PixelPoker.exe
- readme.txt
readme.txt
has the following text:
Welcome to PixelPoker ^_^, the pixel game that’s sweeping the nation!
Your goal is simple: find the correct pixel and click it
Good luck!
Sounds pretty straight forward, let’s see.
Initial Analysis
Running the exe brings up the following window, we have 10 tries to click on the right pixel. The coordinates of the pixel we hover over is shown in the title bar along with the number of tries taken.
Failing to click the right pixel in 10 clicks, gives the following game over message and quits the game.
Finding Bitmaps
Opening the file in CFF Explorer, we find 2 bitmaps, 129.bmp
and 133.bmp
under Resources.
XOR Time
Whenever we come across two images in a CTF that look like noise, we should always try to XOR them together.
First, I extract the images from the exe with the following:
7z x PixelPoker.exe .rsrc/ICON
Next, I use some ImageMagick magic to do the XOR:
convert 129.bmp 133.bmp -fx "(((255*u)&(255*(1-v)))|((255*(1-u))&(255*v)))/255" output
Credits to this answer on Stack Overflow for the ImageMagick one-liner and this answer on Unix Stack Exchange for extracting the images.
Flag
Luckily our hunch was correct and the final image contains the flag. I’m guessing this worked because both images were encrypted with the same key.
Flag: w1nN3r_W!NneR_cHick3n_d1nNer@flare-on.com
Alternate Solution
I feel like I cheated on this challenge, so I decided to revist it and try actually reversing.
Static Analysis
Opening up the binary in Ghidra, we can search for the Game Over string Womp womp... :(, Please play again!
. This string is used once in the following code:
This code looks interesting, so let’s dive into the decompiled code and get an idea of what it’s doing.
The program first checks if we used up all 10 tries and if we did, displays the Game Over message and quits. Otherwise, it increments the counter and then checks to see if uVar8
and uVar6
are equal to some computed values. (I’m guessing that this is where it checks to see if we selected the right pixel).
Dynamic Analysis
Instead of trying to figure out the exact coordinates, I decide to just patch the jumps after each comparison that checks the coordinates.
The two jumps I’m interested in patching are the JNZ
shown below.
We open the binary in x64dbg and flip the jumps at addresses 00401486
and 0040149D
, changing them from JNE
-> JE
. (Quick note, x64dbg shows the JNZ
as JNE
, but as far as we’re concerned, they’re the same.)
Now we can click any pixel and it should give us the flag.