vfsfitvnm / frida-il2cpp-bridge

A Frida module to dump, trace or hijack any Il2Cpp application at runtime, without needing the global-metadata.dat file.
https://github.com/vfsfitvnm/frida-il2cpp-bridge/wiki
MIT License
974 stars 199 forks source link

How to get the script hanging on it through GameObject? #275

Closed axhlzy closed 1 year ago

axhlzy commented 1 year ago

Gameobject and transform can be obtained from each other, and the entire resource level of unity is connected by transform, so we can get all gameobjects in the entire scene by getting any gameobject Since the transfrom inheritance relationship is as follows

RectTransform <--- Transform <--- Component <--- Object <--- Object

So we can use Component's member function public void GetComponents(Type type, List results) to get all its hanging scripts, but in the process of actual operation, we found that there are two types of System.Type and System .RuntimeType

Here is question 1: What is the relationship between these two types, and how are they used?

Il2Cpp.Domain.assembly("UnityEngine.CoreModule").image.class('UnityEngine.Component').type.handle
Is the type in the above code the same as System.Type?

Then it will always appear when using frida to call (GetComponents)

[Pixel 3::XXX ]-> showGameObject(0x7af608ba80)
--------- GameObject ---------
gameObj         --->    0x7af608ba80
getName         --->    LeftButtonImage
getLayer        --->    5
getTransform    --->    0x7b6ccf45c0
hierarchy       --->    LeftButtonImage(0x7b6ccf45c0) <--- LeftButton(0x7b6ccf45e0) <--- PatchNoteView(0x7b6ccf47e0) <--- Menu_UI(0x7b1de16c60) <--- Canvas(0x7b6ce604a0)

[Pixel 3::XXX ]-> showTypeParent(0x7b6ccf45c0)
RectTransform(0x7ae00e6480) <--- Transform(0x7b6cd1aa80) <--- Component(0x7ae00e6080) <--- Object(0x7ae00e61c0) <--- Object(0x7af7f50ec0)

[Pixel 3::XXX ]-> var tmp = Memory.alloc(0x100)

[Pixel 3::XXX ] -> showMethodInfo(0x7ae0fee9b0)

[-] UnityEngine.CoreModule @ 0x7ae5766268
   [-]UnityEngine.CoreModule.dll @ 0x7afa9b05f8 | C:613
     [-]GameObject @ 0x7af8273a00 | M:40 | F:0 | N:UnityEngine
       [-]public Component[] GetComponentsInChildren(Type type,Boolean includeInactive) @ MI:0x7ae0fee9b0 & MP: 0x7ae75f69d8 & RP: 0x1ba49d8
         [-]type | type: 0x7ae89e61f0 | @ class:0x7afaa8b200 | System.Type
         [-]includeInactive | type: 0x7ae89e23f0 | @ class: 0x7afaa5b500 | System.Boolean
         [-]_RET_ | type: 0x7ae88416f8 | @ class: 0x7a1e0fb8f0 | UnityEngine.Component[]

[Pixel 3::XXX]-> callFunction(0x1ba49d8,0x7af608ba80,Il2Cpp.Domain.assembly("UnityEngine.CoreModule").image.class('UnityEngine.Component').type.handle,tmp)
Error: access violation accessing 0x0
"0x0"

Here is the second question: Is it because of the frida thread that the function call fails? so i tried this,but isn't work ...

    Il2Cpp.attachedThreads.forEach((thread) => {
        LOGD(`Thread: ${thread.id} ${thread.object.toString()}`)
        callFunction(0x1ba49d8,0x7af608ba80,Il2Cpp.Domain.assembly("UnityEngine.CoreModule").image.class('UnityEngine.Component').type.handle,tmp)
    })

So I don't know how to get all the scripts mounted under the GameObject, I hope you guys can give me some pointers

thank you very much ^_^

vfsfitvnm commented 1 year ago

Il2Cpp.Domain.assembly("UnityEngine.CoreModule").image.class('UnityEngine.Component').type.handle

This is a pointer to the Il2CppType native struct (that is NOT a Il2CppObject System.Type).

If you need the System.Type object, just use object instead of handle.

I can't really answer to the second question, however you code snippet simply iterates the attached threads and do nothing more than logging. callFunction is always called from the frida thread

axhlzy commented 1 year ago

oh I made a mistake here, it should be written like this

    Il2Cpp.attachedThreads.forEach((thread) => {
        thread.schedule(()=>{
            LOGD(`Thread: ${thread.id} ${thread.object.toString()}`)
            callFunction(0x1ba49d8,0x7af608ba80,Il2Cpp.Domain.assembly("UnityEngine.CoreModule").image.class('UnityEngine.Component').type.handle,tmp)
        })
    })

But he still has problems

[Pixel 3::XXX ]->     Il2Cpp.attachedThreads.forEach((thread) => {
        thread.schedule(()=>{
            LOGD(`Thread: ${thread.id} ${thread.object.toString()}`)
            callFunction(0x1ba49d8,0x7b148b2200,0x79f6d07080,1)
        })
    })
Traceback (most recent call last):
  File "C:\ProgramData\Miniconda3\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\ProgramData\Miniconda3\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\ProgramData\Miniconda3\Scripts\frida.exe\__main__.py", line 7, in <module>
  File "C:\ProgramData\Miniconda3\lib\site-packages\frida_tools\repl.py", line 1361, in main
    app.run()
  File "C:\ProgramData\Miniconda3\lib\site-packages\frida_tools\application.py", line 386, in run
    self._reactor.run()
  File "C:\ProgramData\Miniconda3\lib\site-packages\frida_tools\reactor.py", line 44, in run
    self._run_until_return(self)
  File "C:\ProgramData\Miniconda3\lib\site-packages\frida_tools\repl.py", line 435, in _process_input
    if not self._exec_and_print(self._evaluate_expression, expression):
  File "C:\ProgramData\Miniconda3\lib\site-packages\frida_tools\repl.py", line 463, in _exec_and_print
    (t, value) = self._perform_on_reactor_thread(lambda: exec(arg))
  File "C:\ProgramData\Miniconda3\lib\site-packages\frida_tools\application.py", line 756, in _perform_on_reactor_thread
    raise error
  File "C:\ProgramData\Miniconda3\lib\site-packages\frida_tools\application.py", line 740, in work
    result[0] = f()
  File "C:\ProgramData\Miniconda3\lib\site-packages\frida_tools\repl.py", line 463, in <lambda>
    (t, value) = self._perform_on_reactor_thread(lambda: exec(arg))
  File "C:\ProgramData\Miniconda3\lib\site-packages\frida_tools\repl.py", line 648, in _evaluate_expression
    return self._parse_evaluate_result(result)
  File "C:\ProgramData\Miniconda3\lib\site-packages\frida_tools\repl.py", line 661, in _parse_evaluate_result
    raise JavaScriptError(result[1])
  File "C:\ProgramData\Miniconda3\lib\site-packages\frida_tools\repl.py", line 1194, in __init__
    super().__init__(error["message"])
KeyError: 'message'

Then I tested that there is no problem without using frida-il2cpp-brige, it may be related to the root thread

[Pixel 3::XXX]-> callFunction(0x1ba49d8,0x7b148b2200,0x79f6d07080,1)
"0x797450ec80"

// called without frida-il2cpp-bridge ↑

[Pixel 3::XXX]-> showArray(0x797450ec80)

[*] Array length : 5  |  RET => 0x797450ec80

797450eca0  60 36 97 14 7b 00 00 00 e0 4a 97 14 7b 00 00 00  `6..{....J..{...
797450ecb0  c0 1c ab 14 7b 00 00 00 20 82 aa 14 7b 00 00 00  ....{... ...{...
797450ecc0  20 e1 aa 14 7b 00 00 00                           ...{...

[0]   0x797450eca0 ---> 0x7b14973660  |  UnityEngine.RectTransform
[1]   0x797450eca8 ---> 0x7b14974ae0  |  UnityEngine.CanvasRenderer
[2]   0x797450ecb0 ---> 0x7b14ab1cc0  |  UnityEngine.UI.Image
[3]   0x797450ecb8 ---> 0x7b14aa8220  |  UnityEngine.UI.Button
[4]   0x797450ecc0 ---> 0x7b14aae120  |  Naxeex.Top.Global.Sound.ButtonClickSound
public Component[] GetComponentsInChildren(Type type,Boolean includeInactive)
My question can only be regarded as verifying the feasibility, and then the first type here is a runtimetype
axhlzy commented 1 year ago

This kind of a lot of errors will appear in many versions Support for 2018.4.2f1 #8 <- similar to this question

axhlzy commented 1 year ago

Thank you again for your answers

vfsfitvnm commented 1 year ago

Uhm, unfortunately I have difficulties in taking the mental picture of this problem. I don't know what callFunction does, I don't know which function you are trying to invoke, I don't know its signature, I don't know whether the Frida thread is attached to Il2Cpp...

axhlzy commented 1 year ago

callFunction is just the encapsulation of frida's api new NativeFunction (the first parameter is the address of the function to be called, and later it is the normal parameter converted to pointer)

I trying to invoke GetComponentsInChildren signature public Component[] GetComponentsInChildren(Type type,Boolean includeInactive) It should be attached, I used Il2cpp.perform(()=>{dowork(...)})