Closed commonuserlol closed 1 year ago
There's no straightforward way to do it, unfortunately.
Read https://github.com/vfsfitvnm/frida-il2cpp-bridge/discussions/214 and https://github.com/vfsfitvnm/frida-il2cpp-bridge/issues/283.
This implementation might be helpful: https://github.com/vfsfitvnm/frida-il2cpp-bridge/blob/master/src/il2cpp/structs/thread.ts#L96.
However, I could provide an API to do that without all the hassle...
I found a method that works for me, static void CheckEraRange(System.Int32)
from the System.Globalization.HijriCalendar
class. now my code looks like this
const IntPtr = mscorlib.class("System.IntPtr");
const GUI = ImGui.class("UnityEngine.GUI");
const WindowFunction = GUI.nested("WindowFunction");
const Calendar = mscorlib.class("System.Globalization.HijriCalendar");
Calendar.method("CheckEraRange").implementation = function(id: number) {}
const nullptr = IntPtr.new();
nullptr.method(".ctor").overload("System.Int32").invoke(0);
const callback = WindowFunction.new();
callback.method(".ctor").invoke(Calendar.method("CheckEraRange").object, nullptr); //.ctor(System.Object object, System.IntPtr method);
//some code
GUI.method("Window").invoke(1, size, callback, Il2Cpp.String.from("test window"));
but i still get the error an unexpected native function exception occurred, this is due to parameter types mismatch
, do you know why this might be?
i built (not mine) game using Unity and added the code with built-in ImGui. The interesting thing is that the window does not appear when I create it in Update() method and behaves normally in OnGUI().
Well, I have no experience there so I can't really help you unfortunately
There's no straightforward way to do it, unfortunately.
Read #214 and #283.
This implementation might be helpful: https://github.com/vfsfitvnm/frida-il2cpp-bridge/blob/master/src/il2cpp/structs/thread.ts#L96.
However, I could provide an API to do that without all the hassle...
what do you mean by API here?
Maybe I could provide a class so that you can easily pass a JS callback:
const delegate = Il2Cpp.Delegate.wrap(() => {
console.log("Hello!");
});
// you can now pass 'delegate' to method invocations
it's a good idea, but as far as I know frida doesn't know how to create methods, so you'll have to use "crutches".
const IMGUIModule = Il2Cpp.Domain.assembly("UnityEngine.IMGUIModule.dll").image;
const GUI = IMGUIModule.class("UnityEngine.GUI");
// pretty easy now, isn't it? :P
const delegate = GUI.nested("WindowFunction").delegate((id: number) => console.log("Delegate!", id));
However yes, if you call Il2Cpp.installExceptionListener("all");
, you can see it raises You can only call GUI functions from inside OnGUI
!
then, is there a way to "create" OnGUI method?
Nope, you need to hook OnGUI
from whatever MonoBehaviour
you have
I mean, if we only could replicate what OnGUI does under the hood, then yes...
Nope, you need to hook
OnGUI
from whateverMonoBehaviour
you have
the point is that there is no OnGUI method in the class
I mean, if we only could replicate what OnGUI does under the hood, then yes...
i saw that in UnityEngine.GUI there is a method that checks whether it is running in OnGUI or not. later I will check and try to change its behavior.
I'm sorry, but how to load assemblies now?
upd: frida also throws
TypeError: not a function
on this line
Hey, if you are willing to use master
you should read the commit messages and the source code as well; changes are undocumented until the next release
already figured it out. maybe I'm doing something wrong, but I still get the error an unexpected native function exception occurred, this is due to parameter types mismatch
Il2Cpp.perform(() => {
Il2Cpp.installExceptionListener("all");
const CoreModule = Il2Cpp.domain.assembly("UnityEngine.CoreModule").image;
const ImGUIModule = Il2Cpp.domain.assembly("UnityEngine.IMGUIModule").image;
const AssemblyCSharp = Il2Cpp.domain.assembly("Assembly-CSharp").image;
const EnemyAI = AssemblyCSharp.class("EnemyAIGranny");
const Rect = CoreModule.class("UnityEngine.Rect");
const GUI = ImGUIModule.class("UnityEngine.GUI");
const Utilitty = ImGUIModule.class("UnityEngine.GUIUtility");
Utilitty.method("CheckOnGUI").implementation = function () {
}
const size = Rect.alloc();
const delegate = Il2Cpp.delegate(GUI.nested("WindowFunction"), (id: number) => console.log("Delegate!", id));
size.method(".ctor").overload("System.Single", "System.Single", "System.Single", "System.Single").invoke(100, 100, 100, 100);
EnemyAI.method("FixedUpdate").implementation = function() {
this.method("FixedUpdate").invoke();
GUI.method("Window").invoke(1, size, delegate, Il2Cpp.string("test window"));
}
});
Err, I don't know. Any sample to reproduce (i.e. app name etc whatever to reproduce)?
(I'm closing this issue)
game: granny (you can download the latest version in google play or https://apkpure.com/granny/com.dvloper.granny)
i am using frida server latest version
used esbuild to compile the script: .\node_modules\.bin\esbuild index.ts --bundle --outfile=_.js
(windows)
frida command: frida -Uf com.dvloper.granny -l _.js
my script:
import "frida-il2cpp-bridge";
function GUI() {
Il2Cpp.perform(() => {
Il2Cpp.installExceptionListener("all");
const CoreModule = Il2Cpp.domain.assembly("UnityEngine.CoreModule").image;
const ImGUIModule = Il2Cpp.domain.assembly("UnityEngine.IMGUIModule").image;
const AssemblyCSharp = Il2Cpp.domain.assembly("Assembly-CSharp").image;
const EnemyAI = AssemblyCSharp.class("EnemyAIGranny");
const Rect = CoreModule.class("UnityEngine.Rect");
const GUI = ImGUIModule.class("UnityEngine.GUI");
const Utilitty = ImGUIModule.class("UnityEngine.GUIUtility");
Utilitty.method("CheckOnGUI").implementation = function () {
}
const size = Rect.alloc();
const delegate = Il2Cpp.delegate(GUI.nested("WindowFunction"), (id: number) => console.log("Delegate!", id));
size.method(".ctor").overload("System.Single", "System.Single", "System.Single", "System.Single").invoke(100, 100, 100, 100);
EnemyAI.method("FixedUpdate").implementation = function() {
this.method("FixedUpdate").invoke();
GUI.method("Window").invoke(1, size, delegate, Il2Cpp.string("test window"));
}
});
}
//@ts-ignore
globalThis.GUI = GUI
Sample steps for playback: start game, press play, then Continue and again Continue. after you have GUI elements (joystick, etc.) enter GUI() in frida repl
Thanks, I could reproduce. In the meantime, since you have Windows, would you try this snippet? You could test it against https://github.com/kidagine/Darklings-FightingGame (or whatever Windows game you have installed, if any)
Il2Cpp.perform(() => {
// should be the same!
console.log(Il2Cpp.currentThread?.id, Process.getCurrentThreadId());
});
Thanks :P
it looks like you misunderstood me. the game is on android, but my pc works on windows (which most likely does not affect anything)
I meant if you could test that snippet for me since I do not have Windows - it's not related to this issue (but to #195)! It's just a side thing
Alright, UnityEngine.Rect
is a value type, and you are passing it as a reference type, pass size.unbox()
instead of size
.
Now there's another error System.NullReferenceException: Object reference not set to an instance of an object.
- which is related to the fact you are bypassing CheckOnGUI
I guess...
I meant if you could test that snippet for me since I do not have Windows - it's not related to this issue (but to #195)! It's just a side thing
frida -f C:\Users\User\Downloads\Darklings\Darklings.exe -l _.js
____
/ _ | Frida 16.0.18 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://frida.re/docs/home/
. . . .
. . . . Connected to Local System (id=local)
Spawned `C:\Users\User\Downloads\Darklings\Darklings.exe`. Resuming main thread!
[Local::Darklings.exe ]-> Godot Engine v3.5.2.stable.official.170ba337a - https://godotengine.org
OpenGL ES 3.0 Renderer: Intel(R) HD Graphics 505
Async. shader compilation: OFF
[Local::Darklings.exe ]->
[Local::Darklings.exe ]-> Il2Cpp.perform(() => {console.log(Il2Cpp.currentThread?.id, Process.getCurrentThreadId());})
{}
as I understand it, the game uses godot, does this mean that there is no il2cpp here?
Uh, it looks like they switched to Godot since the last time I checked! Version 0.2.9 is the last one using Unity: https://github.com/kidagine/Darklings-FightingGame/releases/tag/0.2.9
same result
[Local::Darklings.exe ]-> Il2Cpp.perform(() => {console.log(Il2Cpp.currentThread?.id, Process.getCurrentThreadId());})
{}
[Local::Darklings.exe ]-> Process.getCurrentThreadId()
4292
Uhm, weird...
Alright, UnityEngine.Rect is a value type, and you are passing it as a reference type, pass size.unbox() instead of size.
Regarding this one, I cannot automate this step: it's unclear to me if value types are always passed as value types, so I just let the user "guess" it. However, when the exception occurs, I can definitely check for value types passed as reference types, so that a better error message would be raised
this is not relevant to this problem, but frida-il2pp-bridge does not define the class correctly
const AssemblyCSharp = Il2Cpp.domain.assembly("Assembly-CSharp").image;
const EnemyAI = AssemblyCSharp.class("EnemyAIGranny");
const TestFPS = AssemblyCSharp.class("TestFPS");
TestFPS.method("OnGUI").implementation = function() {
this.method("OnGUI").invoke();
GUI.method("Window").invoke(1, size.unbox(), delegate, Il2Cpp.string("test window"));
}
const testFPS = TestFPS.new();
EnemyAI.method("FixedUpdate").implementation = function() {
this.method("FixedUpdate").invoke();
testFPS.method("OnGUI").invoke();
}
but console output is il2cpp: couldn't find method OnGUI in class changeTextureNightmare
Uhm, it works fine on my end.
PS: TestFPS
is a MonoBehaviour
, and you can't create a MonoBehaviour
using the new
operator
hmm, calling the OnGUI method manually is also useless. well, I'll come back to this question when I find a game that uses OnGUI
I want to pass a function
onWindow
from typescript as an argument to a method, how can I do this? code:unity docs for
UnityEngine.GUI.Window
: https://docs.unity3d.com/ScriptReference/GUI.Window.html