Closed RealIndica closed 2 years ago
Hi, would you attach the relevant classes (the ones you get from Il2Cpp.dump().classes().build()
?
Hi, would you attach the relevant classes (the ones you get from
Il2Cpp.dump().classes().build()
?
Yes i will get them in a bit, been busy through the christmas season haha
// Assembly-CSharp.dll
class BeatStarUI.UICanvas : UnityEngine.MonoBehaviour
{
static System.Int32 SortOrder_BottomLayer = -2000;
static System.Int32 SortOrder_HudLayer = -1000;
static System.Int32 SortOrder_TopLayer = 2000;
static System.Int32 SortOrder_DialogLayer = 2200;
static System.Int32 SortOrder_TransitionLayer = 3000;
SpaceApe.EventBus.EventBus eventBus; // 0x18
UnityEngine.RectTransform layerParent; // 0x20
UnityEngine.RectTransform <BottomLayer>k__BackingField; // 0x28
UnityEngine.RectTransform <HudLayer>k__BackingField; // 0x30
UnityEngine.RectTransform <DialogLayer>k__BackingField; // 0x38
UnityEngine.RectTransform <TopLayer>k__BackingField; // 0x40
UnityEngine.RectTransform <TransitionLayer>k__BackingField; // 0x48
UnityEngine.GameObject safeRegionObj; // 0x50
UnityEngine.Canvas <Canvas>k__BackingField; // 0x58
UnityEngine.UI.CanvasScaler <CanvasScaler>k__BackingField; // 0x60
com.spaceape.unityui.SAUIScreenConfig <CurrentScreenConfig>k__BackingField; // 0x68
System.Collections.Generic.List<BeatStarUI.UIScreen> screens; // 0x70
BeatStarUI.UIDialogs dialogs; // 0x78
System.Collections.Generic.List<UnityEngine.RectTransform> Layers; // 0x80
System.Collections.Generic.List<com.spaceape.unityui.SAUISafeRegionConstrain> SafeRegionConstrains; // 0x88
UnityEngine.ScreenOrientation lastOrientation; // 0x90
UnityEngine.Rect lastSafeArea; // 0x94
System.Int32 framesWaitedAfterChange; // 0xa4
System.Nullable<UnityEngine.Vector2> canvasReferenceResolution; // 0xa8
UnityEngine.RectTransform get_BottomLayer(); // 0x023ee240
System.Void set_BottomLayer(UnityEngine.RectTransform value); // 0x023ee248
UnityEngine.RectTransform get_HudLayer(); // 0x023ee250
System.Void set_HudLayer(UnityEngine.RectTransform value); // 0x023ee258
UnityEngine.RectTransform get_DialogLayer(); // 0x023ee260
System.Void set_DialogLayer(UnityEngine.RectTransform value); // 0x023ee268
UnityEngine.RectTransform get_TopLayer(); // 0x023ee270
System.Void set_TopLayer(UnityEngine.RectTransform value); // 0x023ee278
UnityEngine.RectTransform get_TransitionLayer(); // 0x023ee280
System.Void set_TransitionLayer(UnityEngine.RectTransform value); // 0x023ee288
UnityEngine.Canvas get_Canvas(); // 0x023ee290
System.Void set_Canvas(UnityEngine.Canvas value); // 0x023ee298
UnityEngine.UI.CanvasScaler get_CanvasScaler(); // 0x023ee2a0
System.Void set_CanvasScaler(UnityEngine.UI.CanvasScaler value); // 0x023ee2a8
com.spaceape.unityui.SAUIScreenConfig get_CurrentScreenConfig(); // 0x023ee2b0
System.Void set_CurrentScreenConfig(com.spaceape.unityui.SAUIScreenConfig value); // 0x023ee2b8
System.Boolean get_ShowingDialogs(); // 0x023ee2c0
System.Void Awake(); // 0x023ee338
System.Void Start(); // 0x023ee49c
System.Void RefreshScreenConfig(); // 0x023ee4a0
System.Void CreateLayers(); // 0x023eeac0
UnityEngine.RectTransform CreateLayer(System.String name, System.Int32 sortOrder, System.Boolean constrainedInSafeRegion); // 0x023eebac
System.Void HandleOnScreenTransitionBegin(BeatStarUI.UIScreen screen); // 0x023eedb0
System.Void HandleOnScreenTransitionEnd(BeatStarUI.UIScreen screen); // 0x023eee88
System.Void AddScreen(BeatStarUI.UIScreen screen, System.Action onTransitionComplete); // 0x023eef60
System.Void AddDialog(BeatStarUI.UIDialog screen); // 0x023ef0c8 THIS ONE HERE
System.Void OnDialogEntered(BeatStarUI.UIDialog dialog); // 0x023ef258
System.Void ClearAllDialogEntries(); // 0x023ef350
System.Collections.IEnumerator CloseAllDialogs(); // 0x023ef3c0
System.Void HandleOnScreenDestroy(BeatStarUI.UIScreen screen); // 0x023ef448
System.Boolean IsScreenShowing();
System.Collections.IEnumerator CloseAllHudAndDialog(); // 0x023ef4b0
System.Void SetScreenConfig(com.spaceape.unityui.SAUIScreenConfig screenConfig); // 0x023ee8a4
System.Void ToggleSafeRegionDisplay(); // 0x023ef554
System.Boolean HasUIConfigChanged(); // 0x023ef69c
System.Void Update(); // 0x023ef734
com.spaceape.unityui.SAUIScreenConfig GetUIConfig(UnityEngine.Canvas canvas); // 0x023ee540
System.Void .ctor(); // 0x023ef780
}
This should be the only thing I need to attach, as the base class does not contain an AddDialog method either (which i shouldn't anyway, but it was something i checked anyway).
The paramater when I call the method is the right type too, error still shows when I pass the original parameter.
@RealIndica
Ok, I figured it out.
This happens because the actual instance in not a BeatStarUI.UICanvas
, but a GameCanvas
- this one inherits from BeatStarUI.UICanvas
.
The problem here is you are allocating a new Il2Cpp.Object
:
var Instance = new Il2Cpp.Object(this.handle); // btw use const
then, you are calling AddDialog
on it, but GameCanvas
doesn't have such method (its superclass has).
The following snippet works instead. Why?
Il2Cpp.perform(() => {
const AssemblyCSharp = Il2Cpp.Domain.assemblies["Assembly-CSharp"].image;
const UICanvas = AssemblyCSharp.classes["BeatStarUI.UICanvas"];
UICanvas.methods.AddDialog.implementation = function(screen: Il2Cpp.Object) {
return this.methods.AddDialog.invoke<void>(screen);
}
});
Because I artificially cast the instance to the "correct" class: this
is already "casted" to a BeatStarUI.UICanvas
.
Yes, unfortunately I still didn't implement a nice way to call superclass methods, that's something I'll do at one point
I personally didn't realise that "this" returns the current instance of the class in the implementation. Thank you! But yes, it would be nice to have a nicer way to call superclass methods.
Sorry for re-opening the issue, but following what you told me it still won't work...? There's no errors which is good, but somehow the method is still being called fully by the target game. How can this be?
All I did, is basically copy your snippet for testing, and then commented out the return so the method does nothing. However, all UI dialogs appear normally.
Is this something to do with the game, or something to do with it being a superclass method?
Starting to feel that I might just be at a dead end. All I'm trying to do is create an instance of a UIDialog and show it on the screen. Probably something really stupid I'm missing.
@RealIndica well, this is not a frida-il2cpp-bridge
issue, as everything works as expected; but I can tell you more saying I don't think there's an issue at all (and if there was, it should be a frida
one).
My shot is you are looking at the wrong function. More over, I think displaying a custom dialog is not an easy task and involves more stuff than just a function call
@vfsfitvnm you are most likely right. I'm very used to modding unity games with C# mono and using unhollower for il2cpp games on PC.
You know, a wrapper for the full Unity API in frida would be awesome; it's time consuming to hook each and every function in the Unity DLLs to make new game objects, add components etc.
Something I could do, but typescript is fairly new to me and the only reason I'm okay with it is because I'm good with C languages.
@RealIndica Yeah, a Unity API would be good but it's not something I will do (myself) as it is very boring to implement (track changes across versions, test on every platform...); I also think it should be a separate library / package.
You don't need to hook every function to create new objects, but to modify existing ones.
However, what are you trying to achieve?
If you'd like to display custom ui for a mod menu, I'd suggest you to take advantage of frida's rpc methods (send
, recv
) or whatever the host platform offers.
I once did that on android, but using BroadcastReceiver
to send/receive commands.
PS: I think we can close this one, please open a post on Discussions tab.
I am trying to create an instance of a UIDialog (there's one in the game named "CheatCurrenciesScreen") and simply show it. Just trying to get some more of that in-game currency, as you can't play without it (which is stupid).
In C#, I would do something along the lines of:
var uiCanvas = null; //find ui canvas here, forgot name for it lol
uiCanvas.AddComponent<CheatCurrenciesScreen>();
uiCanvas.GetComponent<CheatCurrenciesScreen>().Show();
Im sure the above code would work in C#, however frida is a different story. Don't even know how to pass a type parameter in frida :(
But yeah, after the next response Ill close this issue.
There's
UnityEngine.Component AddComponent(System.Type componentType); // 0x01c7d9ec
You can easily get the underlying System.Type
via CheatCurrenciesScreenClass.type.object
.
Also, if you had something like this:
UnityEngine.Component AddComponent<T>();
you could follow https://github.com/vfsfitvnm/frida-il2cpp-bridge/wiki/Snippets#generics-handling.
I have method A :
And attempting to hook it does work, but the result of the hook does not change the outcome. The implementation below will still be called, but it will not change what the function does and will always return the original result from the hooked function.
Attempting to change the methods outcome I use this code:
That will then throw an error like so:
Any idea how I can go about this?
Thank you and merry christmas! (If you're into the xmas stuff. If not... Happy holidays!)