Unity3D/Mono protections, part 4

kao

This part is more about my own failure than about Unity3D or Mono. I enjoy looking at Android game cheats and how they manage to exploit every single bug in Mono engine used by Unity3D. And then I make equally stupid bug in my fixer tool. How embarrassing! 😳

Well, not really. I don't pretend to be perfect. I make mistakes just like everyone else and I have no problem admitting them. And hope that somebody else will learn from my mistakes, too.

So, today we'll look at the Vietnamese app that has a funny way to encrypt DLLs:

First, I'll show how the main module is encrypted in the original app. Then I'll analyze a modded version of the app on which my fixer tool failed miserably. Finally, I'll provide a fixed version for my tool.

WTF is GameMain.dll.bytes?

Normally, all Unity3D assets are located in APK subfolder \assets\bin\Data\Managed\. However, in this case, there is a suspicious file GameMain.dll.bytes located directly in the \assets\ folder.

When opened in hex editor, it's clear that DLL is somehow encrypted:

Quick search for the filename, and you'll find this code in method Main.Start() inside Assembly-CSharp.dll:

// Token: 0x06001DE9 RID: 7657 RVA: 0x000D9C90 File Offset: 0x000D7E90
private void Start()
{
...
   string pathUrl = cDownloadInfo.getPathUrl(false, "GameMain.dll.bytes");
   WWWResourceManager.AddLoadTask("res_dll", pathUrl, new VoidResourceLoaderDelegate(this.OnDLLLoadFinished), true);
   this._pdbLoad = true;
   WWWResourceManager.DoLoadTask();
}

Decryption routine is called from Main.OnDLLLoadFinished:

// Token: 0x06001DF8 RID: 7672 RVA: 0x000DA074 File Offset: 0x000D8274
public void OnDLLLoadFinished(ResourceLoader resLoader)
{
   WWW www = resLoader.www;
   this._dll = www.bytes;
   if (www.url.EndsWith(".bytes"))
   {
      string versNumber = "1.98.99";
      ResourcesVersion.DecodeDll(this._dll, versNumber);
   }
   this._dllLoad = true;
   if (this._pdbLoad)
   {
      this.StartGameMain_DLL();
   }
}

and finally StartGameMain_DLL() will load the decrypted DLL:

// Token: 0x06001E05 RID: 7685 RVA: 0x000DA5A0 File Offset: 0x000D87A0
public void StartGameMain_DLL()
{
...
   byte[] dll = this._dll;
   byte[] pdb = this._pdb;
   Assembly assembly = Assembly.Load(dll);
...
}

Good news is, I implemented the necessary decryption algo in my tool, so you don't have to go through all the classes and spend your time on that. 🙂

Hacked version of GameMain.dll

Now, let's look at the hacked version of the game. This mod is made by yeumod (aka VinhThitLon) of platinmods.com.

Unlike the original game, it contains GameMain.dll in the \assets\bin\Data\Managed\ folder. But my tool crashes on the DLL with a silly exception:

Unity3D invalid .NET file fixer v2.0. (c) kao, 2018. https://www.lifeinhex.com/

 Loading file: F:\1\GameMain.dll
[!] Fixing wrong PE signature.
[!] Fixing incorrect NumberOfRvaAndSizes
[!] Fixing invalid COR20_HEADER values
[!] Fixing invalid MetadataRoot values
[!] Invalid Stream size 0x120CFC38, changing to 0xCFC38
[!] Invalid Stream size 0x1205C594, changing to 0x5C594

Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at FixUnity3D.Program.Main(String[] args)

Well, that not helpful at all! So, I needed to debug my code and see where it went wrong. 🙄

Can you tell me what's wrong with this code?

var metadataStreamHeader = stream.ReadStruct();
var savedPos3 = stream.Position;
var metadataStreamName = stream.ReadPaddedNullTerminatedString(4);
var savedPos4 = stream.Position;

// Moonton uses "$" in stream names instead of "#". Also, offset and size is obfuscated using binary NOT.
if ((metadataStreamName[0] == '$') && ((metadataStreamHeader.Size & 0xFF000000) != 0))
{
...

It looks and works perfectly fine...

...until you encounter an assembly like this:

It uses the "Invalid Number of .NET Streams" trick I described earlier. There are 5 valid streams. The 6th stream has an empty name. And when you try to check 1st character of an empty string, you get an exception. Oops.

Of course, it's an easy fix. Here is the updated version:

Why write about this, anyway?

The truth is, I'm not an experienced Android reverser. I can break an odd CTF challenge here and there but, overall, my Android skills are quite average. So, for me this is a way to learn more about Android, building on something I am really good at (like, reversing Windows & PE files).

My solutions will not be always the best because I'm still learning. But I'm always trying to provide enough information, so that you can learn as well and do it yourself.

Can you add support for protection X?

People have commented quite a lot under these posts with questions like "Can you add support for protection X?" That is not the right question.

The right question is - "How does protection X work?"

I'm not a big fan of ready-made tools. That's why I explain how the protection works and give you the source code of the fixer tool. I want you to be able to update fixer tool yourself and share the knowledge.

Special thanks to Janela for bringing my attention to this protection


24 thoughts on “Unity3D/Mono protections, part 4

  1. hello. you have help me decrypt in APK file Assembly-CSharp.dll in APK original game file: {hidden link}

    version 2.2 does not work with it. thanks you!

    1. Thank you, that is a very interesting protection, I'll check it out in next few days. 🙂

  2. I use the 2.2 version but cant unlocked fully the dll im going to check. This link {hidden link}

    I hope admin Kao will show me screenshot or procedures to unlock it manually. Thank You

  3. Do you have any idea how to unlock or reverse libjiagu.so / libjiagu x86 in apk. ? How they protect the apk and any idea what tool to use ? i send you screen shot. Its like hiding the smali inside apk then left only. com folder inside smali. Please take a look with this one. {hidden link}

    I need to see the smali full inside apk. here is the APK {hidden link}
    {hidden link}

      1. Its seems a lot of information in the site but can i request to have a reversing tool in libjiagu protection in apk ? I cant understand some techniques there. Thank you

        1. No. This blog is about learning and sharing information, not about requesting ready-made tools.

  4. I see your blog and download your tool there. i use this tool to unlocked this dll but failed to do so. Can you see this and analyze . Send me if you unlocked it. Also Can you find the xigncode bypass code here.

    Cheers and Good Day.
    DLL:
    {hidden link}

    APK:
    {hidden link}

    1. My tool works and fixes the PE file. To be able to see the code, you still need to remove .NET Reactor protection.

      If you can't open the fixed PE file in dnSpy/de4dot, read the explanation in my previous post.

      1. Can you send me that dll open to my email ? Also can you check its xigncode where it bypass ?

  5. Hi, there is a mod of BMT that still won't open on dnSpy at all after running fixer tool. No PE thing shown on dnSpy means not a .NET dll i guess.
    {hidden link}

    1. My tool works and fixes the PE file. To be able to see the code, you still need to remove .NET Reactor protection.

      If you can't open the fixed PE file in dnSpy/de4dot, read the explanation in my previous post.

  6. Please check my email admin i send you message . the dll force close your tool . i send you here

  7. Quick question that you dont even have to answer lol.

    But how do you use the FixUnity tool? Been trying to figure out my self, but then again i am not expert or average on this. Just a beginner trying to learn.

    Today i encounter an Assembly-CSharp.dll that obviously is encrypted af since i cant see shit when i open it on dnspy. It just shows a red X meaning i cant even open the headers.

    Again, im just a beginner trying to learn and process all this information and learning how everything works.

  8. This is the full APK
    {hidden link}

    This is dll injection locked by unknown protect
    {hidden link}

    please do check this . thanks. Force close your tool when using to that part

Comments are closed.