Mass Effect 2 Kasumi crash fix

Introduction

Ever since ME2 was released, some people have been affected by a bug that causes the game to crash at the end of Kasumi's loyalty mission, after the shuttle scene, when pressing the Exit button to return to Normandy. This crash seems to affect modern PCs more than old ones so I decided to investigate.

In this article, I'll explain how I fixed the problem and made a mod that can be easily loaded into the game to fix the crash.

Installation

If you're just here for the fix, here's what you have to do:

  • Download Erik-JS's Binkw32 proxy DLL for Mass Effect 2
  • Open the downloaded archive and copy binkw32.dll and binkw23.dll to the game's Binaries folder, overwriting the existing files
  • Download my Kasumi crash fix
  • In the game's Binaries folder, make a new folder called asi and enter it
  • Open the downloaded archive and copy ME2KasumiCrashFix.asi to the newly created asi folder

At the end of the process, your Binaries and asi folders should look like this: Binaies folder ASI folder

Now you can run the game.

Now that the good stuff is out of the way, let's get into how it works.

Investigating the crash

To investigate the crash, we can't use a regularly purchased version of the game because there's DRM on it and the exe file is encrypted, so I used a cracked exe, which is unencrypted, and triggered the crash.

In the Event Viewer, we can see some the details of the crash, collected by Windows: Event Viewer

Windows tells us that the game crashed due to a null pointer exception, at file offset 1ACBCF.

A quick look with IDA Pro shows us the incriminated code with the crash at .text:005ACBCF: Original buggy code

As C-style pseudocode, this is what's going on:

...
MyStruct *s=someFunction();
badFunction(s);
...
void badFunction(MyStruct *s){
    ...
    if(s->attr1==NULL) return 0;
    ...
    return 1;
}
...

The game calls a function with a pointer to a struct, then proceeds to check if some attributes of the struct are NULL without checking that the pointer to the struct itself isn't NULL, and that's where it crashes.

But what is this struct anyway? Honestly, I have no idea. Looking at the stack trace, it looks like we're inside the engine, possibly in the scripting engine.
Previous "fixes" for this issue suggest using the -nomoviesstartup command line argument to workaround this issue, and that disables Bink video playback so my guess is that it's something releated to video playback, maybe it tries to play a file that doesn't exist? I don't know.

The fix is quite simple: we need to modify the code so that badFunction will do this:

...
if(s==NULL) return 0;
if(s->attr1==NULL) return 0;
...
return 1;

Adding code to an existing binary is not always easy, but in this case we're lucky because there're an empty area in the exe nearby, presumably used for cache alignment.

We're going to overwrite the first part of the function with our new code, put the overwritten code in the previously empty area and use jumps to get the correct execution path.

This is the new code:

test eax, eax ;check s==NULL
jz short loc_5ACC40 ;if it's NULL, go to the code that returns 0
jmp short loc_5ACC44 ;jump to the overwritten code
loc_5ACBD5: ;rest of original code begins
...
loc_5ACC44:
cmp dword ptr [eax+54h], 0 ;check s->attr1==NULL
jz short loc_5ACC40 ;if it's NULL, go to the code that returns 0
jmp short loc_5ACBD5 ;continue with the original code
...

This is what the function looks like now: Fixed code

Running the game we can see that it no longer crashes.

Distributing the fix

While the fix seems to work perfectly, there is the issue of distribution: I can't just distribute my modified exe because it's based on a cracked version and ME2 is not exactly abandonware, I'd run into copyright issues. This is where Erik-JS's binkw32 DLL comes to rescue, since it allows loading of ASI mods.

An ASI file is basically a DLL that is loaded into the game at run time and can provide various functionality, most interestingly, it can alter the program code, and this is exactly what my fix does:

  • When the ASI is loaded, it looks for the original code in the code segment of ME2, in memory
  • If it finds it, it overwrites it with the patched code

Thanks to Erik-JS's excellent code, creating the ASI file was surprisingly easy, I simply reused one of his mods and adapted it to my needs. Visual Studio was the main source of wasted time, to be honest.

Getting the fix working on all versions of the game took some time: the cracked version is the best, as usual, but I had to add a couple of workarounds to get it working on the official DRM-infested releases:

  • Because the exe is encrypted and the DRM decrypts it while the game is running, if we just scan for the pattern immediately when the ASI is loaded, we won't find it. I worked around this issue in the same way that Erik-JS did, by scanning every 300ms for up to 10 times, giving the DRM enough time to decrypt the code segment. This isn't a sophisticated DRM, it decrypts the whole thing
  • Apparently the function is slightly different in the various releases of the game, so instead of scanning for the entire code of the function, I scan for just the first 32 bytes, which seem to be identical in all versions; when the pattern is found, I don't overwrite the entire function, I just patch the few bytes that I need to change

This fix should work on all versions of Mass Effect 2: Steam, Origin, Disc or cracked, although I've only personally tested it on the cracked version, which is the one I usually play because I don't want DRM running on my system.

At the moment, I've only tested the fix on Windows 10, but it should work on Windows 7 as well. Erik-JS says that his loader is designed for Windows 7 and newer so it should not work on Windows XP.

You can download the ASI file from here

Code

You can get the source code from here or from the Github repo. You'll need Visual Studio 2019 with MSVC v140 to build it.

The fix is distributed under the GNU GPL v3 license.

Needless to say, I am not affiliated to EA or Bioware in any way, and this is not an official fix.

Report issues

If you're running into issues with this mod, open an issue on Github or send me an email at info@fdossena.com.

Share this article

Comments