frida - hook Android method not work if method called before attach - frida

Say app use a button to trigger function call.
Button btn = new Button(this);
btn.setText("Test");
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
hello();
}
});
The function define:
public int hello() {
Log.v(TAG,"hello frida!");
return 0;
}
The script to hook hello API:
Java.perform(function () {
var clzname = "com.sample.MainActivity";
var instance = Java.use(clzname);
instance.hello.overload().implementation = function () {
console.log("[*] onEnter hello...");
var retval = this.hello();
return retval;
};
});
If launch app, then attach script:
frida -U -l hook.js com.sample
it works fine, below log will output:
-> [*] onEnter hello...
But if launch app, then click button to trigger the API call firstly, then attach script, it does not work, no output from console.
Does that means if API already being called, then we can not hook it? How to fix my script?

Related

xamarin.android webview evaluatejavascript It does not return any value at all

I have a fundamental problem that I can not really understand where the problem comes from.
I am designing a project by xamarin.android webview.
Now I need to run a Java function in Web View and check the return value in a if function.
I searched all the websites and in all of them I got the following code:
In Main Activity Class:
public class MainActivity : AppCompatActivity
{
WebView web_view;
.
.
.
Define web_view public in class
In OnCreate :
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.activity_main);
web_view = FindViewById<WebView>(Resource.Id.webview);
web_view.Settings.JavaScriptEnabled = true;
web_view.Settings.BuiltInZoomControls = true;
web_view.Settings.AllowContentAccess = true;
web_view.SetWebViewClient(new HelloWebViewClient());
web_view.LoadUrl("https://www.example.com");
}
In Back Key Press:
public override bool OnKeyDown(Android.Views.Keycode keyCode, Android.Views.KeyEvent e)
{
if (keyCode == Keycode.Back)
{
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat)
{
JavascriptResult jsr = new JavascriptResult();
string strjs = "closePackageDetails();";
web_view.EvaluateJavascript(strjs, jsr);
string rrr = jsr.strResult;
Toast.MakeText(this, "message send:" + rrr, ToastLength.Long).Show();
}
else
{
Toast.MakeText(this, "android version less 4.4" , ToastLength.Long).Show();
}
}
}
On JavascriptResult Class (separate on C# Class Palaced in MainActivity in Root directory)
namespace webviewapp
{
class JavascriptResult : Java.Lang.Object, IValueCallback
{
public string strResult;
public void OnReceiveValue(Java.Lang.Object result)
{
Toast.MakeText(Android.App.Application.Context, "رسیدن نتیجه احضار شد", ToastLength.Long);
strResult = ((Java.Lang.String)result).ToString();
}
}
}
<>
Everything looks right and the program is debugged without error and the APK file is created successfully.
After installing the program on the mobile phone and running it, the web page is loaded and everything looks good.
By touching the back button, the JavaScript function is executed correctly and the result is visible in Web View. But the result, which is a boolean value, is not returned.
In fact, the OnReceiveValue procedure does not work.
The variable 'rrr' always displays an null value.
Where it went wrong really puzzled me?
It is happening because the callback is executed later than the next line ,so the variable 'rrr' is always null.
Add the breakpoint at OnReceiveValue and the line string rrr = jsr.strResult; to check it .
Just do the next thing directly in the method OnReceiveValue in the callback class.

Electron - ipcRenderer not working in Async Class

i have a class with a Constructor and Async functions.
I have done module.exports so that i could call my Class from my GUI.js file and in my GUI.js file, i have required that class, and everything works fine.
But inside my class, im trying to do this ipcRenderer.send('message', 'Hello');
And im getting this error:
TypeError: Cannot read property 'send' of undefined
is it possible to remote the ipcRenderer in my GUI.js?
Thanks.
i have required the module in my main file, and in my renderer file it sends ipcRenderer.send('startMyClass');
And in my Main file: ipcMain.on('startMyClass', (event, args) => {
const client = new myClass();
client.Start();
})
This is my class/index.js file that is being required in my main file.
const request = require('request-promise');
const cheerio = require('cheerio');
const { ipcRenderer } = require('electron')
class myClass {
constructor() {
this._jar = request.jar();
this._request = request.defaults({ jar: this._jar });
}
async Start() {
await this.Test();
};
async Test() {
ipcRenderer.send('myMessage', 'Hello');
}
}
module.exports = myClass;
EDIT:
If i dont require it, and have the whole class in my main file, i can do event.sender.send('myMSG', 'hello');
But i want to do it in my class, that's NOT in the same file as my main.
Sending message from Main to Renderer should be done by sending to a specific webContents. That's why event.sender.send('myMSG', 'hello') works, while ipcRenderer.send not. The latter sends from Renderer to Main as stated in docs (and also, cannot be accessed from Main process as your Error told you it's undefined).
As explainded in ipcMain's docs you should access the webContents you want to send to and call send on that.
So to correct your code you can
Pass a reference to the main window to myClass and call send on that
class myClass {
constructor(args) {
// ...
this.mainWindow = args.win
}
// ...
async Test() {
this.mainWindow.webContents.send('myMessage', 'Hello');
}
}
Or send to the actually focused window (BrowserWindow.getFocusedWindow()) if that fits your needs
class myClass {
// ...
async Test() {
BrowserWindow.getFocusedWindow().webContents.send('myMessage', 'Hello');
}
}

javaFX webview window.onload is fired before loadworker succeeds

I use a JavaFX webview in my application. With the following code I set a member after the page has been loaded
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
#Override
public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("mymember", new JavaScriptBridge(this));
}
}
});
Now in javascript I can invoke mymember.doSomething() e.g. called when I press the button and it's executed successfully, but if I add the following code to the html
<script>
function startup() {
mymember.doSomething();
}
window.onload=startup;
</script>
It's not executed automatically when the page is loaded. It seems like window.onload is executed before the LoadWorker gets notified. So mymember is not set yet. But on the other hand, I cannot set mymember before the html has been loaded, right?
Any idea when I need to set mymember to have it ready when window.onload is executed?
Thanks!
Maybe it's too late for an answer to this problem, but after answering this question, I've been trying to find a reason why executeScript has to be called after the complete load of the webpage.
So I've done this test:
public class EarlyWebEngineTest extends Application {
#Override
public void start(Stage stage) {
final WebView webView = new WebView();
final WebEngine webEngine = webView.getEngine();
// Early call of executeScript to get a JavaScript object, a proxy for the
// Java object to be accessed on the JavaScript environment
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("app", new JavaApplication());
webEngine.getLoadWorker().stateProperty().addListener((ov,oldState,newState)->{
if(newState==State.SCHEDULED){
System.out.println("state: scheduled");
} else if(newState==State.RUNNING){
System.out.println("state: running");
} else if(newState==State.SUCCEEDED){
System.out.println("state: succeeded");
}
});
Button button=new Button("Load Content");
button.setOnAction(e->webEngine.loadContent("<html>"
+ " <script>function initialize() {"
+ " var nameVar = \"This is a JS var\"; "
+ " app.callJavascript(nameVar);"
+ "} </script>"
+ " <body onLoad=\"initialize()\">Hi, this is a test!</body>"
+ "</html>"));
VBox vbox = new VBox(10,button,webView);
Scene scene = new Scene(vbox,400,300);
stage.setScene(scene);
stage.show();
}
public class JavaApplication {
public void callJavascript(String msg){
System.out.println("JS>> "+msg);
}
}
public static void main(String[] args) {
launch(args);
}
}
The content is not loaded until the button is clicked, but we've already created the JavaScript object on the browser.
Before clicking the button, there's nothing on the output console. But if we click the button... this is the output:
state: scheduled
state: running
JS>> This is a JS var
state: succeeded
As we can see, the Java object is effectively passed to the script before the latter is executed, and app.callJavascript is successfully called while the content is being loaded.
Note that for the common purpose of accessing the loaded DOM, the usual approach of calling executeScript after State.SUCCEEDED is still the recommended way.
Woks for all (including subsequent) pages:
Where "java" is set in JAVA code:
window.setMember("java", new JavaApplication());
HTML (subsequent) page, keep waiting for 100ms if var "java" is not set (externally by JAVA):
<script>
function init(){
if (typeof java !== 'undefined') {
java.doSomething();
}else{
setTimeout(function(){ init() }, 100 );
}
}
$(document).ready(function(){
init();
});
</script>
Yes, loadworker always execute after window.onload or document.onload.
The workaround you can try, you can create new listener in javascript, for example so-called:
document.addEventListener("deviceready", function(){
MyJavaBridge.executeJavaMethod();
});
And then in your loadworker, you can do this:
webview.getEngine().getLoadWorker().stateProperty().addListener((ov, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
JSObject window = (JSObject) webview.getEngine().executeScript("window");
System.out.println("window : " + window);
window.setMember("MyJavaBridge", javaBridge);
webview.getEngine().executeScript("const event = new Event('deviceready');document.dispatchEvent(event);");
}
});
As you can see, you execute this webview.getEngine().executeScript("const event = new Event('deviceready');document.dispatchEvent(event);"); after setMember, so instead of initialise your work in window.onload, you can do it in your custom event listener deviceready, so you can have better control on the sequence of page load and java side loadworker.
This is exactly how cordova doing, this idea is coming from it.
JQuery document.ready vs Phonegap deviceready

How to call javascript functions from blackberry native?

I am developing an app where i need to call some methods from blackberry native to javascript.
when i click on back key down event , i want to trigger the onBackKeyDown() method, which is declared in javascript.
Main.java
protected boolean keyDown(int keycode, int time) {
// TODO Auto-generated method stub
if(Keypad.key(keycode) == Keypad.KEY_ESCAPE)
{
// onBackKeyDown();
// i want to call the following method which is declared in main.js file
Dialog.alert("this is back button");
return true;
}
return super.keyDown(keycode, time);
}
main.js
function onBackKeyDown() {
try {
if ($.mobile.activePage.is("#Page1")) {
$.mobile.changePage("#page5");
} else if ($.mobile.activePage.is("#page2")) {
$.mobile.changePage("#main");
} else if ($.mobile.activePage.is("#page3")) {
$.mobile.changePage("#main");
} else if ($.mobile.activePage.is("#main")) {
navigator.app.exitApp();
}
} catch(e) {
alert("Exception:ConsoleLog.log:" + e);
}
}
As i am having idea that by using "extendScriptEngine" , the methods declared in javascript are invoked in native. But here how to invoke the methods in javascript which are in native as per my above code... can anyone please help me with this...
You don't show this code, but I have to assume that your app has some Screen that contains some kind of browser field, which is displaying HTML content.
I can't tell you for sure without seeing that code, but what I would recommend is to use net.rim.device.api.browser.field2.BrowserField (Browser Field 2), if your app only needs to support OS 5.0 and higher.
If you have to support less than OS 5.0, I'm not sure how to do that.
Anyway, with this 5.0+ BrowserField, you can do this:
BrowserFieldConfig config = new BrowserFieldConfig();
config.setProperty(BrowserFieldConfig.JAVASCRIPT_ENABLED, Boolean.TRUE); // should be the default
// Browser basic initialization
BrowserField _browserField = new BrowserField(config);
and then
protected boolean keyDown(int keycode, int time)
{
if(Keypad.key(keycode) == Keypad.KEY_ESCAPE)
{
// i want to call the following method which is declared in main.js file
_browserField.executeScript("onBackKeyDown()");
Dialog.alert("this is back button");
return true;
}
return super.keyDown(keycode, time);
}

Blackberry button click handler

I want to run some Java code when the user clicks on this ToolbarButtonField in my BlackBerry app. I have the following code which is not working. Please tell me where I am wrong.
butHome = new ToolbarButtonField(new StringProvider("Home"));
butHome.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
System.out.println("Clicked...");
}
});
You can use:
ToolbarButtonField#invoke
Performs an action when this
ToolbarButtonField is clicked on if
Command has been set. A click is
defined as the following sequence of
touch events: TouchEvent.DOWN,
TouchEvent.CLICK, TouchEvent.UNCLICK
and TouchEvent.UP.
You're going to have to use that in conjuction with the Command framework. If that's not desirable, override ToolbarButtonField#touchEvent for a TouchEvent.UNCLICK event to execute the desired code.
public boolean touchEvent(TouchEvent message) {
if ( message.geEvent() == TouchEvent.UNCLICK ) {
// do what I want.
}
}
Try this:
butHome = new ToolbarButtonField(new StringProvider("Home")) {
protected boolean navigationClick(int status, int time) {
System.out.println("Clicked...");
return true;
}
});

Resources