Closed leonitousconforti closed 7 months ago
Ok in ghidra I can see all the il2cpp api exports in the Exports
folder of the symbol tree? How come my frida script isn't able to see them though?
Personally, I have never encountered such scenario, but I haven't been actively using (i.e. for a personal project) this library for more than two years, so my bag is quite empty I'm afraid.
I'm curious too to see how Ghidra can detect the exports; what happens if you use enumerateSymbols
?
I just tried to enumerateSymbols, and frida crashes sometimes :(
my script:
const il2cppModule = Process.findModuleByName("libil2cpp.so")!;
for (const symbol_ of il2cppModule.enumerateSymbols()) {
send(`${symbol_.name} @ ${symbol_.address}`);
}
send("aaaaahhhhhh");
sometimes it works:
Spawned `com.nimblebit.tinytower`. Resuming main thread!
[Remote::com.nimblebit.tinytower ]-> message: {'type': 'send', 'payload': 'aaaaahhhhhh'} data: None
but as you can see it prints no symbols, and sometimes it crashes:
Process crashed: java.lang.Error: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
***
FATAL EXCEPTION: UnityMain
Process: com.nimblebit.tinytower, PID: 6514
java.lang.Error: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Version '2020.3.38f1 (8f5fde82e2dc)', Build type 'Release', Scripting Backend 'il2cpp', CPU 'arm64-v8a'
Build fingerprint: 'Must use __system_property_read_callback() to read'
Revision: '0'
ABI: 'arm64'
Timestamp: 2023-11-20 17:27:53+0000
pid: 6514, tid: 6548, name: gum-js-loop >>> com.nimblebit.tinytower <<<
uid: 10168
signal 4 (SIGILL), code -6 (SI_TKILL from pid -484203228, uid 28905), fault addr --------
x0 000070ee28896460 x1 000000000000000a x2 0000000000000000 x3 0000000000000000
x4 000070ee28896b00 x5 fffffffffffffff9 x6 64616f6c79617022 x7 2264616f6c796170
x8 433fffffffffffff x9 0000000000000012 x10 000070e9e2b69f18 x11 000070e9e323a398
x12 000000000000003d x13 000070e9e32360d8 x14 0000000000000057 x15 0000000000000007
x16 0000000000000001 x17 0000000000000000 x18 0000000000000000 x19 000070ee28896460
x20 0000000000000000 x21 000070ee28896460 x22 0000000000000000 x23 000070e9e284950a
x24 000070ee288e3aa0 x25 fffffffffffffff9 x26 000070ee28896b00 x27 0000000000000007
x28 0000000000000001 x29 000070e9ddd1dc18
sp 000070e9ddd1da80 lr 000070e9e323a430 pc 000070e9e323a524
backtrace:
#00 pc 0000000000c2e524 /data/local/tmp/re.frida.server/frida-agent-arm64.so
#01 pc 0000000000c2e3a4 /data/local/tmp/re.frida.server/frida-agent-arm64.so
#02 pc 0000000000c390d0 /data/local/tmp/re.frida.server/frida-agent-arm64.so
at frida-agent-arm64.0xc2e524(Native Method)
at frida-agent-arm64.0xc2e3a4(Native Method)
at frida-agent-arm64.0xc390d0(Native Method)
***
[Remote::com.nimblebit.tinytower ]->
Thank you for using Frida!
The script failed with exit code 1
The above means nothing to me, sometimes I get different errors if I rerun it, but I am clueless in how to decipher it.
Never mind, I am able to get the script to run successfully now without crashing all the time, seemed to be an issue with my network connection. I can see a bunch of symbols using objdump too:
Just not sure why frida can't see them
Ok a little more information to chew on, here is the objdump command I used (I am using whichever objdump comes by default on macos):
objdump -TC libil2cpp.so | grep "il2cpp_"
where -C
is alias for --demangle
and -T
is alias for --dynamic-syms
If I run objdump without -T
it finds no symbols. I also tried nm
(once again the default one that comes on macos):
nm -D libil2cpp.so | grep il2cpp_
where -D
is alias for --dynamic
and once again, if I run nm without -D
it finds no symbols.
I'm not familiar with dynamic symbol tables, but if I had to guess right now, frida isn't able to see the dynamic symbols for some reason.
Ok, I've gotten something working again. I copy and pasted the output of
nm -D libil2cpp.so | grep il2cpp_
into my frida script, used vscode multi cursor to edit every line at once and transform it into:
il2cpp_get_corlib: () => Il2Cpp.module.base.add(0x64d03c),
so my final frida script looked like:
import "frida-il2cpp-bridge";
declare global {
let IL2CPP_EXPORTS: Record<string, () => NativePointer>;
}
(globalThis as any).IL2CPP_EXPORTS = {
il2cpp_get_corlib: () => Il2Cpp.module.base.add(0x64d03c),
...
};
Il2Cpp.perform(() => {
send("aaaahhhhh");
});
and it works now. I still don't understand why frida can't see those exports though? I might keep investigating and open an issue over there because to me it seems like frida should be able to see them
Nice job! Yes, you could open an issue on Frida's side :smile: Alternatively you could use an ELF reader (or whatever file format reader) and do the mapping at runtime. Closing since there's nothing I can do
Hey there,
I've read similar issues like #300, #363, #400, and #427 about other games missing some of the required il2cpp api exports and how they solved it by disassembling, looking for the required exports, and then using the global IL2CPP_EXPORTS object to set the addresses.
In those other issues, it seemed to me like they weren't missing all the il2cpp exports. However, when I run this Frida script:
It prints no exports.
I've used tools like Il2cppDumper to dump exports and then loaded the generated ghidra script into ghidra but it has no address withIs there any hope in finding all the required IL2cpp exports? because it seems to me like they have all been stripped out. Have you encountered anything like this before?il2cpp
in their names. I am just wondering, when I disassemble the game using ghidra, what exactly am I looking for to find the il2cpp exports?