Why is "this" undefined when hooking abstract methods using Frida? - javascript

it's two days that I am having a problem hooking and calling getPackageInfo using Frida.
I have wrote this code:
Java.perform(()=>{
const jPM=Java.use('android.app.ApplicationPackageManager');
const getPkgInfo=jPM.getPackageInfo.overload('java.lang.String','int');
getPkgInfo.implementation=(pname,f)=>{
console.log("Called => getPackageInfo (Flag="+f+", Pkg="+pname+")");
return getPkgInfo(this,pname,f);
}
});
At the line that calls getPkgInfo (return getPkgInfo(this,pname,f);) i get this error:
Called => getPackageInfo (Flag=0, Pkg=test.app)
{"type":"error","description":"TypeError: cannot read property '$getHandle' of undefined","stack":"TypeError: cannot read property '$getHandle' of undefined
at value (frida/node_modules/frida-java-bridge/lib/class-factory.js:1052)
at e (frida/node_modules/frida-java-bridge/lib/class-factory.js:585)
at <anonymous> (/script.js:42)
at apply (native)
at ne (frida/node_modules/frida-java-bridge/lib/class-factory.js:619)
at <anonymous> (frida/node_modules/frida-java-bridge/lib/class-factory.js:597)","fileName":"frida/node_modules/frida-java-bridge/lib/class-factory.js","lineNumber":1052,"columnNumber":1}
So the method is hooked, because i can see the Called => getPackageInfo (Flag=0, Pkg=test.app) string, but i can't call the original method.
This happens only when i try hooking methods that are normally called using the abstract variant (in this case android.content.pm.PackageManager.getPackageInfo, but i have also tried hooking getPackageManager).
I have made different versions of this code, for example one that calls the function in this way: this.getPackageInfo.overload('java.lang.String','int').call(this,pname,f); and i get an error saying that "this" is undefined, so i think that it is the problem.
I have tried this script on different apps and devices but i always get the same result.
I am using Frida Inject.
Please help me.

Related

TypeError: elem[prop] is not a function in Webdriveio

TypeError: elem[prop] is not a function
E2E testing in webdriveio. I want to click a button inside an iframe.
let iframe = browser.$('#fullmessage')
browser.pause(1000)
browser.switchToFrame(iframe)
browser.setTimeout({ implicit: 10000 })
let clickAgree = $('a[class="button is-success"]')
clickAgree.click()
browser.switchToParentFrame()
browser.pause(3000)
I was facing same error and when debug more using REPL found that the issue could be due to 2 reasons:
selector is returning array of elements and so it was not able to call the method used.
the method being called on element does not supports.
For example with following code:
$('.some_class').$$('input').getValue();
was getting error - Uncaught Error: elem[prop] is not a function. Using $('.auto_test_class').$$('input')[1].getValue(); works. But its better to use some Id or xpath.
Hope this might be useful for someone facing same issue :)
Hi i faced with the same problem, but in async. The reason is that you need
to await already defined element as parameter:
get iframe() { return $('.iframe'); }
await browser.switchToFrame(await this.iframe);
Because switchToFrame works only with element, not with promise.
Maybe for someone it will be useful.

How to push in 'class instance' or 'this' into a 'Function' method

i am trying to put the user defined logic (Javascript) in frontend and my backend function execute it with 'Function' method (as below)
let cmdResult = Function('"use strict"; let _AW_DAY_SUMMARY_=' + JSON.stringify(_AW_DAY_SUMMARY_) + ';' + sUserDefinedCmd)()
...
this.alicia.dump(); // run the code correctly if hardcoded in script. But hit error below when defined by user frontpage
The user defined logic work correctly, and i was able to push in object with tons of values with JSON.stringify method. But i have a challenge as i have loaded quite a number of classes
constructor(
private alicia: AliciaService,
private benny: BennyService,
private cass: CassService,
) { }
How could the user defined logic to allow call like this.alicia.dump();
Whenever i use it in my user defined logic, it complained
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'alicia' of undefined
There are many business process intensive method in those classes and i need the user defined logic to call and return rather than re-write from scratch.
The execution context of function that was created through Function constructor is a global object: window in your case.
In order to change this context you specify with each context to execute your function through Function.prototype.call():
Function('...').call(this)
Stackblitz Example

Callback function in Axios returning error (using Vue, no jQuery)

I am using Axios with the Vue Javascript framework to loop through an array. I'm trying to set each element in the array to the result of the API call for that element. My functions were not running in order, so I tried using a callback function but it returns an error.
I have looked through other answers(which is why I'm trying to use a callback function) but I still can't get my code to work.
I have a CodePen that shows my problem:
https://codepen.io/thwaawaa/pen/VoEbqR
The CodePen console gives me this error:
[object Error] {
column: 19,
line: 34,
sourceURL: “some long link”
}
here is a working fork with no errors : Codepen
the issue you had is that the this.word inside your then callback was not defined because you didn't bind the vue this inside it ...also you handled the response by using 2 thens so the first one was handling the response but it wasn't returning anything to the second one that's why response was undefined to fix this just use one then or return a value from one and chain it to the other then after it.... i would recommend removing the first one on your axi method and add the code inside it on the other then also like we said you have to bind then and you can do that by replacing :
then(function(response){
var r = response.data[0].phonetic;
this.word[x] = r;
})
with this :
then((response) => {
var r = response.data[0].phonetic;
this.word[x] = r;
})
the arrow function will bind the this implicitly so your function now knows what this means and it won't trigger the catch

Jasmine Unit Tests Unexpected this Reference

I am trying to test a fairly simple JavaScript function in Jasmine, however the first statement is throwing an error for being undefined.
myClass.prototype.functiontoBeTested = function() {
var x = this.method()
...
}
The above throws an error in Jasmine as method is not a function and is undefined. The prototype is altered earlier to have this method, and out of curiosity I assigned this method to my test object in the spec itself as such:
myObject.method = function(){return mockResults;};
So I decided to log this to the console and instead of it being my object, I see Window {top: Window, location: Location, document: document, window: Window, external: Object…} which doesn't seem right. I've had this issue before with testing a function in Jasmine that used this but just changed the source code to refer to the object by name since the function was being assigned to something within the closure. I can't do that in this case, and I'm curious why this is referring to something unexpected (at least to me).
Edit: Some details on what the test case looks like as requested:
it("updates the control count", function(){
var mockResults = { ... };
myObject.method = function() {return mockResults;};
expect(myObject.method).not.toThrow();
});
Right now I'm just trying to get the method to execute to completion during the test. The function to be tested updates the text on some HTML components, I'll work on verifying those once I can get it to actually run. The method that is causing an error is the first line of the function, and is simply an accessor method for the object being called. In actual execution, var x = this.method() runs without issue. When testing in jasmine var x = this.method() throws an error because method() is undefined for this. Instead of this referring to the calling object, it is referring to the window. This doesn't happen live, but only during testing with Jasmine. This method is undefined even when I forcibly define it for the test object just prior to execution in the test as above. That's when I decided to log this to console in the source code and realized it isn't referring to what I would have expected it to refer to.
In JavaScript this for a method depends on the context it was called from. When you do a call myObject.method(), then method was called from the context of myObject, therefore this is myObject.
When you pass your function to Jasmine toThrow matcher, it calls it as it was passed (see source code):
try {
actual();
} catch (e) {
// ....
}
Here, actual() is a call of your method. It has no any specific context, so by default it will be called from window context.
Solution is to explicitly bind you method to myObject like the following:
expect(myObject.method.bind(myObject)).not.toThrow();
Credits to questions, you can find more details there:
Does Jasmine's toThrow matcher require the argument to be wrapped in an anonymous function?
How to write a test which expects an Error to be thrown in Jasmine?

Javascript variable function method call

I apologise if this has been asked elsewhere, I looked but without knowing the name for what I am doing is, I couldn't find anything.
Anyways, the code is as follows:
function alertTypeOptions(AlertType, AlertOptions) {
navigator.notification.AlertType(AlertOptions);
}
This code is for a phonegap / cordova application.
The basic idea is that you pass the function a two variables and these are used to execute the appropriate method. Examples of this could be alertTypeOptions('beep', '3') or alertTypeOptions('vibrate', '2000'). This (should) play the default alert tone 3x or vibrate the phone for 2 seconds.
I am currently getting the following error:
02-21 15:36:07.185: E/Web Console(7206): Uncaught TypeError:
Object #<Object> has no method 'AlertType'
at file:///android_asset/www/res/scripts.js:181
Obviously the function is currently just using the alertType variable as written rather than as a variable.
Is there a way to get this to work elegantly? Currently my only thoughts are to use a switch statement with AlertType as the check.
Jack
It looks like you want to access your function using the bracket notation :
navigator.notification[AlertType](AlertOptions);
or rather, if I trust this documentation and if AlertOptions is an array :
navigator.notification[AlertType].apply(navigator, AlertOptions);

Categories

Resources