Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save FrankSpierings/6caa692a2c5fc10663176ce9aa78e646 to your computer and use it in GitHub Desktop.
Save FrankSpierings/6caa692a2c5fc10663176ce9aa78e646 to your computer and use it in GitHub Desktop.
Override Android WebView to include a custom JavaScript handler
Java.perform(() => {
// Register a new WebAppInterface Javascript environment
const WebView = Java.use('android.webkit.WebView');
const WebAppInterface = Java.registerClass({
name: 'com.evil.WebAppInterface',
fields: {
mContext: 'android.content.Context',
},
methods: {
$init: [{
argumentTypes: ['android.content.Context'],
implementation(context) {
console.log("Initializing", context);
this.mContext.value = context;
}
}],
// Example export
showToast: [{
returnType: 'void',
argumentTypes: ['java.lang.String'],
implementation(message) {
const Toast = Java.use('android.widget.Toast');
// console.log(this.mContext.value, message, Toast.LENGTH_SHORT.value);
Toast.makeText.overload('android.content.Context', 'java.lang.CharSequence', 'int').call(Toast, this.mContext.value, message.toString(), Toast.LENGTH_SHORT.value).show();
}
}]
}
});
// Hook into the main activity to get the context
const Activity = Java.use('android.app.Activity');
Activity.onCreate.overload('android.os.Bundle').implementation = function(savedInstanceState) {
// Call the super
this.onCreate(savedInstanceState);
// Access the context
const context = this;
console.log('Context:', context);
const webappinterface = WebAppInterface.$new(context);
// Hook loadUrl calls, to dynamically add our JavaScript environment
WebView.loadUrl.overload('java.lang.String').implementation = function (url) {
console.log('Adding JavaScript interface to webview, navigating to:', url);
this.addJavascriptInterface(webappinterface, "AndroidInterface");
return this.loadUrl(url);
}
};
// Intercepting calls to WebViews to instruct the existince of @JavascriptInterface
const Executable = Java.use('java.lang.reflect.Executable');
Executable.isAnnotationPresent.implementation = function (clazz) {
const name = clazz.getName();
console.log('Class:', name);
if (name === "android.webkit.JavascriptInterface") {
console.log("Overriding; Instruct code the annotation IS there");
return true;
}
return this.isAnnotationPresent(clazz);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment