Reputation: 409
I want to instrument an APK to count the number of executions of its callback methods (similar to this SO post).
To do so, I want to create a static class from scratch (similar to this link) which keeps the counting numbers. Then add this class to the APK, and finally instrument the beginning of callback methods to call a method of this static class (similar to this link).
I was able to do a similar thing with a Java application but I couldn't do it for an APK. Here is the part of the code that generates a new SootClass and adds it to Scene
:
SootClass staticCls = generateClass("StaticCounter");
Scene.v().addClass(staticCls);
Scene.v().addBasicClass("StaticCounter", SootClass.SIGNATURES);
Scene.v().loadNecessaryClasses();
generateClass
is adapted from here. But when I examined the modified APK, there was no sign of StaticCounter
class. Moreover, I installed and ran the modified APK and got this error:
08-21 14:15:45.936 19917 19917 E AndroidRuntime:
Caused by: java.lang.ClassNotFoundException:
Didn't find class "StaticCounter" on path:
DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/data/app/APKNAME-RdhHiJzxKyyUHh_KCi6RUA==/base.apk"],nativeLibraryDirectories=[/data/app/APKNAME-RdhHiJzxKyyUHh_KCi6RUA==/lib/x86, /system/lib]]
Which simply shows the generated class is not inside the APK.
Any solution to this problem?
Upvotes: 1
Views: 505
Reputation: 409
I guess I found why the newly generated class was unknown to the app thanks to Martin Zitler's hint. The generated class must be in the package of the APK. Soot handles the package of a class by looking at the signatures of the class. As a result, the StaticCounter
class must have a signature like
com.example.app.StaticCounter
which indicates that StaticCounter
is in the package com.example.app
.
It is possible to find the package name using ProcessManifest
class which can be found in FlowDroid:
new ProcessManifest(apkPath).getPackageName();
I simplified the working code and put it here. It creates a new class from scratch and adds a static integer field and a method that the field is the times that the static method is called, and the method prints this value. Then using a transformation pack, every method in the app will call this static method.
Upvotes: 0
Reputation: 1393
Soot will not emit the class unless you have flagged it as application class. Can you try that?
Upvotes: 0
Reputation: 76807
You might need to provide the dependency it demands:
android {
useLibrary "org.apache.http.legacy"
}
The reason why it won't build might be, that StaticCounter
is unknown at compile time - because it likely should not be referenced from within the application package, which does not know it. Check out this blog post, apparently from the Soot
author... the driver class might be key to success:
//prefer Android APK files// -src-prec apk
Options.v().set_src_prec(Options.src_prec_apk);
//output as APK, too//-f J
Options.v().set_output_format(Options.output_format_dex);
// resolve the PrintStream and System soot-classes
Scene.v().addBasicClass("java.io.PrintStream", SootClass.SIGNATURES);
Scene.v().addBasicClass("java.lang.System", SootClass.SIGNATURES);
here's the whole example: AndroidInstrument.java
Upvotes: 1