Как создать и добавить класс Java в APK с помощью Soot?

Я хочу настроить APK для подсчета количества выполнений его методов обратного вызова (аналогично этому SO post).

Для этого я хочу создать статический класс с нуля (аналогично этому ссылка), в которой хранятся счетные числа. Затем добавьте этот класс в APK и, наконец, настройте начало методов обратного вызова для вызова метода этого статического класса (аналогично этому ссылка).

Я смог сделать то же самое с приложением Java, но не смог сделать это с APK. Вот часть кода, которая генерирует новый SootClass и добавляет его в Scene:

SootClass staticCls = generateClass("StaticCounter");
Scene.v().addClass(staticCls);
Scene.v().addBasicClass("StaticCounter", SootClass.SIGNATURES);
Scene.v().loadNecessaryClasses();

generateClass адаптировано из здесь. Но когда я исследовал модифицированный APK, не было никаких признаков StaticCounter класса. Более того, я установил и запустил модифицированный APK и получил такую ​​ошибку:

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]]

Это просто показывает, что сгенерированный класс не находится внутри APK.

Любое решение этой проблемы?


person noidsirius    schedule 21.08.2019    source источник


Ответы (3)


Возможно, вам потребуется предоставить требуемую зависимость:

android {
    useLibrary "org.apache.http.legacy"
}

Причина, по которой он не может быть собран, может заключаться в том, что StaticCounter неизвестно во время компиляции - потому что, вероятно, не следует ссылаться на него из пакета приложения, который этого не знает. Прочтите сообщение в блоге, по-видимому, от Soot автора ... класс драйвера может быть ключом к успеху:

//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);

вот весь пример: AndroidInstrument.java

person Martin Zeitler    schedule 21.08.2019
comment
Спасибо. Но я уже выполнил шаги из сообщения в блоге. Он отлично работает, когда нет дополнительного класса: после запуска приложения он будет печатать журнал всякий раз, когда я выполняю один из обратных вызовов. Однако мне интересно добавить в пакет новый класс (StaticCounter). Я думаю, должен быть способ изменить конфигурации самого APK, чтобы новый класс был виден для всех методов. - person noidsirius; 22.08.2019
comment
@noidsirius, вы могли бы добавить его в тестовое приложение, добавив его в androidTest исходный набор, или использовать TestSuite и добавить его туда ... Soot кажется довольно специализированным для настольной Java, которая представляет собой совершенно другое животное - и поэтому могут быть определенные ограничения. - person Martin Zeitler; 22.08.2019

Сажа не будет излучать класс, если вы не отметили его как класс приложения. Вы можете это попробовать?

person Community    schedule 27.08.2019
comment
Но я сделал это, спасибо. Похоже, проблема была в пакете класса. - person noidsirius; 28.08.2019

Думаю, я обнаружил, почему недавно созданный класс был неизвестен приложению, благодаря подсказке Мартина Цитлера. Созданный класс должен быть в пакете APK. Soot обрабатывает пакет класса, глядя на сигнатуры класса. В результате класс StaticCounter должен иметь подпись типа

com.example.app.StaticCounter

что означает, что StaticCounter находится в пакете com.example.app.

Имя пакета можно найти с помощью класса ProcessManifest, который можно найти в FlowDroid:

new ProcessManifest(apkPath).getPackageName();

Я упростил рабочий код и поместил его здесь. Он создает новый класс с нуля и добавляет статическое целочисленное поле и метод, в котором указано время, когда статический метод вызывается, и метод печатает это значение. Затем, используя пакет преобразований, каждый метод в приложении будет вызывать этот статический метод.

person noidsirius    schedule 28.08.2019