The hunting binary turned out to be a little game, in which we had to kill a “boss”. For this we were provided with different skills, which we could use against him. On every attack, he does a counter-attack and we’re able to use a specific shield (ice, fire, wind). If our shield matches his attack, we won’t lose any hitpoints.
Let’s have a look at the disassembled parts of the binary:
Main menu:
Option 2 is for “Use skill”, which lets us attack the boss. It will start a new thread for calculating the player attack against the boss and then calls the “defend”-function (in the main thread), in which the attack from the boss is handled. After that, it will directly loop back into the menu.
We should keep that in mind, since this makes it possible to trigger another option, while the attack thread is still running, if executed fast enough.
First, we tried to just stay alive and kill the boss by just not dying. To be able to do this, we need to know what attack the boss will be doing next, before it is executed. So let’s have a look at the “defend” function:
Defend
So it basically just uses
to calculate the attack, the boss will be using.
Since the random generator was initialized with the current time as seed, we should easily be able to guess the attack every time and use the appropriate shield by initializing our own random generator with the same time (which is just current time at process start).
We’ll have to bear in mind, that in the player attack thread also a rand() is used to calculate the damage the player is doing to the boss. So we’ll need to consume two rand()’s per round to stay in sync with the app rng.
So we’ll start just casting iceball again and again, while defending perfectly against the boss attacks.
First try
Ok, that made us invincible for now, so it wasn’t a problem anymore to kill the boss without losing any health:
But at level 4, the boss hp jumped up just a “little bit”. Since our damage value is calculated in 32bit, it would’ve taken forever to kill the boss this way.
So we need another approach to kill the boss faster. Let’s check how the player damage is calculated:
In the executePlayerAttack function, it will check for the skill we’re currently using and depending on it, our damage will be calculated .
Just a quick peek at some skills and their calculations:
Iceball
Fireball
Icesword
So there are some subtle differences between those skills.
Iceball can do a good amount of damage (0-1000).
Fireball can do a max damage of 100, but it lets the attack thread sleep for 1 second, which iceball doesn’t.
Icesword seems to be calculating alot but in reality it just always returns “-1” as dmg (0xffffffff in 32 bit)
Back to the attacking thread. It tries to “lock” the attack calculation with an if/else checking if a “lock object” is set.
One of the most common examples of how not to implement “thread safety”. Since we’re multi-threading, the attack thread can suspend on every instruction, letting other threads (like the main thread) do something.
The attack thread will then check, if we’re using a skill below or equal “4”, and if so, subtracts its damage value from the boss hp (calling cdqe before, converting the damage value into a signed 64 bit value). If we’re using a skill above 4, it won’t convert the damage value and use the value as it is.
This means, if we’re using icesword, the binary is using the second damage calculation, interpreting the value as 64 bit 0xFFFFFFFF (resulting in 4294967295 damage, which means nothing to the current boss hp). But if we would be able to get it to use the first calculation it would convert the damage of icesword to a qword resulting in a 64 bit 0xFFFFFFFFFFFFFFFF (resulting in -1 damage, which would then be suctracted, and thus gets added onto the boss hp).
Since the boss has 0x7FFFFFFFFFFFFFFF (9223372036854775807) HP , adding 1 to it, would let it “overflow” to 0x8000000000000000 (-9223372036854775808) HP, killing him instantenously.
So what we need to do:
Let the binary think we’re using a skill <= 4, to get into the first “calculation method”
Get over the negative damage check
Change the skill just before the damage gets subtracted from the boss hp by switching to icesword and attack with it
The sleep from “Fireball” and “Icesword” is there to help with this. As soon as we reach level 4 we will change our attack pattern to:
Select “Fireball”
Use skill
Immediately change skill to “Ice sword”
Use skill
If we manage to do this in the correct timing, this should do the following:
Enter the boss attack thread, trying to execute fireball
The fireball calculation will create some minor damage value, then sleep 1 second (giving us time to send another input)
The boss attack thread will then check, if we’re using a skill below or equal to “4” (which fireball is)
While this is happening we’re already switching our skill on the main thread to “Ice sword” and execute another attack
Since the damage from icesword will be calculated 1 second after fireball the chances are high, that we’ll pass the “skill lock” and the “skill” check, and replace the player damage with 0xFFFFFFFF, which gets then converted to “-1” just before subtracting it from the boss hp.
Race conditions aren’t always very predictable, but after two or three tries, the script resulted in a “boss kill”, which rewarded us with another flag: