Reverse engineering a binary code modification of an Unity3D game

This happened a while ago, but found the time to write about this only now(no surprises there).

* * *

So, during a casual conversation it came up that a single player FPS game I used to play on Android also had an official PC version. This made me quite happy, though my joy was crushed soon after: 60 degree field of view is the recipe for instant headaches. disorientation and general discomfort.

But I won’t let that stop me! No way. Although I’m quite a noob, I’ve still had some success reverse engineering various games. The game uses Unity3d web player, so I’ll just unpack that and find some strings referencing fov, and then take a look at the code and modify that pesky 60 to a more manageable number. Not that easy. And yeah, it’s not C, but C#. That’s a whole different kind of beast with it’s execution model.

But hey, there actually seems to be a CheatEngine table on Google with fov mod! Piecing it together I was finally able to modify the fov with it. Great, I just downloaded some stuff and pressed a button. l33t hax.

* * *

So, how does that thing work? Well, I also found out that the game’s code was not obsfucated. Running the game dll through a decompiler produced lovely human readable code. And look! A camera class! And it has that pesky 60 fov hardcoded in to several places! Maybe the CE script searches for it and replaces the entries? Converting 60.0f to hex and doing some manual comparisons verified that to be the likely scenario.

Then some more reading about C# IL code etc. and comparing the bytes in the script with the IL code of the relevant camera methods. Perfect match! Indeed the CE script was searching for the camera code and replacing it with one where the hardcoded fov value was different. This also explains why the script didn’t work if a level was already loaded. The IL code was already JIT compiled to another form.

* * *

This discovery means that I can look for arbitrary code in the game, parse the IL dump with my Python script and then make the relevant changes. Then use that same CE script to replace those parts of the game’s code.

Using this new ability, I also found that pesky code that was responsible for aim assist. A few NOPs and welcome full manual aiming! Though, some time later the game received an update, breaking the aim assist disabling. I’d like to revisit that section of the code some day and see what needs to be done to fix it.

Some thoughts about the new desktop – part II

So, a new desktop and life is wonderful? Sure, maybe for a month. Then the random BSODs started to happen. Then some more BSODs, at worst daily. Long hours of analyzing minidumps, tracking possibly bad drivers, upgrading and disabling them. Reading message boards. Adjusting power settings. Adjusting voltages. Running memtests. Nothing seems to be helping and nothing helpful emerges. I’m beginning to suspect the BSODs have something to do with sleep or hibernate, but nothing conclusive as the BSODs take too long a time to get certainty about the causality. Might just as well try upgrading to Windows 8.1 now that all hope is lost.

Of course setting up a fresh OS install brings daily restarts, so the BSODs seem to be gone for a moment. But then, again, they start happening. Checking drivers once again, nothing. Well, it was as if removing Gigabyte's chipset drivers somewhat reduced the BDOSs, but they were not gone completely. Then, with heavy heart, I disabled the sleep-mode just to test it. No more BSODs.

* * *

Now, according to dump files, it’s been almost four months without a single BSODs. A hardware problem with sleep-mode RAM voltage regulation? Software issue? No idea…

Some thoughts about the new desktop – part I

So I finally did what I had been slowly planning for about two years: I upgraded my desktop computer! It’s been a couple of months now, so I’ve had time to get accustomed to it and test it in everyday use.

* * *

During the years I used my previous setup, there was one particular goal in my mind that was clearer than all the others: silence. This was due to the hideous stock cooler of the previous i7 930. Now I would be wiser and select the best the market has to offer, a Noctua NH-D14 cooling a i7 4790k. Combine that beast with a spacious, sound proofed, Fractal Design Define R4 case and a 550W XTR PSU and the result is almost total silence. The low hum of the fans can be heard, but only faintly, in a silent room, laying still in a bed about 1.5 meters from the case.

The trend of low acoustic emissions continued in the selection of the GPU: Gigabyte GTX 770 OC Windforce 3x. Three fans, but on a typical desktop/movie use-case they spin so silently that they barely add any additional noise.

But amidst all that serenity a new, and loud, problem surfaced when I connected the HDDs: the abysmal noise of the older 7200rpm 1 TB disk. I may have to replace it or move it somewhere else. For now it’s still connected but offline in disk management most of the time to prevent accidental spin-ups.

Other than that I had a sweet upgrade in the system disk. From HDD to a Samsung 840 Evo SSD. The system is now so fast! Especially in all the reboots a new system requires. Not going back to HDDs, that is for sure.

* * *

But let’s not get ahead of ourselves. The components needed to be put together first. No big deal, right? Not quite. First: it takes frighteningly large amount of force to close the CPU-socket.  And secondly: after reapplying the thermal paste for the third time and seeing 50c+ in the bios every time I started to think that maybe the thermal paste was not the real issue here. I nervously installed Windows and all the required drivers and behold: idle temps only few degrees higher than ambient. Lesson learned: don’t trust the bios to provide the correct, real-world CPU idle temps.

* * *

But that was just the beginning, only now the dark clouds of system instability are really starting to gather atop the soothing silence that is my new rig. Stay tuned for part II.

Generating a procedural planet/asteroid field

Lately I've been working with a game project where the player flies along a swarm of planetoids, placing bombs, collecting coins and dodging bad asteroids. As it would be quite dull to have a single hand-crafted map for the game, procedural content generation was required. The ultimate goal in map generation would be to create a path for the player to loosely follow. The path should have occasional obstacles but mostly it just contains lots of coins for extra score. Who wouldn't want to get a score as high as possible?

White is the main path, yellow is the obstacle option four. Read more later on.
So we need a path. And not just any path, a naturally looking path that shouldn't zigzag around too wildly. Rather, it should have small, smooth hops from one node to another. And to make the player stay on the path there should be obstacles. In theory there can be obstacles everywhere, just as long as they are not on the path. But note that complete coverage is not a necessity, as long as there is enough obstacles. There can be some open areas that function as alternative routes for the player. But how to create the path?

Proof-of-concept: energy metering with TI Stellaris Launchpad and Python

One afternoon I was trying to think of some quick and easy thing to do with my Stellaris Launchpad and remembered that for a long time I had been pondering on the possibility of semi-accurately measuring the real-time electricity consumption of a whole house. And finally I can present a raw proof-of-concept on that.

I had the MCU, but lacked a sensor. Thinking that I had an LDR tucked somewhere I searched my stashes but unfortunately all I could find was an old calculator solar cell. Might as well give it a try. Knowing practically no theory on connecting anything to MCUs I just plugged its ground to GND and + to an analog input pin via a 4k7 resistor I had lying around. And behold! After some tinkering with the code, I was able to poll meaningful light values with rather non-existent latency. See a video.

Next step: taping the solar cell to the electricity meter and hanging the Stellaris board from a nearby cloth hook. The readings were then transmitted over wi-fi to my desktop for visualization. I implemented an extremely simple pulse detector with on-off thresholds, but it required constant adjustment due to the sun. But the concept was verified, it is very possible to do real-time energy metering with high accuracy.

Maybe I’ll find time some other afternoon to make/find better (delta-based?) pulse detection algorithm and then offload it to the MCU, leaving it to only emit the actual time stamped pulses and kW/h readings.

Edit: had to try the deltas: works great.

USG documents now public

Having worked on this document for several(maybe even a dozen) hours over the past two years, I feel it’s finally time to let the world see how I have big plans. Big plans that will probably never be fulfilled. Actually I don’t expect to get everything done, but rather see it as something to work towards to.

There is also some videos on my YouTube channel.

* * *

For those unfamiliar with my projects: USG is the newest incarnation of my long-running series of space themed 2D games.

Old versions of The Peli –game project now on video

Had a short discussion about my game project today. Short story shorter, I didn’t have any material to show what is was like years ago.

Now I do. It was surprisingly simple to get most of the versions to run like they used to. The only real challenge was eliminating the dependency for an asset server; at that time one of my interests was streaming patching and bigfiles as in Guild Wars. Of course I had to implement my own version to a ‘real’ game. After some asset hunting and code patching the games successfully loaded local files and I could finally record the videos in question.

Except one. I had some serious issues with font rendering in one of the versions(pygame either segfaults or freezes without error) and in the end had to replace the fonts with placeholder squares; no idea why in broke and no real reason to fix them.

I accidentally a server – Part II

Ok, I admit this part took a while longer to write than I originally planned, but this is here now and that’s what matters, maybe. This post was supposed to be more like a configuration guide, but as so much time has passed this turned out to be just reflection. In the previous part I talked a bit about the Usva’s initial hardware related issues so now it’s turn for software.

* * *

As usva would be primarily a virtualization platform, all it really needs is a flexible firewall, a virtual machine manager and some sensors. Debian and KVM itself installed without a hitch, but getting all the other things to work properly was bit of a chore.

First to be configured was shorewall; it’s rules and bridge groups. The plan was to have three different levels of firewalling. One for local network with no traffic restrictions, one for servers with no direct access to lan and lastly a testing / untrusted network where only a single ip/proto/port-pair was accessible from the VM:s, ideal for VPN-only traffic. All interfaces would share a single NAT’d network connection.

Amazingly the configurations weren’t that hard to implement with a bit of help. But of course there were problems, the bridge groups got cleared on reboot and a file in /etc/networking required some tuning to fix that. Also the nic-driver required some module magic. Oh, and I still haven’t thoroughly understood how to configure shorewall.

* * *

Some while later, when everything was working relatively smoothly I finally got to configuring sensors properly. Initially I had managed to get some readings, but now nothing worked. After a fair bit of googling around and trying to load modules it became clear that a newer kernel was required.

No problem! I’ll just copy this old kernel config and compile with --initrd. Nope! Shorewall required some more exotic switches to work, again! And who would have guessed, almost a whole number bigger kernel version number and I finally got some sweet temperature readings.

* * *

Everything went as expected? Nope.

Usva was supposed to firewall and NAT my entire lan(and server as an IPv6 gateway), but due to either noise or hardware constraints(can’t have both) that is not possible at the moment. That old Cisco 871 must continue it’s 70% of max speed NATting job.

Web server? Still haven’t found the time for configuring, the one in Routa is enough for personal use, www.dea.fi for the rest.

What then? Only a pitiful Minecraft server with technology related mods…

Guild Wars 2 - some thoughts

"[Y]ou have played for 255 hours 48 minutes over the past 25 days."
* * *

Now that the most anticipated game has been released, I must confess that I'm a little dissapointed.

While the overall gameplay is nice and dynamic, it gets a bit repeative even if one tries to vary doing hearths, PvP, dungeons, exploration and general PvE. And as I said earlier, I'm hugely dissapointed in the fact the game lacks any kind of mana(well, almost, initiative doesn't count for this).

On it's defence though Guild Wars 2 has a really dynamic and dodge-heavy combat mechanics to balance that otherwise cooldown-based skill system.

* * *

First I made an Elementalist, as the attunement managing was supposed require smart playing and all stuff glorious, but I found myself just using fire magic for everything due to the DPS it offers. Only occasionally did I use the other attunements. Ele also felt far too squishy in Orr even when dodging like crazy.

Then I made a Guardian. It had the survivability I wanted, and quite suprisingly also had some serious DPS, even more than my ele!

Next - not that the class was bad or anything - after getting bored(only slighlty) to Guardian, Thief was next. As initiative was a resource to be managed I was quite excited. But meh, the class felt like, I don't know, it was lacking something. So, after getting to level 24 I made an Engineer.

Now, at this point I was quite excited about WvW(see paragraph later). The Engineer has a Mortar elite skill and turrets, so it is supposed to be The perfect class for WvW defenses. It indeed offers various kits that can be freely used even during combat and without cooldown, making it a very adaptable class. Seemingly perfect, but the game has begun to take it's toll. Having already 'grinded' almost 200 levels, getting another 80 was starting to fell bit exhaustive.

Currently I have managed to get this new Engineer to level 30 and unlocked that tier two elite mortar skill. Now I feel like I might actually be able to take a small rest and do some casual WvW.

Except that I should be farming while I can, gem prices have skyrocketed during the past few days. Get some gems while they are relatively cheap. Oh well...

* * *

Endgame areas have also been suffering from an unfortunately high bugrate. Some skill challanges and events are frozen or otherwise rendered unplayeable. It is also possible to get stuck inside some objects.

On the other hand World vs World vs World has been full of suprises. During betas and also during the full game I've disliked the long distances and zergs there. It has changed, I got recruited to a smallish WvW guild by a chance and had a blast holding Redlake tower last night. Reinforcing, supply chain and breaking sieges suddenly felt much more enjoyable.

I accidentally a server – Part I

I hereby announce, that my infrastructure took a giant leap forward as I purchased a i3 server(i3 530, 4GB low latency RAM, passive cooling except PSU) on the small hours of some random day not too much in the past. Deals were smooth, the merchant in question was a semi-friend and a computer event was just coming up, so a trusted third party could pick the hardware from there, and then later deliver it to me. Effectively zero postage.

But then the curse kicked in. On the few last kilometers the transport of the 3rd party broke, and caused a delay of several hours. But then it finally arrived.

I found out that the case I had in mind had a bit non-standard method of attaching the motherboard, so I had to forcibly remove some parts from an earlier mobo from that case, and ta-da, almost good as new.

Next part of the curse: chipset does not support on-board video, and no low-end video cards available. Ok, let's just borrow one from routa.

But then things got hardcore; PSU did not have connectors for additional power the GPU requires. So, instead of complete PSU change, let's just power the GPU with another PSU! While it is still in another case, but not connected to anything else. Wirestart, mmm.

Now that the system was up and running, it came time to install an OS. I wanted to finally test out ESXi, and it installed to a USB stick and booted up just nicely. Unfortunately there was a catch; no support for sensors, no support for a Realtek NIC and no support for the mobo's SATA controller. There is some unofficial drivers available, maybe, but at this time I think I'll just install Gentoo Debian. More on that on a later post.