TL;DR
After digging through classes, we find that we need to list all the actors in the game. Using the in-game chat to interact with the code, we extract a list of all actors and teleport to each of their coordinates in search of golden eggs. We also find out another method of tracking down each egg's location so we can pick up the Flag of the Egg Hunter.

The Video

Introduction

In the last article, we discussed how we could use teleporting and hovering to get the Unbearable Revenge flag. We're making progress towards collecting them all! This time, we decided to skip the Overachiever quest, as it involves completing each achievement in the game, and "Egg Hunter" sounds more interesting anyways. So, in this episode of the Pwn Adventure 3: Pwnie Island video series, we'll work towards finding all of the golden eggs in the game and completing the Egg Hunter quest!

The Egg

You might've noticed a shiny, golden egg in previous episodes when we tried flying out of the cave at the beginning of the game.

An unexpected golden egg!

What's up with this? While we were reverse engineering and debugging the libGameLogic.so library, we actually stumbled across the GoldenEgg class, which implies the presence of eggs somewhere in the game. This was effectively confirmed when we realized we'd gone past one of them when trying to fly out of the cave!

So, we know where one egg is. What about all the other ones? Is there a way that we can just get all of the egg locations from the code, so we can quickly collect them all and complete the quest?

So, how can we find the (x, y, z) coordinates for each and every egg?

Let's Get Digging

... not in the game, but into the code! If the game can place an egg in a location, surely the egg has a position, or a set of coordinates (x, y, z).

Checking The Classes

Let's start with the GoldenEgg class. This class is an Item (as can be seen below), which in turn is an IItem...

class GoldenEgg : public Item {	
	public:
    	virtual bool ShowEventOnPickup();
        virtual bool ShowEventOnDuplicatePickup();
        virtual const char * GetName();
        virtual const char * GetDisplayName();
        virtual const char * GetItemTypeName();
        virtual const char * GetDescription();
        virtual const char * GetFlavorText();
        virtual ItemRarity GetItemRarity();
};
The GoldenEgg class, in the code.
GoldenEgg is an Item, which is an IItem... But what's with all the functions?

The functions contained in each class actually didn't really point us in any particular direction. In fact, there is no GoldenEgg object. So, let's look at this the other way: we need to find something that gives us a reference to a golden egg.

To do so, we looked for any piece of code that returns or otherwise handles golden eggs. In our search, we saw that the GameAPI class contains a GetGoldenEggList(); function, which returns a vector of item pickups.

GetGoldenEggList(); in the GameAPI.

The ItemPickup class (which is also an Actor, by the way) holds a reference to IItem objects, which we know is what our GoldenEgg class is. So, we're in a good position. Note also that this ItemPickup class also has a couple of lines allowing the player to use the object, basically interacting with it in-game. This is a good sign!

virtual bool CanUse(IPlayer *);
virtual void PerformUse(IPlayer *);
The ItemPickup class.

If we can get a reference to the GameAPI, then we can just call the GetGoldenEggList() function and, well, get the list of locations of all the eggs. By the way, remember the global GameWorld variable? We found another global variable while exploring around, called, Game, which is in fact a GameAPI object. So let's just call it using GDB and get the locations. Well, it didn't work.

p Game.GetGoldenEggList()
$5 = std::vector of length 0, capacity 0
Not quite the result we either expected, nor wanted.

It seems to be empty. How about p g_eggs? Nope, doesn't work either.

p g_eggs is a vector of length 0 too. Bummer.

Thinking About Our Approach

Let's think about what we've learned so far. We tried to see if the GoldenEgg class returned a position. It doesn't do so, but we learned while reading the class that it is effectively an Item object, which is in turn an IItem object. Finding a reference to the eggs got us to a couple of functions which we thought would give us the answer, but they instead returned empty vectors. We did all of this on the client side, since it's where we're working from to hack the game.

Hacking requires understanding what's going on at both a high level and a more in-depth level. In the case of Pwn Adventure 3, the server and client talk to each other (a lot). It's possible that the golden eggs are not handled client-side, but only server-side, with the egg position information then fed to the client at the appropriate time. This method makes sense! However, we tested it out by going to the cave with the egg located halfway to the opening in the cave ceiling, all the while checking the output of p Game.GetGoldenEggList() and p g_eggs. Once again, they both return empty vectors.

Still with the zero-length vectors.

This is, as the youths would say, "wack", but it makes sense if we think about it. Both the server and the client share the libGameLogic.so shared object. Since they share this, it is totally possible to make the client calculate something or interact with the shared object just like the server would. Effectively, if the server has the list and the client doesn't, maybe we can find a way to make the list available to the client, allowing us to quickly and efficiently track down all the golden eggs.

Getting the Egg Coordinates

If we're standing in front of an egg in-game, surely its position has to be listed somewhere in the code. This one took us a while to figure out, but it's pretty nifty. Remember the ItemPickup class? The code also tells us that the GoldenEgg object is also an actor via the very same ItemPickup class.

GoldenEggs are actors.

The GameWorld object can give us a list of all the actors in the in-game world. Can you see where we're going with this yet? Maybe the eggs are in the actor list given by the GameWorld object. Let's check it!

To do so, we wrote a short function that we could input in the in-game chat (it's like having our own terminal in the game, how cool is that?!). We appended it to the code we wrote in the previous article. The code for the actor list looks like this:

else if(strncmp("actors", msg, 6)==0) {
        // get the address of the global variable GameWorld
        ClientWorld* world = *((ClientWorld**)(dlsym(RTLD_NEXT, "GameWorld")));
        // loop over all actors in the world
        for (ActorRef<IActor> _iactor : world->m_actors) {
            Actor* actor = ((Actor*)(_iactor.m_object));
            Vector3 pos = actor->GetPosition();
            printf("[actor] %s: %.2f %.2f %.2f\n", actor->GetDisplayName(), pos.x, pos.y, pos.z);
        }
    }

What this code does, is if we type "actors" in the in-game chat and hit the return key, we get all the addresses of the GameWorld global variable, which gives us the list of each actor in the game world. Then, the position of each actor is obtained from the game, and output to the terminal where we can read the coordinates in their (x, y, z) format.

Using the in-game chat as console is amazing. Here, we're pulling up the coordinates for all the actors.

If you pair that with the teleporting command we set up in the last article, you're in business!

When I say business, I didn't mean getting burned to death under Magnarok. Oops.

Remember, you can checkout GitHub for the complete code. The code for the golden eggs is available here.

Since we had a list of all the actors but no idea which was which, we needed to cycle through them one after the other. As you saw in the screenshot above, this has led to some untimely deaths in-game... but it doesn't matter. Very quickly, we found our first egg! We also unlock a new achievement, the Chamber of Secrets, and start the Egg Finder quest.

First egg!

We then continue to cycle through the list and work our way through to each egg! We skipped over teleporting to the NPCs, because the eggs are probably not around them. Collecting the eggs is easy at this point, and we're about to be done, until we get to the last egg at Ballmer Peak, and it's nowhere to be found! Time to investigate some more.

Sneaky egg is nowhere to be found. Hmm...

Ballmer Peak

Teleporting to the next actor's position gets us in front of an xkcd about Ballmer Peak. Interesting... We took a look into the disassembled libGameLogic.bndb with Binary Ninja, searched the file for the Egg term and found this line

BallmerPeakEgg::~BallmerPeakEgg()

If we check the CanUse function from the BallmerPeakEgg() function, we find that it checks for a BallmerPeakSecret .

Checking out the BallmerPeakEgg in the disassembler.

This secret is only referenced in other places in the code such as BallmerPeakPoster::damage. So, what's this damage about? Looking at the relationships within BallmerPeakPoster, there seems to be a check having to do with "CowboyCoder" before we can reach the BallmerPeakPoster::damage point. Cowboy Coder is in fact a weapon that we picked up as part of our Cow King article where the Cow King dropped a revolver as loot when we defeated it. That revolver is called the Cowboy Coder!

Okay, let's try something. We used the Cowboy Coder revolver to shoot the poster. After firing our six shots, the poster showed no visible damage.

Who would win: one cowboy coder or one xkcd poster?

We decided to go back to where the actor coordinates were for the last egg, on the balcony of Ballmer Peak, and lo and behold, the final egg! And with it, the Flag of the Egg Hunter! That would've been worth 250 points in the Ghost in the Shell 2015 CTF competition. Not bad at all!

Getting the Flag of the Egg Hunter and checking off another item on our list!

But wait, there's more!

Alternate Method

In retracing our steps to write the procedure for the video, we realized that we'd missed some pretty interesting content. There is in fact another way of finding all the eggs' locations. If we look at all the initialization methods that happen for the game, we realize that they follow a linear structure.

Wait, hold on, it's linear code? Yup, always has been.

For instance, GameAPI::InitObjects() is a function that creates the objects in the game, one after the other, in a linear fashion. As you might imagine, it's huge. We decided to write a bit of Python code to help us parse through and find the information that is relevant to us. We implemented it in Binary Ninja using its API console.

for il in current_function.llil_instructions:
	if il.operation == enums.LowLevelILOperations.LLIL_CALL:
    	try:
        	fname = bv.get_function_at(il.operands[0].value.value).name
            if 'Egg' in fname:
            	print hex(il.address), fname
            except:
            	pass
A bit of Python to find the eggs!

This loop goes over every instruction (line 1), and looks for a call (line 2). It gets the call target (line 4), which is a function bv.get_function_at(il.operands[0].value.value). What we're interested in is its name, so we grab that by appending .name at the end of the function, and assigning it to the fname variable. Finally, if the Egg string is in the function name, the hex address is returned, which gives us the entire list of golden eggs. Bingo!

Python script and output.

We can check this by looking in the disassembler again; for example, the hex address 0x1751d1L gets us to a place where the constructor of the class is called, which calls the  operator new, basically creating a new golden egg object. Rinse and repeat for all the other eggs.

At some other point in the code, a 3-dimensional vector is created with three parameters xmm0, xmm1, and xmm2. These are registers that are used for floating-point operations... but the hardcoded values that are given are of type int32_t, a type which is evidently not a float. What's this all about?! We changed their data type to float, and it gives us the in-game location of the eggs! Pretty nifty indeed.

Swap the int32_ts to floats and bam, coordinates!

So there you have it! Two different methods that you can use to finish the Egg Hunter quest and pick up the Flag of the Egg Hunter. Eggselent work!