← Back to list

Age of Errors II: The Conquerors

My first exploration of buffer overflow, and used to punish game cheaters.

EtherDream · 2026-07-11 16:03 · 0 claps · 3.9 min read
#memoir #cybersecurity #pranks #age-of-empires
Open on Medium ↗
Wiki topics: FT · Fine-tuning & Adaptation HIS · History LIT · Literature & Writing 🔒 · Cybersecurity ✍️ · Writing & Creative

Age of Errors II: The Conquerors

My first exploration of buffer overflow, and used to punish game cheaters.

In 2006, half of my high school years had already slipped by. To keep me focused on studying, my family locked the computer in a closet. It didn’t help. If anything, it only made me lose interest in school altogether.

Luckily, I lived in the attic. Every night around midnight, I would quietly take the computer out, assemble it on the floor, and play for a while before putting it away again. That year, most of that stolen time went into Age of Empires II: The Conquerors.

I had loved the game since childhood. Its graphics, campaigns, and balance were all excellent. But the programming behind it was a mess, riddled with bugs. Synchronization errors were common, and any one of them could waste an hour for all eight players in a match. Some people jokingly called it Age of Errors.

Because the attic had no internet connection, I mostly played downloaded scenarios. Sometimes I edited them just to make them more fun. Later, I became interested in random maps as well. Unlike scenarios, random maps were plain text files, editable in Notepad.

One day, I wondered what would happen if I gave an object an absurdly long name. So I replaced one with thousands of As. When the game loaded the map, it crashed — exactly as I expected. But the error message was strange: address 0x41414141 is unreadable. I changed the As to Bs, and the address became 0x42424242.

After a few more tests, I found that the value came directly from four bytes somewhere deep inside my input. That was enough to make me suspect a buffer overflow.

Back when I had first learned C, I had already been told that copying memory carelessly could cause serious security problems. So the basic idea wasn’t unfamiliar — but this was the first time I had run into one myself.

Fortunately, I already had a collection of tools on hand, including OllyDbg, so I tried opening the game in a debugger. But once I was staring at assembly instructions, I was completely lost.

The next day, I bought a book on x86 assembly.

The last time I had wanted to learn assembly was when I was a child dreaming of making NES games, but back then I knew too little for it to go anywhere. This time was different. For the next month, I secretly read the book during the day and practiced at night. To save time, I wrote assembly directly in Visual C++ using inline syntax, skipping the trouble of a full toolchain.

Eventually I returned to the overflow. The critical part seemed to be the first four bytes, since they determined where the CPU would jump next. I spent nearly a week staring at it, trying to figure out what address could do that. I wanted to solve it on my own, but in the end I ran out of both time and patience.

So I gave up and looked for the answer in the e-reading room.

The trick turned out to be simple and brilliant: those four bytes just had to be a fixed address in Windows XP whose value was a JMP ESP instruction, causing execution to jump into the data that followed.

That was the first time I really understood how shellcode worked. Along the way, I also learned how shellcode could load DLLs and call Windows APIs.

By summer break, I could finally go online openly again.

I wrote a shellcode that turned off the monitor and quickly shut down the computer, then embedded it into a prank map. I named the map “Classic Black Forest ”— a popular random map at the time, but with an extra trailing space so it wouldn’t conflict with the original.

The first victim came back a few minutes later and said his power supply must be failing, because his computer had suddenly shut down. I found this hilarious.

What made it even funnier was that custom maps spread automatically when people joined games. Before long, the fake map had propagated on its own, and players in chat groups were all talking about the mysterious shutdowns. Eventually, the original map got renamed “Classic Black Forest (Genuine)” to distinguish it from mine.

Once I had gone that far, I naturally wanted more.

I started looking for easier ways to write shellcode. Instead of hand-writing everything in assembly, I experimented with putting the logic into a C function and extracting the machine code after compilation. I also tried various C macro tricks, including ways to build strings directly on the stack.

The game’s countless bugs had already spawned all sorts of cheat tools. I decided to fight fire with fire. My suspicion was that if map strings were vulnerable, then other string handling probably was too. So I turned to the chat system.

By bypassing the game’s built-in message length limit, I found another overflow in the chat system. This one was even better than the map vulnerability: chat messages were far more flexible, and during a match I could send them directly to specific players. That let me punish anyone I wanted.

I designed a few commands. Sending /die would shut down their machine, /bye would crash the game instantly, and others were useful for testing. I used them especially against the people who hosted lobbies just to sell cheat tools. I even modified their game settings so their lobby title read, “I am an idiot.”

Inside the game, I felt increasingly powerful. Outside it, everything was slipping in the other direction. The long nights did more than ruin my studies. Life kept getting worse. But in that game, I was the true conqueror.


메타데이터
post_id
e561d8f7953d
slug
age-of-errors-ii-the-conquerors-e561d8f7953d
url
https://medium.com/@etherdream/age-of-errors-ii-the-conquerors-e561d8f7953d
canonical_url
https://medium.com/@etherdream/age-of-errors-ii-the-conquerors-e561d8f7953d
author_url
https://medium.com/@etherdream
status
ok
fetched_at
2026-07-13 06:23:13