Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add an option to generate kotlin code for xposed #2070

Merged
merged 4 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public class JadxSettings extends JadxCLIArgs {

private static final Path USER_HOME = Paths.get(System.getProperty("user.home"));
private static final int RECENT_PROJECTS_COUNT = 30;
private static final int CURRENT_SETTINGS_VERSION = 18;
private static final int CURRENT_SETTINGS_VERSION = 19;

private static final Font DEFAULT_FONT = new RSyntaxTextArea().getFont();

Expand Down Expand Up @@ -110,6 +110,8 @@ public class JadxSettings extends JadxCLIArgs {

private boolean jumpOnDoubleClick = true;

private XposedCodegenLanguage xposedCodegenLanguage = XposedCodegenLanguage.JAVA;

/**
* UI setting: the width of the tree showing the classes, resources, ...
*/
Expand Down Expand Up @@ -732,6 +734,14 @@ public void setDockLogViewer(boolean dockLogViewer) {
partialSync(settings -> this.dockLogViewer = dockLogViewer);
}

public XposedCodegenLanguage getXposedCodegenLanguage() {
return xposedCodegenLanguage;
}

public void setXposedCodegenLanguage(XposedCodegenLanguage language) {
this.xposedCodegenLanguage = language;
}

private void upgradeSettings(int fromVersion) {
LOG.debug("upgrade settings from version: {} to {}", fromVersion, CURRENT_SETTINGS_VERSION);
if (fromVersion <= 10) {
Expand Down Expand Up @@ -769,6 +779,10 @@ private void upgradeSettings(int fromVersion) {
checkForUpdates = true;
fromVersion++;
}
if (fromVersion == 18) {
xposedCodegenLanguage = XposedCodegenLanguage.JAVA;
fromVersion++;
}
if (fromVersion != CURRENT_SETTINGS_VERSION) {
LOG.warn("Incorrect settings upgrade. Expected version: {}, got: {}", CURRENT_SETTINGS_VERSION, fromVersion);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package jadx.gui.settings

enum class XposedCodegenLanguage {
JAVA,
KOTLIN,
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import jadx.gui.settings.JadxSettings;
import jadx.gui.settings.JadxSettingsAdapter;
import jadx.gui.settings.LineNumbersMode;
import jadx.gui.settings.XposedCodegenLanguage;
import jadx.gui.settings.ui.cache.CacheSettingsGroup;
import jadx.gui.settings.ui.plugins.PluginSettings;
import jadx.gui.settings.ui.shortcut.ShortcutsSettingsGroup;
Expand Down Expand Up @@ -622,13 +623,22 @@ private SettingsGroup makeOtherGroup() {
needReload();
});

JComboBox<XposedCodegenLanguage> xposedCodegenLanguage =
new JComboBox<>(XposedCodegenLanguage.getEntries().toArray(new XposedCodegenLanguage[0]));
xposedCodegenLanguage.setSelectedItem(settings.getXposedCodegenLanguage());
xposedCodegenLanguage.addActionListener(e -> {
settings.setXposedCodegenLanguage((XposedCodegenLanguage) xposedCodegenLanguage.getSelectedItem());
mainWindow.loadSettings();
});

SettingsGroup group = new SettingsGroup(NLS.str("preferences.other"));
group.addRow(NLS.str("preferences.lineNumbersMode"), lineNumbersMode);
group.addRow(NLS.str("preferences.jumpOnDoubleClick"), jumpOnDoubleClick);
group.addRow(NLS.str("preferences.useAlternativeFileDialog"), useAltFileDialog);
group.addRow(NLS.str("preferences.check_for_updates"), update);
group.addRow(NLS.str("preferences.cfg"), cfg);
group.addRow(NLS.str("preferences.raw_cfg"), rawCfg);
group.addRow(NLS.str("preferences.xposed_codegen_language"), xposedCodegenLanguage);
return group;
}

Expand Down
95 changes: 81 additions & 14 deletions jadx-gui/src/main/java/jadx/gui/ui/codearea/XposedAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.gui.settings.XposedCodegenLanguage;
import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JField;
import jadx.gui.treemodel.JMethod;
Expand Down Expand Up @@ -85,16 +86,40 @@ private String generateMethodSnippet(JMethod jMth) {
methodName = "\"" + mth.getMethodInfo().getName() + "\", ";
}
String rawClassName = javaMethod.getDeclaringClass().getRawName();
String xposedFormatStr = "XposedHelpers.%s(\"%s\", classLoader, %snew XC_MethodHook() {\n"
+ " @Override\n"
+ " protected void beforeHookedMethod(MethodHookParam param) throws Throwable {\n"
+ " super.beforeHookedMethod(param);\n"
+ " }\n"
+ " @Override\n"
+ " protected void afterHookedMethod(MethodHookParam param) throws Throwable {\n"
+ " super.afterHookedMethod(param);\n"
+ " }\n"
+ "});";
String javaXposedFormatStr =
"XposedHelpers.%s(\"%s\", classLoader, %snew XC_MethodHook() {\n"
+ " @Override\n"
+ " protected void beforeHookedMethod(MethodHookParam param) throws Throwable {\n"
+ " super.beforeHookedMethod(param);\n"
+ " }\n"
+ " @Override\n"
+ " protected void afterHookedMethod(MethodHookParam param) throws Throwable {\n"
+ " super.afterHookedMethod(param);\n"
+ " }\n"
+ "});";
String kotlinXposedFormatStr =
"XposedHelpers.%s(\"%s\", classLoader, %sobject : XC_MethodHook() {\n"
+ " override fun beforeHookedMethod(param: MethodHookParam) {\n"
+ " super.beforeHookedMethod(param)\n"
+ " }\n"
+ "\n"
+ " override fun afterHookedMethod(param: MethodHookParam) {\n"
+ " super.afterHookedMethod(param)\n"
+ " }\n"
+ "})";

XposedCodegenLanguage language = getLanguage();
String xposedFormatStr;
switch (language) {
case JAVA:
xposedFormatStr = javaXposedFormatStr;
break;
case KOTLIN:
xposedFormatStr = kotlinXposedFormatStr;
break;
default:
throw new JadxRuntimeException("Invalid Xposed code generation language: " + language);
}

List<ArgType> mthArgs = mth.getArgTypes();
if (mthArgs.isEmpty()) {
Expand All @@ -119,16 +144,58 @@ private String generateClassSnippet(JClass jc) {
JavaClass javaClass = jc.getCls();
String rawClassName = javaClass.getRawName();
String shortClassName = javaClass.getName();
return String.format("ClassLoader classLoader = lpparam.classLoader;\n"
+ "Class<?> %sClass = classLoader.loadClass(\"%s\");",
shortClassName, rawClassName);

String javaXposedFormatStr =
"ClassLoader classLoader = lpparam.classLoader;\n"
+ "Class<?> %sClass = classLoader.loadClass(\"%s\");";
String kotlinXposedFormatStr =
"val classLoader = lpparam.classLoader\n"
+ "val %sClass = classLoader.loadClass(\"%s\")";

XposedCodegenLanguage language = getLanguage();
String xposedFormatStr;
switch (language) {
case JAVA:
xposedFormatStr = javaXposedFormatStr;
break;
case KOTLIN:
xposedFormatStr = kotlinXposedFormatStr;
break;
default:
throw new JadxRuntimeException("Invalid Xposed code generation language: " + language);
}

return String.format(xposedFormatStr, shortClassName, rawClassName);
}

private String generateFieldSnippet(JField jf) {
JavaField javaField = jf.getJavaField();
String isStatic = javaField.getAccessFlags().isStatic() ? "Static" : "";
String type = PRIMITIVE_TYPE_MAPPING.getOrDefault(javaField.getFieldNode().getType().toString(), "Object");
String xposedMethod = "XposedHelpers.get" + isStatic + type + "Field";
return String.format("%s(/*runtimeObject*/, \"%s\");", xposedMethod, javaField.getFieldNode().getFieldInfo().getName());

String javaXposedFormatStr =
"%s(/*runtimeObject*/, \"%s\");";
String kotlinXposedFormatStr =
"%s(/*runtimeObject*/, \"%s\")";

XposedCodegenLanguage language = getLanguage();
String xposedFormatStr;
switch (language) {
case JAVA:
xposedFormatStr = javaXposedFormatStr;
break;
case KOTLIN:
xposedFormatStr = kotlinXposedFormatStr;
break;
default:
throw new JadxRuntimeException("Invalid Xposed code generation language: " + language);
}

return String.format(xposedFormatStr, xposedMethod, javaField.getFieldNode().getFieldInfo().getName());
}

private XposedCodegenLanguage getLanguage() {
return getCodeArea().getMainWindow().getSettings().getXposedCodegenLanguage();
}
}
1 change: 1 addition & 0 deletions jadx-gui/src/main/resources/i18n/Messages_de_DE.properties
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ preferences.excludedPackages.button=Bearbeiten
preferences.excludedPackages.editDialog=<html>Liste der durch Leerzeichen getrennten Paketnamen, die nicht dekompiliert oder indiziert werden. (spart RAM)<br>z.B. <code>android.support</code></html>
preferences.cfg=CFG-Grafiken für Methoden generieren (im 'dot'-Format)
preferences.raw_cfg=RAW CFG-Grafiken generieren
#preferences.xposed_codegen_language=Xposed code generation language
#preferences.integerFormat=Integer format
preferences.font=Schrift ändern
#preferences.smali_font=
Expand Down
1 change: 1 addition & 0 deletions jadx-gui/src/main/resources/i18n/Messages_en_US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ preferences.excludedPackages.button=Edit
preferences.excludedPackages.editDialog=<html>List of space separated package names that will not be decompiled or indexed (saves RAM)<br>e.g. <code>android.support</code></html>
preferences.cfg=Generate methods CFG graphs (in 'dot' format)
preferences.raw_cfg=Generate RAW CFG graphs
preferences.xposed_codegen_language=Xposed code generation language
preferences.integerFormat=Integer format
preferences.font=Editor font
preferences.smali_font=Monospaced font (Smali/Hex)
Expand Down
1 change: 1 addition & 0 deletions jadx-gui/src/main/resources/i18n/Messages_es_ES.properties
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ preferences.threads=Número de hilos a procesar
#preferences.excludedPackages.editDialog=
preferences.cfg=Generar methods CFG graphs (in 'dot' format)
preferences.raw_cfg=Generate RAW CFG graphs
#preferences.xposed_codegen_language=Xposed code generation language
#preferences.integerFormat=Integer format
preferences.font=Fuente del editor
#preferences.smali_font=
Expand Down
1 change: 1 addition & 0 deletions jadx-gui/src/main/resources/i18n/Messages_id_ID.properties
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ preferences.excludedPackages.button=Edit
preferences.excludedPackages.editDialog=<html>Daftar nama paket yang dipisahkan spasi yang tidak akan di deskompilasi atau diindeks (menghemat RAM)<br>contoh: <code>android.support</code></html>
preferences.cfg=Hasilkan grafik CFG metode (dalam format 'dot')
preferences.raw_cfg=Hasilkan grafik CFG mentah
#preferences.xposed_codegen_language=Xposed code generation language
preferences.integerFormat=Format bilangan bulat
preferences.font=Font editor
preferences.smali_font=Font monospasi (Smali/Hex)
Expand Down
1 change: 1 addition & 0 deletions jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ preferences.excludedPackages.button=Edit
preferences.excludedPackages.editDialog=<html>RAM 절약을 위해 디컴파일되거나 인덱싱하지 않을 패키지 이름 목록 (공백으로 항목 구분)<br>예: <code>android.support</code></html>
preferences.cfg=메소드 CFG 그래프 생성 ('dot' 포맷)
preferences.raw_cfg=RAW CFG 그래프 생성
#preferences.xposed_codegen_language=Xposed code generation language
#preferences.integerFormat=Integer format
preferences.font=에디터 글씨체
#preferences.smali_font=
Expand Down
1 change: 1 addition & 0 deletions jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ preferences.excludedPackages.button=Editar
preferences.excludedPackages.editDialog=<html>Lista espaço de pacotes que não vão ser descompilados ou indexados (economiza RAM)<br>ex: <code>android.support</code></html>
preferences.cfg=Gera gráficos de métodos CFG no formato de pontos ('dot')
preferences.raw_cfg=Gera gráficos CFG no formato RAW
#preferences.xposed_codegen_language=Xposed code generation language
#preferences.integerFormat=Integer format
preferences.font=Fonte do editor
#preferences.smali_font=
Expand Down
1 change: 1 addition & 0 deletions jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ preferences.excludedPackages.button=Изменить
preferences.excludedPackages.editDialog=<html>Список пакетов, которые не будут декомпилироваться и индексироваться (экономит ОЗУ)<br>например: <code>android.support</code><br>Разделитель - одинарный пробел</html>
preferences.cfg=Методы генерации графиков CFG (в "dot" формате)
preferences.raw_cfg=Генерировать необработанные графики CFG
#preferences.xposed_codegen_language=Xposed code generation language
#preferences.integerFormat=Integer format
preferences.font=Шрифт редактора Java
#preferences.smali_font=
Expand Down
1 change: 1 addition & 0 deletions jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ preferences.excludedPackages.button=编辑
preferences.excludedPackages.editDialog=<html>排除于反编译或索引的以空格分隔的包名列表(节省 RAM)<br>例如<code>android.support</code></html>
preferences.cfg=生成方法的 CFG 图('.dot')
preferences.raw_cfg=生成原始的 CFG 图
#preferences.xposed_codegen_language=Xposed code generation language
preferences.integerFormat=数值格式化
preferences.font=编辑器字体
preferences.smali_font=等宽字体 (Smali/Hex)
Expand Down
1 change: 1 addition & 0 deletions jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ preferences.excludedPackages.button=編輯
preferences.excludedPackages.editDialog=<html>排除於索引或反編譯外的套件列表 (以空格分隔) (節省 RAM) <br>例如 <code>android.support</code></html>
preferences.cfg=產生方法 CFG 圖表 ('dot' 格式)
preferences.raw_cfg=產生 RAW CFG 圖表
#preferences.xposed_codegen_language=Xposed code generation language
preferences.integerFormat=整數模式
preferences.font=編輯器字型
preferences.smali_font=等寬字型 (Smali/Hex)
Expand Down