Hi, I’m the author of ProjectO. To solve the challenge, player must reversing the game server to understand the protocol and mechanism.
A semi-auto game client is sufficient to gain the flag.
MSVC STL
Though the binary is stripped, it’s not difficult to recognize it’s using some STLs in C++. But one should quickly realize that the layout of structures are differ from their equivalent in libc++. The concept is similar, it’s should not be a problem to figure out the correct layout. Here is the source code of MSVC STL. In case you have no idea about the libc++ STL, this is the tutorial made by flagbog.
Protocol Buffers
Both of the code of server logic and the protobuf library were chosen as Release version at compile stage, but the information of protocol buffers wasn’t stripped. It helps to understand the functionality of the binary. The problem is how to send a valid request.
First step is to find out the vtable of protobuf, e.g the balsn::Request::vftable
is the vtable of Request
message in package balsn
. One of the functions in vtable contains the implementation of serialization. By following the function at 0x000140015A30
, we can target the function responsible for serialization stored at vtable+0x48
, which is sub_1400020D0
:
... |
A number in protobuf is represent by Variant Length Integer, the pattern can be observed in function sub_140012B80
, which also being called in sub_1400020D0
.
... |
But it’s time consuming to review each of such functions of every types of message. Actually, after parsing a member of a message, the protobuf set a bit in the structure to indicate the present/absent of a member:
... |
So, by following the usage of each message, we can construct the message now. Though the name of members are unimportant, you can find them in binary. The source code of message:
syntax = "proto2"; |
Besides the protobuf itself, the binary required client to send the length of the incoming protobuf, it looks like:
| (4 bytes) length of message | message | |
The Game
The game is:
- 10 levels of random generated MAZE with 10 enemies and a portal to next level
- Have to kill 70 enemies to claim the flag after level 10
- Enemies won’t move and only slash it’s adjacent blocks every 3 turns
- Player only has 1 HP
- Connection timeout after 12 minutes
That’s it, just write a semi-auto client to reach the goal.
It’s possible! Check out the #writeups channel on Discord.
And this github repo contains the source code of the challenge.