Bioshock Part One
So it honestly felt like this would never get off the ground. With power outages in my neighbourhood and random work stuff happening it had to be delayed multiple times: but we did it.
“It took less than seven hours but you get the idea”
With no technical dramas hindering the event I got stuck into Bioshock Remastered.
“No gods or kings. ONLY timb3r.”
As is typical with remastered versions of games; they’re often hacked/patched to support newer rendering pipelines and Bioshock was no different. Dumping the imports showed that yes: it was using both DirectX 9 and DirectX 11.
d3d9.dll 114B1AA0 Import Address Table 1177F2E8 Import Name Table 0 time date stamp 0 Index of first forwarder reference 9 Direct3DCreate9 d3d11.dll 114B1A98 Import Address Table 1177F2E0 Import Name Table 0 time date stamp 0 Index of first forwarder reference 4 D3D11CreateDevice
My hunch was that it would be solely using DX11 with DX9 left in the weeds. However I like to be thorough with these things and I proceeded to quickly generate a DX9 proxy DLL using my template. To my surprise this happened:
Our hook got called? Well that’s not entirely outside the realm of possibility. Running the game shows that yes nothing is rendered to the screen. Meaning that my assumption was correct that DX11 is now the game’s main rendering pipeline and DX9 possibly a fallback if DX11 fails to initialise.
“CreateDevice being called.”
So a bit of brief analysis in a debugger to confirm that there was no funny business with DX9. I quickly cobbled together some code using the code from Dauntless as a base.
“Aaaaand this happened.”
Wrong calling convention? What the bloody Christmas? I’ll give a brief explanation of how the hook works to save you reading the other article.
- The game loads.
- Our d3d11.dll proxy loads.
- All calls to DX functions are redirected to the real ones.
- Our DLL locates and detours IDXGISwapChain::Present.
- Our DLL waits for the first call to Present to initialise ImGui.
- Our DLL then draws to the screen and calls the original IDXGISwapChain::Present.
This works on modern games without issue, but for some reason this is crashing. Now I felt the error message was wrong and there was some bug in my code that was corrupting the ESP register. I quickly removed any code that might have caused problems and reloaded the game and I was greeted by the game silently crashing and closing.
I went over my code line-by-line and removed anything that could be potentially causing a problem. I rechecked my pointer maths, confirmed that everything was correct and it still crashed.
Running the game through a debugger showed that yes: my hooked function was corrupting the stack and it was most likely caused by an incorrect calling convention. I confirmed this by analysing the symbols on dxgi.dll and yes: IDXGISwapChain::Present was exposed as a stdcall.
I don’t know enough about the internals of the game or DirectX 11 but one can only assume that either:
- The game is running some type of hacked weirdness.
- Microsoft updated/changed the calling conventions somewhere between 11.0 and 11.3.
Either way I’m not interested enough to investigate.
Updating the calling convention confirmed this:
“The game is happily running now: 0C8C6EF8 is a pointer to IDXGISwapChain.”
Reapplying our drawing code shows that yes: it works bitches!
So with that the first successful Hackvent was held. A special thanks to Icey in the discord for making me feel like I wasn’t talking to myself. Also a very special thanks to all Patreon subscribers who support me so I can keep doing this stuff you guys rock.
The next one will be held tentatively Friday next week (at a more reasonable time ) considering most readers are in the US.