DawgCTF 2026 WU

Cheater_Cheater…

Here we have a clean .jar file, i ran it and it’s a pacman game, the flag supposedly appears after achieving the highscore.

Decompile it with JADX, the class SimplePacMan has a method for throwing flag.

Dynamic approach

Set the score to 6942069 and we’re done

Here we can cook it with jdb (java debugger)

Or just read it out

Alternatively, we can continue static analysis. Notice that:

There is a revalidate() method in JTextBasket:

Note that public class JTextBasket extends JComponent, so it passes the score as the component’s name. Then in revalidate() it calls getName() to retrieve that score 6942069 for deriving the flag. Here is a python script that replicates what it does:

from Crypto.Cipher import AES
import base64

val = (6942069 * 10 + 1) ** 4

key = bytes.fromhex(str(val))
iv = bytes.fromhex(str(val)[::-1])
ct = base64.b64decode("6Ach6HiD0JmCc1L+RwxDRzhW3sC1kS6XydgSuWVFpxVXRU8EjfuMxIMoIzMwK/ii")
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = cipher.decrypt(ct)
print(decrypted)

I have a nightmare where I have to learn OOP again.


Checkmate Liver King

“I found this interesting Chess game. It seems to run really slow. I wonder what secrets it holds?”

Let’s check things out.

Without turning on the engine, the game runs normally with no lag. With the engine on, it starts freezing after 2 moves

However, when I play certain openings, it responds really fast. There must be an opening book embedded inside.

That leads me to the easy approach.

The OSINT way

https://www.chess.com/article/view/fried-liver-attack-chess-opening

Play the main line and it pops.

lol

anyway, that’s by luck, i’m studying reverse, so here we go.

Rev approach

Benchmarking work lol. When i play some random moves, it prints out “Reply function triggered” and after a while it prints those remaining logs.

I put the binary in IDA and searched for ENGINE messages. They are all processed in sub_9E0650.

The engine

Inside, there are some loops calculating the pieces position,etc…

Benchmarking with gdb: It takes a while for sub_A51490 to return. So that’s the core.

holy moly

The chess engine operates on two tracks: it either retrieves ‘book moves’ from a database or generates them via complex, computationally expensive algorithms.

My approach was to locate the “slow” part of the engine by benchmarking with gdb. Although the complex part was easier to find, it looked horrible to analyze (wasted a lot of time on ts :mattimkhocloc:).

So I sought the “fast route” with the IDA graph, here is the fastest that i found:

Checker sub_AE0580

I began by stepping through in pwndbg. Derived these

I play a known “fast move” to see what is the address of the book position.

Check the memory map

So the position table is heap-allocated at runtime. I dumped it out and inspect

Scrolling down a bit is the black’s immediate response:

At this point, we can try follow the positions in the heap dump and the flag message would pop.

Flag

nice anti-slop with that big engine

DawgCTF{e4e5f3c6c4f6g5d5d5d5f7f7}