This is Part 3 of the series about tricks in PE file format used by Unity3D-based games and cheats.
In Part 1 I analyzed some basic tricks used by Android game modders and ways how to defeat them. In Part 2 I covered more tricks used by modding teams and traced their origins to obscure Chinese Android games.
This part will cover tricks used by game developer Moonton in their games:
-
Mobile Battleground: Frontline (currently removed from Google Play)
All games use modified versions of libmono.so containing few tricks that nobody else uses. Different versions of libraries have slightly different ways of implementing these tricks, most of my analysis is based on Mobile Legends: Bang Bang v1.3.25.3323.
Changed DOS signature
First thing you'll notice is that the normal MZ signature is missing in the Assembly-CSharp.dll and other DLLs.
That is because method mono_image_load_pe_data was changed to check for "ER" instead:
memcpy (&msdos, image->raw_data + offset, sizeof (msdos)); if (!(msdos.msdos_sig [0] == 'E' && msdos.msdos_sig [1] == 'R')) goto invalid_image; ....
Changed .NET metadata stream names, offsets and sizes
Another trivial change is done inside load_metadata_ptrs - all stream names have "#" replaced with "$". So, instead of "#Blob" stream, you have "$Blob", and so on.
To accomplish that, load_metadata_ptrs was changed like this:
for (i = 0; i < streams; i++){ if (strncmp (ptr + 8, "$~", 3) == 0){ .... } else if (strncmp (ptr + 8, "$Strings", 9) == 0){ .... } else if (strncmp (ptr + 8, "$US", 4) == 0){ .... } else if (strncmp (ptr + 8, "$Blob", 6) == 0){ .... } else if (strncmp (ptr + 8, "$GUID", 6) == 0){ ....
Obfuscated .NET metadata stream offsets and sizes
Final change is the most interesting one - Moonton has decided to obfuscate all .NET metadata stream offsets and sizes. They chose to use simple "binary NOT" operation - but it works really well. 🙂
Compare original load_metadata_ptrs in Mono code:
for (i = 0; i < streams; i++){ if (strncmp (ptr + 8, "#~", 3) == 0){ image->heap_tables.data = image->raw_metadata + read32 (ptr); image->heap_tables.size = read32 (ptr + 4); ptr += 8 + 3; } else if (strncmp (ptr + 8, "#Strings", 9) == 0){ ....
and decompiled code from libmono.so
for (i = 0; i < streams; i++){ if (strncmp (ptr + 8, "$~", 3) == 0){ image->heap_tables.data = ~read32 (ptr) + image->raw_metadata; image->heap_tables.size = ~read32 (ptr + 4); ptr += 11; } else if (strncmp (ptr + 8, "$Strings", 9) == 0){ ....
In a different version of libmono.so from Puzzle Ark v1.0.21, both standard and hacked PE files are supported:
if ( msdos.msdos_sig[0] != 0x4D || msdos.msdos_sig[1] != 0x5A ) { for ( i = 0; streams > i; ++i ) { if ( !strncmp(ptr + 8, "$~", 3u) ) { image->heap_tables.data = image->raw_metadata + ~read32 (ptr); image->heap_tables.size = ~read32 (ptr + 4); ptr += 11; } else if ( !strncmp(ptr + 8, "$Strings", 9u) ) .... } } else { for ( i = 0; streams > i; ++i ) { if ( !strncmp(ptr + 8, "#~", 3u) ) { image->heap_tables.data = image->raw_metadata + read32 (ptr); image->heap_tables.size = read32 (ptr + 4); ptr += 11; } else if ( !strncmp(ptr + 8, "#Strings", 9u) ) ....
Update of my tool
All of Moonton's tricks are very easy to revert. For example, fixing DOS header is a matter of 3 extra lines:
var dosHeader = stream.ReadStruct(); // Check for Moonton protection if (dosHeader.e_magic == 0x5245) { Console.WriteLine("[!] Fixing wrong MZ signature (Moonton games)."); stream.WriteStruct (0, IMAGE_DOS_HEADER.IMAGE_DOS_SIGNATURE); } else if (dosHeader.e_magic != IMAGE_DOS_HEADER.IMAGE_DOS_SIGNATURE) { Console.WriteLine("[x] Not a MZ/PE file. Can't help you with that"); return; }
Similarly, a check for .NET metadata stream names can be implemented.
Here you can download updated tool + source code:
Special thanks to Yuuki Kuroyama for bringing my attention to this protection.
A question, what program do you use to decompile libmono.so file?
I'm using IDA 7.0. Free version allows only disassembly of x64; for ARM support and decompilation you need a full version (which can be easily found on Google..)
I send you message in gmail. Please see this. Btw this os the file i need to fix and decrypt the dll .{hidden link}
I already answered to your email, but here it is again for completeness:
Thanks for your hardwork and time for this,. BTW can you send me how you unlocked the second dll i send you before in email since i decrypt it but not yet fully unlocked > its from blackmod. Thanks again
Please see my message in gmail. Thank you.
Please, there is no need to send me reminders every day.
I will answer to your email when I have some free time to do that.
Thanks admin. Hope you got free time . sorry if i bothered you.
Amazing work. author please check my DLL . i cant unlock it. and also i send email to you. {hidden link}
APK full : {hidden link}
This game had xigncode . Please mind to check where they change it. Thank You.
Please Check my email mr Kao .
Comments disabled. Read about the reasons here: https://lifeinhex.com/changes-in-the-blog/