-
Notifications
You must be signed in to change notification settings - Fork 200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix tracer return value parse error #483
Conversation
Thanks, I'm fine with that. But perhaps it would be more meaningful if we reported it, even a simple message is fine something like:
Bonus points if you make it red! What do you think? |
I haven’t seen something similar here, how would you implement a value check??
|
Correct impl is const result = returnValue == undefined ? "" :
returnValue instanceof NativePointer ?
returnValue.equals(NULL)
? " = \x1b[0m\x1b[38;5;9mnull [native IL2CPP excpetion occurred]\x1b[0m"
: ` = \x1b[36m${fromFridaValue(returnValue, method.returnType)}\x1b[0m`
: ` = \x1b[36m${fromFridaValue(returnValue, method.returnType)}\x1b[0m`; now tracer works (in prev piece of code it died when |
Hmm, this is how I would do it: let returnValue;
let isError = false;
try {
returnValue = method.nativeFunction(...args);
} catch (_) {
isError = true;
}
if ((this as InvocationContext).threadId == threadId) {
// prettier-ignore
state.buffer.push(`\x1b[2m0x${paddedVirtualAddress}\x1b[0m ${`│ `.repeat(--state.depth)}└─\x1b[33m${method.class.type.name}::\x1b[1m${method.name}\x1b[0m\x1b[0m${returnValue == undefined ? "" : ` = \x1b[36m${fromFridaValue(returnValue, method.returnType)}`}\x1b[0m${isError ? " \x1b[38;5;9m[native IL2CPP excpetion occurred]\x1b[0m" : ""}`);
state.flush();
}
return isError ? NULL : returnValue; However, I'm wondering what happens in case Frida expect us to return a |
Il2Cpp compiled code already have checks for |
Actually we can shift responsibility to the app (it will handle NULL), what do think about this? |
By the way, there's a typo here, it should be |
I found method which already throws error (but target still works)
after commit:
For other types it should work |
Note: Backend.method("HandleResponse").implementation = function (req) {
this.method<void>("HandleResponse").invoke(req);
// let's imagine that an exception was caught (abort was called), we returning null
console.log("test: return NULL for System.Void HandleResponse(HttpRequest request);");
console.log(`isPrimitive for original ret (void): ${this.method<void>("HandleResponse").returnType.isPrimitive}`)
return NULL;
} output:
|
const cm = ((globalThis as any).cm = new CModule(`int lol(void) { return 1; }`));
Interceptor.replace(cm.lol, new NativeCallback(() => NULL as any, "int", []));
console.log(new NativeFunction(cm.lol, "int", [])()); I get |
Look, i pushed one more commit which does |
ping |
Sorry for bothering. looks like you are familiar with this module. would you mind help my question in issue? |
@vfsfitvnm please review this pr |
@vfsfitvnm ping |
@commonuserlol Hi, I think I'm having the same issue here. I've tried building your fork and there were 4 errors before, but now there are only 2 left. Could you please take a look? I'd really appreciate it. - Error: abort was called
- at invokeRaw (structs/method.ts:234)
- at toString (structs/object.ts:58)
- at concat (native)
- at <anonymous> (tracer.ts:297)
- at map (native)
- at callback (tracer.ts:297)
- Error: access violation accessing 0x10
- at get length (structs/string.ts:26)
- at get content (structs/string.ts:5)
- at toString (structs/object.ts:58)
- at concat (native)
- at <anonymous> (tracer.ts:297)
- at map (native)
- at callback (tracer.ts:297) |
@fakekey Hi, I haven't these error when tested, can you tell game name (or send link) |
I see. I think we shouldn't flood there. Please create issue on my repo or you can DM me at discord (same name as on github) to track it. I'll look into tomorrow |
Before we used Interceptor.replace which called `NativeFunction`. For reasons that are not very clear to me, it could throw "abort was called", which made us return a null pointer and possibly crash the program. Now we use Interceptor.attach and thus do not interrupt the original execution. For example: previous implementation il2cpp: 0x010d4c94 ┌─UserTargeting.HamsterOfferwall::get_ActiveReward(this = HamsterOfferwall (UserTargeting.HamsterOfferwall)) 0x010d4c94 └─UserTargeting.HamsterOfferwall::get_ActiveReward = null [native IL2CPP exception occurred] // <- null pointer returned after that the app crashed. new implementation il2cpp: 0x010d4c94 ┌─UserTargeting.HamsterOfferwall::get_ActiveReward(this = HamsterOfferwall (UserTargeting.HamsterOfferwall)) 0x010d4c94 └─UserTargeting.HamsterOfferwall::get_ActiveReward = "" and execution continues as desired, yay! One more important improvement, as @fakekey and @Vladik01-11 noticed, some apps have issues with getting the parameter value (again, for reasons I don't understand). Now we check if it is possible to get the parameter value, instead of spamming the console with errors, if it is impossible to get the parameter value (as I noticed, this applies mostly to Il2Cpp.Object) you will see the red text "null (failed to parse parameter value)".
Hi @fakekey, @Vladik01-11 - reproduced, pushed and tested on |
Confirmed by fakekey (via discord) |
This reverts commit 875b84b.
Reverted due return value parsed incorrectly. |
When a method definition does not include an null value (example:
MyClass getMyClass();
) but something went wrong (or null check was stripped by il2cpp compiler) it can returnNULL
soError: abort was called
will be thrown (I think becauseNativeFunction
expectedpointer
return type but got null)One more note, "real" IL2CPP code checks if the value is null (at least ghidra decompiler shows that), so nothing bad should happen
Before:
After: