Closed lshain closed 2 years ago
What's the output of Test1.fridaSignature
?
Test1: System.Void Test1(System.String aa); // 0x00277aa8 Test1.fridaSignature: pointer,pointer this: AAAA value: "AAAA" il2cpp: couldn't find method Test1 in String, did you mean Trim?
package.json: "devDependencies": { "@types/frida-gum": "^17.1.0", "@types/node": "^16.4.8", "frida-compile": "^10.0.0", "frida-il2cpp-bridge": "^0.7.11" }
Would you give more context? E.g. is the application yours? If not, what's the name?
This looks awkward... this
is set here, args[0]
can't be a TestA
instance...
Just a Unity test app, Unity Version is 2021.3.0f1, Contains only the following c# code, Build with IL2CPP:
public class TestA : MonoBehaviour
{
private void Awake()
{
Test1("AAAA");
}
void Test1(string aa)
{
Debug.LogError("Application.version: " + Application.version);
Debug.LogError("Application.unityVersion: " + Application.unityVersion);
Debug.LogError("Application.persistentDataPath: " + Application.persistentDataPath);
Debug.LogError("Application.dataPath: " + Application.dataPath);
Debug.LogError(aa);
}
}
ts Code:
"use strict";
import "frida-il2cpp-bridge";
Il2Cpp.perform(() => {
log('Il2Cpp.perform.... ');
const assemblyCSharp = Il2Cpp.Domain.assembly("Assembly-CSharp").image;
/*
public class TestA : MonoBehaviour
{
private void Awake()
{
Test1("AAAA");
}
void Test1(string aa)
{
Debug.LogError("Application.version: " + Application.version);
Debug.LogError("Application.unityVersion: " + Application.unityVersion);
Debug.LogError("Application.persistentDataPath: " + Application.persistentDataPath);
Debug.LogError("Application.dataPath: " + Application.dataPath);
Debug.LogError(aa);
}
}
*/
const TestA = assemblyCSharp.class("TestA");
const Test1 = TestA.method("Test1");
log('Test1: ' + Test1); // -> Test1: System.Void Test1(System.String aa);
log('Test1.fridaSignature: ' + Test1.fridaSignature);
// System.Void Test1(System.String aa);
Test1.implementation = function (value: Il2Cpp.String): void {
console.log('this: ' + this); // -> this: AAAA
console.log('value: ' + value); // // value: "AAAA"
//value.content = "--!--";
// <--- onEnter
this.method("Test1").invoke(value); // -> il2cpp: couldn't find method Test1 in String, did you mean Trim?
// <--- onLeave
};
});
At the moment, I can't test custom C# code unfortunately.
However, I cannot reproduce in 2021.2.7f1
... honestly I don't have a clue.
Would you be able to dig a little?
E.g: what does this print?
const replacement = new NativeCallback((instance, string) => {
console.log("this:", new Il2Cpp.Object(instance));
console.log("string:", new Il2Cpp.String(string));
}, "void", ["pointer", "pointer"]);
Interceptor.replace(Test1.virtualAddress, replacement);
Il2Cpp.perform(() => { const assemblyCSharp = Il2Cpp.Domain.assembly("Assembly-CSharp").image;
/*
public class TestA : MonoBehaviour
{
private void Awake()
{
Test1("AAAA");
}
void Test1(string aa)
{
Debug.LogError("Application.version: " + Application.version);
Debug.LogError("Application.unityVersion: " + Application.unityVersion);
Debug.LogError("Application.persistentDataPath: " + Application.persistentDataPath);
Debug.LogError("Application.dataPath: " + Application.dataPath);
Debug.LogError(aa);
}
}
*/
const TestA = assemblyCSharp.class("TestA");
const Test1 = TestA.method("Test1");
log('Test1: ' + Test1); // -> Test1: System.Void Test1(System.String aa); // 0x00277aa8
log('Test1.fridaSignature: ' + Test1.fridaSignature); // -: Test1.fridaSignature: pointer,pointer
const replacement = new NativeCallback((instance, string) => {
console.log("this:", new Il2Cpp.Object(instance)); // -> this: AAAA
console.log("string:", new Il2Cpp.String(string)); // -> string: "AAAA"
}, "void", ["pointer", "pointer"]);
Interceptor.replace(Test1.virtualAddress, replacement);
});
64-bit apk + 64-bit arm frida_server unity version: 2020.3.29f1
Il2Cpp.perform.... Test1: System.Void Test1(System.String aa); // 0x004ddc80 Test1.fridaSignature: pointer,pointer this: AAAA string: "AAAA"
64-bit apk + 64-bit arm frida_server unity version: 2021.2.7f1 Il2Cpp.perform.... Test1: System.Void Test1(System.String aa); // 0x0025fe84 Test1.fridaSignature: pointer,pointer this: AAAA string: "AAAA"
32-bit apk + 64-bit arm frida_server
Il2Cpp.perform....
Test1: System.Void Test1(System.String aa); // 0x001c5a1c
Test1.fridaSignature: pointer,pointer
Error: access violation accessing 0x4
at
package.json: "devDependencies": { "@types/frida-gum": "^18.0.0", "@types/node": "^17.0.31", "frida-compile": "^10.2.5", "frida-il2cpp-bridge": "^0.7.13" }
tsconfig.json: "compilerOptions": { "target": "es2020", "module": "commonjs", "allowJs": true, "noEmit": true, "strict": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "skipLibCheck": true }
last apk(delete the zip suffix): testA.apk.zip
64-bit apk + 64-bit arm frida_server unity version: 2020.3.29f1 Il2Cpp.perform.... Test1: System.Void Test1(System.String aa); // 0x004ddc80 Test1.fridaSignature: pointer,pointer this: AAAA string: "AAAA"
At this level, frida-il2cpp-bridge
is not involved at all - this may be a Frida bug (but I don't think so).
Are you using an emulator, by chance?
All tests are performed on the MI 8 UD
I don't know, I can't reproduce. Other than updating frida-compile
to 10.2.5
, I don't have ideas.
Does this happen with all methods?
Also, try this:
const replacement = new NativeCallback((instance, string) => {
console.log("NativeCallback", instance, string);
console.log("this:", new Il2Cpp.Object(instance));
console.log("string:", new Il2Cpp.String(string));
}, "void", ["pointer", "pointer"]);
Interceptor.replace(Test1.virtualAddress, replacement);
Il2Cpp.perform.... Test1: System.Void Test1(System.String aa); // 0x0025fe84 Test1.fridaSignature: pointer,pointer NativeCallback 0x6f60053810 0x6f60053810 this: AAAA string: "AAAA"
NativeCallback 0x6f60053810 0x6f60053810
As you can see, these addresses are the same: they are the same objects. As I said previously, this aspect is not related to frida-il2cpp-bridge
, so I'll mark this issue as invalid - a close will follow in the next days.
That method looks compiled correctly, this is how ghidra decompiles it - it looks fair:
void FUN_0025fe84(undefined8 param_1,undefined8 param_2)
{
undefined8 uVar1;
if ((DAT_0077e541 & 1) == 0) {
thunk_FUN_001ce078(&DAT_00744f58);
thunk_FUN_001ce078(&DAT_0074d430);
thunk_FUN_001ce078(&DAT_0074d440);
thunk_FUN_001ce078(&DAT_0074d448);
thunk_FUN_001ce078(&DAT_0074d438);
DAT_0077e541 = 1;
}
uVar1 = FUN_004efd18(0);
uVar1 = FUN_00323914(DAT_0074d448,uVar1,0);
if (*(int *)(DAT_00744f58 + 0xe0) == 0) {
thunk_FUN_00173f34(DAT_00744f58);
}
FUN_004f0ec0(uVar1,0);
uVar1 = FUN_004efcf0(0);
uVar1 = FUN_00323914(DAT_0074d440,uVar1,0);
FUN_004f0ec0(uVar1,0);
uVar1 = FUN_004efcc8(0);
uVar1 = FUN_00323914(DAT_0074d438,uVar1,0);
FUN_004f0ec0(uVar1,0);
uVar1 = FUN_004efca0(0);
uVar1 = FUN_00323914(DAT_0074d430,uVar1,0);
FUN_004f0ec0(uVar1,0);
FUN_004f0ec0(param_2,0);
return;
}
I guess this is a Frida issue, is it up to date?.
Il2Cpp.perform(() => { log('Il2Cpp.perform.... ');
});