SamboyCoding / Cpp2IL

Work-in-progress tool to reverse unity's IL2CPP toolchain.
MIT License
1.68k stars 197 forks source link

ARM Support (Nintendo Switch, Android, etc) #6

Closed wowjinxy closed 2 years ago

SamboyCoding commented 4 years ago

I believe the switch uses an ARM processor, not x86, so any support will come after x86 support is to a decent state.

jbro129 commented 4 years ago

What about Android architectures? armeabi-v7a, arm64-v8a, etc. Also, maybe you can incorporate Il2CppDumper into Cpp2IL to add support for Android and Switch games? https://github.com/Perfare/Il2CppDumper

SamboyCoding commented 4 years ago

Cpp2IL is actually based on Il2CppDumper, but I made the decision early on to strip out all the other architectures for simplicity and add them back once finished.

Even if I hadn't, this wouldn't offer any advantage over Il2CppDumper right now other than speed, because the analysis is very processor-specific and I wrote all of that myself.

In terms of android - both android architectures use the same basic ARM instruction set, so once I add support for one platform, the rest should work.

pixeltris commented 4 years ago

In terms of supporting different architectures, wouldn't it make sense to switching over to Capstone? There are .NET bindings for it which are really nice, and it supports all major architectures (including wasm).

SamboyCoding commented 4 years ago

Yes, that would probably be good. I had looked at capstone previously and somehow missed the bindings for .NET. I only saw the legacy C# bindings, so I thought it wouldn't be viable. However - having seen that it exists, I'll check it out. It would certainly make arm support easier (though still not easy)

pixeltris commented 4 years ago

Yea it will always be tricky no matter what, each architecture would need it's own complex handlers. I haven't looked into it much but Ghidra's decompiler really interests me for something like this as from what I can tell it operates on Ghidra's PCode which is essentially a central "intermediate language". It's able to produce great pseudo-C output without having to do anything architecture specific. If it's able to produce such great pseudo-C I'm sure the PCode is just as good for this use case.

The decompiler part of Ghidra has been stripped out and used in other programs like IDA. I'm not sure if someone has done it but I imagine simply Capstone+bits of Ghidra could be a powerful combination. (or just doing all this as a Ghidra plugin in general I guess might make sense...)

https://github.com/cseagle/blc https://github.com/radareorg/r2ghidra

Darkar25 commented 3 years ago

what about collaborating with DevX?as i can see he made something like working IL2CPP to ARM...i think you may share some thoughts to each other...idk if he has github account or not so here is his email... devxdevelopment@gmail.com Screenshot_1484

SamboyCoding commented 3 years ago

Support for Dummy/Stub DLL generation is added for ARMv7 and AARCH64(ARMv8) ELF binaries, so this will work on Linux il2cpp games (in theory, I haven't been able to get my hands on one to test), and manually extracted metadata/elf binaries from APKs. Switch support needs more work - mainly because I don't have any binaries.

Analysis is still a long way off.

jbro129 commented 3 years ago

Support for Dummy/Stub DLL generation is added for ARMv7 and AARCH64(ARMv8) ELF binaries, so this will work on Linux il2cpp games (in theory, I haven't been able to get my hands on one to test), and manually extracted metadata/elf binaries from APKs. Switch support needs more work - mainly because I don't have any binaries.

Analysis is still a long way off.

Can you provide the correct way to use Cpp2IL with an il2cpp android app? image

I made a folder with the apk contents and the tool. image I tried using the --force-metadata-path and --force-binary-path arguments to point to the libil2cpp.so and global-metadata.dat but I received an error as well. image Am I using it wrong?

Edit: I just realized you said that you need some binaries for testing. Inside the zip is an arm64-v8a and an armeabi-v7a sample for Pokemon Go. Both have a libil2cpp.so and a global-metadata.dat. https://drive.google.com/file/d/1nf4ywtIzxi11E9KG5Z_CVW0SN3QTiMzS/view?usp=sharing

SamboyCoding commented 3 years ago

Hi, you also need to provide the --force-unity-version with the other two force options - those force options are the only way to run with APK files at present.

I do eventually intend for you to be able to just provide the APK path via --game-path, but that's not implemented yet

SamboyCoding commented 3 years ago

Also, when it comes to testing binaries, I'm ok for android, it's specifically for Linux x86/x64, and Nintendo Switch games (though I have now been provided one switch game)

jbro129 commented 3 years ago

Hi, you also need to provide the --force-unity-version with the other two force options - those force options are the only way to run with APK files at present.

I do eventually intend for you to be able to just provide the APK path via --game-path, but that's not implemented yet

Thanks for the reply. So I used the --force-unity-version and opened the unity default resources file within il2cpp apks at /assets/bin/Data using Notepad++ and got the Unity version. I got an error anyways, did I do something wrong? image

SamboyCoding commented 3 years ago

Remove the a7 - just 2019.2.0

jbro129 commented 3 years ago

Remove the a7 - just 2019.2.0

Awesome, it worked. DummyDLL files were generated and they look correct when I open them up in DnSpy. I had to run again with the --skip-analysis arg which makes sense since you said that it doesn't support these types of binaries yet. Does the analysis feature try to convert and interpret the code of every function to C# to use in the dummy dls?

SamboyCoding commented 3 years ago

That's correct, yeah.

TerranTian commented 3 years ago

Any Update?

SamboyCoding commented 3 years ago

Nope, and I don't expect to have one for a while - at least until x86 is in a decent state.

SamboyCoding commented 3 years ago

Actually, I do have an update. One: As of 2021.3.7, both 32-bit and 64-bit ARM instruction sets are fully supported for loading (and therefore Dummy DLL generation) in the same way as x86. Two: I'm going to try and do a big code cleanup in order to prepare for analysis on ARM. How much gets done, and whether this will actually show as anything from the outside, is unknown yet, but this should at least pave the way for future work on ARM support.

SamboyCoding commented 3 years ago

Progress tracked in #35

AndnixSH commented 3 years ago

I have a few games that have both DLL and Il2Cpp version. I usually kept DLL one for analysis so i can do more fun stuff on Il2cpp Maybe it can help you improve more with ARM support

SamboyCoding commented 3 years ago

It's ok, I have no shortage of games in ARM. As I said, work is being done, you can see my checklist in #35 - once that is done, I can start working on ARM reasonably quickly, I hope

SamboyCoding commented 3 years ago

Okay, the latest experimental/pre-release build of cpp2il now has ARM64 disassembly (most oculus quest games, a bunch of recent android ones) to a decent level. It's not yet on-par with the x86 stuff, but it supports the basics:

image

and supports outputting IL to the actual DLL, like x86, if you so desire (though this behavior is experimental as with x86!): image

Both screenshots taken from the output of an ARM64 binary from an android game.

Note that 32-bit arm (armv7) is still in an early stage - the analysis will run, but you won't get any actual output other than a dump of the arm machine code for each function.

AndnixSH commented 3 years ago

Amazing progress! ARMv7 games is our priority since it works on both ARMv7 and ARM64 android devices, no reason to work on ARM64 only so I will be waiting for the ARMv7 support hehe

SamboyCoding commented 3 years ago

I'm focusing on arm64 specifically because most quest games are built only for arm64, while a lot of android games are built for both.

AndnixSH commented 3 years ago

I see, I'm kinda oldschool, and i hate ARM64 games because of its issues with modding. I tried one of ARM64 game but i got an error. i'm not sure what i did wrong

Unhandled exception. System.InvalidOperationException: Sequence contains no matching element
   at System.Linq.ThrowHelper.ThrowNoMatchException()
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 , Func`2 )
   at Cpp2IL.Program.GetRuntimeOptionsFromCommandLine(String[] commandLine)
   at Cpp2IL.Program.Main(String[] args)

This game is using Unity 2018 https://apkcombo.com/guild-of-heroes-epic-dark-fantasy-rpg-game-online/com.goplaytoday.guildofheroes/

And can you make it possible to specify APK file instead --game-path? i'm not a fan of decompiling big APK because it's too slow on my HDD

SamboyCoding commented 3 years ago

That's an error in your command line, not in the disassembly. Not sure exactly what.

Edit: you're not specifying the force options properly as described further up this thread, so it's looking for an exe.

Also, don't decompile the apk, just open it using 7zip or similar software and drag out the libil2cpp.so and global-metadata files.

But yes, I'll try to add support for APKs

SamboyCoding commented 3 years ago

Ok, I've just added a feature to allow you to use --game-path to specify a path to an APK (but NOT an apkm or xapk) instead of using force paths for these files. Cpp2IL will extract the binary, metadata, and use the globalgamemanagers file to get the unity version.

AndnixSH commented 3 years ago

I forgot to force unity version. It still asked me for game path, that's why i have to decompile

 ./Cpp2IL-Win --game-path "D:\APK Easy Tool\1-Decompiled APKs\Guild of Heroes_ Epic Dark Fantasy RPG game online_1.118.3_apkcombo.com" --force-binary-path "D:\APK Easy Tool\1-Decompiled APKs\Guild of Heroes_ Epic Dark Fantasy RPG game online_1.118.3_apkcombo.com\lib\armeabi-v7a\libil2cpp.so" --force-metadata-path "D:\APK Easy Tool\1-Decompiled APKs\Guild of Heroes_ Epic Dark Fantasy RPG game online_1.118.3_apkcombo.com\assets\bin\Data\Managed\Metadata\global-metadata.dat" --force-unity-version 2018.4.30f1
===Cpp2IL by Samboy063===
A Tool to Reverse Unity's "il2cpp" Build Process.

[Info] [Program] Running on Win32NT
[Warn] [Program] Using force options, I sure hope you know what you're doing!
Unhandled exception. System.FormatException: Input string was not in a correct format.
   at System.Number.ThrowOverflowOrFormatException(ParsingStatus , TypeCode )
   at System.Number.ParseInt32(ReadOnlySpan`1 , NumberStyles , NumberFormatInfo )
   at System.Int32.Parse(String )
   at System.Linq.Enumerable.SelectArrayIterator`2.ToArray()
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 )
   at Cpp2IL.Program.GetRuntimeOptionsFromCommandLine(String[] commandLine)
   at Cpp2IL.Program.Main(String[] args)

But nvm, specifing an APK works fine and the process has completed but i'm not seeing any source inside DLLs. Maybe i should wait more till it's more implemented

SamboyCoding commented 3 years ago

Unity version shouldn't have the f1 part, but as I said, it should work without the force options as of the latest version. Also if providing force options, yes, game path is marked as a required option, so you can just provide it as --game-path ignored.

At the end of the day, the force options are there for development purposes - that's why they're not listed in the readme.

Also, if you want source inside the dlls, read the readme, it tells you how to enable that.

AndnixSH commented 3 years ago

I tried, i got a few IL codes. Most of them are broken since it's still in experiment i know And also most of methods are extern even they aren't

SamboyCoding commented 3 years ago

The extern thing is a bug I haven't yet been able to fix. Removing the method body as part of cleaning up failed IL generation results in the method being marked as extern.

SamboyCoding commented 2 years ago

Extern bug has been fixed and Nintendo Switch binary suport is implemented (albeit requiring the force options for now).

Closing this issue as the support of Arm64 and Armv7 is now tracked in the README and everything else mentioned here is complete.