Is possible use Frida on Windows for tracing methods in Java apps?
I'm already use it for debugging APK on Android using Javascript, but I cannot do the same on Windows in a Java application.
More specific question: I need to hook some obfuscated functions and get parameters values and return value of those.
Yes.
You can hook method by address + base.
https://www.frida.re/docs/examples/windows/
Interceptor.attach(Module.findExportByName(null, "dlopen"), {
onEnter: function(args) {
this.lib = Memory.readUtf8String(args[0]);
console.log("[*] dlopen called with: " + this.lib);
},
onLeave: function(retval) {
if (this.lib.endsWith(moduleName)) {
Interceptor.attach(Module.findBaseAddress(moduleName).add(nativeFuncAddr_AKA_offset), {
onEnter: function(args) {
console.log("[*] hook invoked");
}
});
}
}
});
Related
I have my JNLP application which work perfectly fine with Oracle JDK.
But when I tried running it with openJDK 1.8.0.252 and IcedTea WS (provided by default with openJDK).
I see My application can be launched with multiple instances although there is implementation of SingleInstanceListener .
I never got the logger "Start newActivation method" printed in console.
Also I wanted (tried) to Launch the application with parameter.
Can anyone help me with this
Code ::
// Code from Main class
private void startSingleInstance() {
log.info("Initializing single instance Web Start");
boolean didAddListener = false;
final SingleInstanceListener singleInstanceListener = new SingleInstanceListener() {
#Override
public void newActivation(String[] args) {
log.info("Start newActivation method");
log.info("newActivation(args:{}) in env {} Frame visible? {}",
new Object[] {args, System.getProperty("app.environment"), frame != null ? frame.isVisible() : false});
if (args.length > 1) {
// some logic
}
SwingHelper.frameToFront(frame);
}
};
try {
SingleInstanceService singleInstanceService =
(SingleInstanceService) ServiceManager.lookup("javax.jnlp.SingleInstanceService");
log.info("singleInstanceService {} ",singleInstanceService);
// add the listener to this application!
log.info("Add singleInstanceListener");
singleInstanceService.addSingleInstanceListener(singleInstanceListener);
didAddListener = true;
} catch (UnavailableServiceException e) {
log.info("Unable to register single WebStart instance (Not Web Start environment?).");
}
At the OpenWebStart Repo you can find an issue that current discuss how the SingleInstanceListener should work. Since the people that Maintain OpenWebStart are the same people that maintain IcedTeaWeb it would be good if you can add your input to that issue :)
I'm using Nashorn with Java to make a modular plugin system. The plugins will be written in Javascript. An important feature is to have handlers that can be written in the Javascript code. Starting off I was aiming to make a simple command system. The javascript implements an interface, and calls a Java method to register the command. However, I am getting an error. I made sure that I am using Nashorn (var usingNashorn = typeof importClass !== "function";) returned true.
The Javascript:
var CommandListener = Java.extend(Java.type("com.techsdev.scriptengine.listeners.CommandListener"), {
invoke : function(sender, command, args) {
java.lang.System.out.println("Received a command: " + command);
}
});
var listen = function(scriptManager) {
var listener = new CommandListener();
scriptManager.registerCommand("plugin name", "test", listener);
}
The Java code:
To invoke "listen":
try {
engine.eval(new FileReader(f));
Invocable invocable = (Invocable) engine;
invocable.invokeFunction("listen", this);
} catch(Exception e) {
logger.error("Failed to load script "+f.getName(), e);
}
where 'f' is the Javascript file
where 'engine' is the Nashorn ScriptEngine
where 'this' is the ScriptManager
In the ScriptManager class this method is responsible to register the actual command:
public void registerCommand(String plugin, String command, CommandListener listener) {
if(commandHandlers.containsKey(command.toLowerCase())) {
logger.warn("Command "+command+" tried to be registered, but is already registered!");
return;
}
commandHandlers.put(command.toLowerCase(), listener);
}
However, this code throws the following exception:
java.lang.ClassCastException: com.techsdev.scriptengine.listeners.CommandListener$$NashornJavaAdapter cannot be cast to com.techsdev.scriptengine.listeners.CommandListener
at com.techsdev.scriptengine.JsScriptManager.registerCommand(JsScriptManager.java:168) ~[scriptengine-mod.jar:?]
at jdk.nashorn.internal.scripts.Script$Recompilation$2$616A$\^eval\_.listen(<eval>:22) ~[?:?]
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:625) ~[nashorn.jar:?]
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494) ~[nashorn.jar:?]
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393) ~[nashorn.jar:?]
at jdk.nashorn.api.scripting.ScriptObjectMirror.callMember(ScriptObjectMirror.java:199) ~[nashorn.jar:?]
at jdk.nashorn.api.scripting.NashornScriptEngine.invokeImpl(NashornScriptEngine.java:383) ~[nashorn.jar:?]
at jdk.nashorn.api.scripting.NashornScriptEngine.invokeFunction(NashornScriptEngine.java:190) ~[nashorn.jar:?]
at com.techsdev.scriptengine.JsScriptManager.loadFile(JsScriptManager.java:134) [JsScriptManager.class:?]
at com.techsdev.scriptengine.JsScriptManager.loadFolder(JsScriptManager.java:116) [JsScriptManager.class:?]
at com.techsdev.scriptengine.JsScriptManager.init(JsScriptManager.java:104) [JsScriptManager.class:?]
Please let me know if I missed anything.
Thank you in advance.
I'd print the classloader of com.techsdev.scriptengine.listeners.CommandListener from script and as well as from Java code.
From JavaScript:
print(Java.type("com.techsdev.scriptengine.listeners.CommandListener").class.classLoader)
From Java:
System.out.println(com.techsdev.scriptengine.listeners.CommandListener.class.getClassLoader());
If the same (fully-qualified) named class bytes is loaded by two different loaders, those (runtime) classes are different from JVM point of view. If you see different classloaders from javascript and java code, most likely you have a classpath/classloader issue.
My situation
I call multiple Groovy scripts from Java, they both contain long-lived Groovy objects.
I would like my Groovy scripts to make some changes to a Java meta-class for a Java class (that have about 100 instances). However, the scripts should be able to make different changes, and changes in one of the scripts should not be reflected in the other scripts.
The problem: The meta-class for the Java class is shared across all the scripts.
This question is similar to How do I undo meta class changes after executing GroovyShell? but in this case I want two scripts to execute simultaneously, so it is not possible to reset after script execution.
Example Code
SameTest.java
public interface SameTest {
void print();
void addMyMeta(String name);
void addJavaMeta(String name);
void callMyMeta(String name);
void callJavaMeta(String name);
}
SameSame.java
import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;
public class SameSame {
public SameTest launchNew() {
try {
GroovyScriptEngine scriptEngine = new GroovyScriptEngine(new String[]{""});
Binding binding = new Binding();
binding.setVariable("objJava", this);
SameTest script = (SameTest) scriptEngine.run("test.groovy", binding);
return script;
} catch (Exception | AssertionError e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
SameSame obj = new SameSame();
SameTest a = obj.launchNew();
SameTest b = obj.launchNew();
a.addMyMeta("a");
a.callMyMeta("a");
try {
b.callMyMeta("a");
throw new AssertionError("Should never happen");
} catch (Exception ex) {
System.out.println("Exception caught: " + ex);
}
a.addJavaMeta("q");
b.callJavaMeta("q");
a.print();
b.print();
}
}
test.groovy
ExpandoMetaClass.enableGlobally()
class Test implements SameTest {
SameSame objJava
void print() {
println 'My meta class is ' + Test.metaClass
println 'Java meta is ' + SameSame.metaClass
}
void addMyMeta(String name) {
println "Adding to Groovy: $this $name"
this.metaClass."$name" << {
"$name works!"
}
}
void addJavaMeta(String name) {
println "Adding to Java: $this $name"
objJava.metaClass."$name" << {
"$name works!"
}
}
void callMyMeta(String name) {
println "Calling Groovy: $this $name..."
"$name"()
println "Calling Groovy: $this $name...DONE!"
}
void callJavaMeta(String name) {
println "Calling Java: $this $name..."
objJava."$name"()
println "Calling Java: $this $name...DONE!"
}
}
new Test(objJava: objJava)
Output
Adding to Groovy: Test#7ee955a8 a
Calling Groovy: Test#7ee955a8 a...
Calling Groovy: Test#7ee955a8 a...DONE!
Calling Groovy: Test#4a22f9e2 a...
Exception caught: groovy.lang.MissingMethodException: No signature of method: Test.a() is applicable for argument types: () values: []
Possible solutions: any(), any(groovy.lang.Closure), is(java.lang.Object), wait(), wait(long), each(groovy.lang.Closure)
Adding to Java: Test#7ee955a8 q
Calling Java: Test#4a22f9e2 q...
Calling Java: Test#4a22f9e2 q...DONE!
My meta class is groovy.lang.ExpandoMetaClass#2145b572[class Test]
Java meta is groovy.lang.ExpandoMetaClass#39529185[class SameSame]
My meta class is groovy.lang.ExpandoMetaClass#72f926e6[class Test]
Java meta is groovy.lang.ExpandoMetaClass#39529185[class SameSame]
Desired result
The two lines showing information about the Java meta should be different.
This should crash:
a.addJavaMeta("q");
b.callJavaMeta("q");
The question
Is it possible somehow to use different MetaClassRegistry's in the different GroovyScriptEngine instances?
Or is there any other way to make the desired result as shown above happen?
The feature you are looking for is one I had planed for Groovy 3. But since I will no longer be able to work full time on Groovy and since nobody else dares a big change to the MOP this is no option at the moment.
So is it possible to use different MetaClassRegistry's in the different GroovyScriptEngine instances?
No, since you cannot use different MetaClassRegistry's. The implementation is somewhat abstracted, but the usage of MetaClassRegistryImpl is hardcoded and allows for only one global version.
Or is there any other way to make the desired result as shown above happen?
That depends on your requirements.
If you could let the scripts not share the Java classes (load them using differing class loaders), then you don't have a problem with shared meta classes to begin with (for those). If you want more the idea bayou.io had might be best.
You could provide your own meta class creation handle (see setMetaClassCreationHandle in MetaClassRegistry). Then you would have to of course capture a call like ExpandoMetaClass.enableGlobally(). You could use ExpandoMetaClass with a custom invoker (set someClass.metaClass.invokeMethod = ...) or of course directly extend the class. You would then somehow need a way to recognize that you are coming from one script or the other (there is something called origin or caller in the bigger invokemethod signature, but the information is not always reliable. Same thing for get/setProperty). As for how to reliably and efficiently transport that information... well.. that's something I have no answer for. You have to experiment if what ExpandoMetaClass provides is good enough for you. Maybe you could use a ThreadLocal to store the information... though then you would have to write a transform, which will rewrite all method and property calls and most probably cause a performance disaster.
I found a couple of solutions how to do that in Java, but did not find how can I do it in QML or Qt. I know that first I should set the WAKE_LOCK permission in AndroidManifest.xml. What should I do to make it possible to turn on and off the screen locking from Qt in runtime?
Use window.callMethod<void> instead of window.callObjectMethod
Run on GUI thread with QtAndroid::runOnAndroidThread
Clear exceptions afterwards
To disable always on behaviour, use clearFlags
This is tested Qt 5.7 code:
void keep_screen_on(bool on) {
QtAndroid::runOnAndroidThread([on]{
QAndroidJniObject activity = QtAndroid::androidActivity();
if (activity.isValid()) {
QAndroidJniObject window =
activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
if (window.isValid()) {
const int FLAG_KEEP_SCREEN_ON = 128;
if (on) {
window.callMethod<void>("addFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
} else {
window.callMethod<void>("clearFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
}
}
}
QAndroidJniEnvironment env;
if (env->ExceptionCheck()) {
env->ExceptionClear();
}
});
}
You can use the Qt Android Extras module and use JNI to call the relevant Java function from C++. Something like :
void keepScreenOn()
{
QAndroidJniObject activity = QtAndroid::androidActivity();
if (activity.isValid()) {
QAndroidJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
if (window.isValid()) {
const int FLAG_KEEP_SCREEN_ON = 128;
window.callObjectMethod("addFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
}
}
}
You can achieve this by editing the java file used by qt itself. In installation path under src in android path you will find QtActivity.java file. In the onCreate function add the below line
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
WAKE_LOCK permission in AndroidManifest.xml also should be added.
Build the project, it will work fine.
I am working on a Phonegap Project where i am at the stage of extending the base capabilities of Phonegap with a custom Plugin. The stupid problem i am having is getting the Plugin to react correctly. The Plugin if called with the 'echo' parameter should answer giving back its matched parameter name, the same goes for 'echo2'.
The strange part:
'echo' returns the expected answer (it executes the success callback) whereas the 'echo2' variant returns the error callback. Seriously running out of ideas...
The JS Definitions: Identical functions (only the 4th Parameter is different)
window.echo = function(str, callback) {
cordova.exec(callback, function(err) {
callback('Nothing to echo.');
}, 'Echo', 'echo', [str]);
};
window.sync = function(str, callback) {
cordova.exec(callback, function(err) {
callback('Nothing to echo.');
}, 'Echo', 'echo2', [str]);
};
The JS Calls on these functions:
echo('Echo String', function(echoValue) {
alert(echoValue);
});
sync('Sync String', function(echoValue) {
alert(echoValue);
});
Java Class:
public class Echo extends CordovaPlugin {
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
switch(action) {
case "echo": String message = args.getString(0);
this.echo("Call on: Echo.echo()" + message, callbackContext);
return true;
case "echo2": String message = args.getString(0);
this.echo("Call on: Echo.echo2()" + message, callbackContext);
return true;
}
return false;
}
private void echo(String message, CallbackContext callbackContext) {
if (message != null && message.length() > 0) {
callbackContext.success(message);
} else {
callbackContext.error("Expected one non-empty string argument.");
}
}
}
To all those having a similar problem, here is some information on why this did not work:
Firstly: The Code works fine - the problem doesn't lie here.
Where's the fault?
When i asked the question, the Java Class was named Echo which worked when the class method was being called. Trying to call any other method fails because the
Phonegap Build Service does not allow direct includes of plugins
BUT in my case it still partially worked because the Java Class Echo happens to be a standard Plugin that Phonegap Build included for me.
This Echo Plugin being included by Phonegap Build happens to have a method echo which resulted in a success callback, obviously.
After further reading:
A tool called plugman (also developed by Adobe) handles the custom plugin implementation by adding the created plugin to the phonegap project ... i am still testing and learning this, the official information (and only information i found) is available here:
► Leads to the deprecated pluginstall tool
► Plugman Tool Repo - GitHub