未验证 提交 bb4d88cc 编写于 作者: S Skylot

fix(gui): add template for constructor and void methods to Frida snippet (#1714)

上级 4aaea2b9
...@@ -23,7 +23,6 @@ import jadx.api.utils.CodeUtils; ...@@ -23,7 +23,6 @@ import jadx.api.utils.CodeUtils;
import jadx.core.codegen.TypeGen; import jadx.core.codegen.TypeGen;
import jadx.core.dex.info.MethodInfo; import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.gui.treemodel.JClass; import jadx.gui.treemodel.JClass;
...@@ -76,45 +75,48 @@ public final class FridaAction extends JNodeAction { ...@@ -76,45 +75,48 @@ public final class FridaAction extends JNodeAction {
} }
private String generateMethodSnippet(JMethod jMth) { private String generateMethodSnippet(JMethod jMth) {
JavaMethod javaMethod = jMth.getJavaMethod(); MethodNode mth = jMth.getJavaMethod().getMethodNode();
MethodInfo methodInfo = javaMethod.getMethodNode().getMethodInfo(); MethodInfo methodInfo = mth.getMethodInfo();
String methodName = StringEscapeUtils.escapeEcmaScript(methodInfo.getName()); String methodName;
if (methodInfo.isConstructor()) { if (methodInfo.isConstructor()) {
methodName = "$init"; methodName = "$init";
} else {
methodName = StringEscapeUtils.escapeEcmaScript(methodInfo.getName());
} }
String overload;
String callMethodName = methodName; if (isOverloaded(mth)) {
String shortClassName = javaMethod.getDeclaringClass().getName(); String overloadArgs = methodInfo.getArgumentsTypes().stream()
.map(this::parseArgType).collect(Collectors.joining(", "));
String functionUntilImplementation; overload = ".overload(" + overloadArgs + ")";
if (isOverloaded(javaMethod.getMethodNode())) {
List<ArgType> methodArgs = methodInfo.getArgumentsTypes();
String overloadStr = methodArgs.stream().map(this::parseArgType).collect(Collectors.joining(", "));
functionUntilImplementation = String.format("%s[\"%s\"].overload(%s).implementation", shortClassName, methodName, overloadStr);
} else { } else {
functionUntilImplementation = String.format("%s[\"%s\"].implementation", shortClassName, methodName); overload = "";
} }
List<String> argNames = collectMethodArgNames(jMth.getJavaMethod());
List<String> methodArgNames = collectMethodArgNames(javaMethod); String args = String.join(", ", argNames);
String logArgs;
String functionParametersString = String.join(", ", methodArgNames); if (argNames.isEmpty()) {
String logParametersString = logArgs = "";
methodArgNames.stream().map(e -> String.format("'%s: ' + %s", e, e)).collect(Collectors.joining(" + ', ' + ")); } else {
if (logParametersString.length() > 0) { String joinStr = " + ', ' + ";
logParametersString = " + ', ' + " + logParametersString; logArgs = joinStr + argNames.stream().map(a -> "'" + a + ": ' + " + a).collect(Collectors.joining(joinStr));
} }
String functionParameterAndBody = String.format( String shortClassName = mth.getParentClass().getShortName();
"%s = function (%s) {\n" String classSnippet = generateClassSnippet(jMth.getJParent());
+ " console.log('%s is called'%s);\n" if (methodInfo.isConstructor() || methodInfo.getReturnType() == ArgType.VOID) {
+ " let ret = this.%s(%s);\n" // no return value
+ " console.log('%s ret value is ' + ret);\n" return classSnippet + "\n"
+ " return ret;\n" + shortClassName + "[\"" + methodName + "\"]" + overload + ".implementation = function (" + args + ") {\n"
+ "};", + " console.log('" + shortClassName + "." + methodName + " is called'" + logArgs + ");\n"
functionUntilImplementation, functionParametersString, methodName, logParametersString, callMethodName, + " this[\"" + methodName + "\"](" + args + ");\n"
functionParametersString, methodName); + "};";
}
return generateClassSnippet(jMth.getJParent()) + "\n" + functionParameterAndBody; return classSnippet + "\n"
+ shortClassName + "[\"" + methodName + "\"]" + overload + ".implementation = function (" + args + ") {\n"
+ " console.log('" + shortClassName + "." + methodName + " is called'" + logArgs + ");\n"
+ " let ret = this[\"" + methodName + "\"](" + args + ");\n"
+ " console.log('" + shortClassName + "." + methodName + " return: ' + ret);\n"
+ " return ret;\n"
+ "};";
} }
private List<String> collectMethodArgNames(JavaMethod javaMethod) { private List<String> collectMethodArgNames(JavaMethod javaMethod) {
...@@ -159,27 +161,24 @@ public final class FridaAction extends JNodeAction { ...@@ -159,27 +161,24 @@ public final class FridaAction extends JNodeAction {
break; break;
} }
} }
JClass jc = jf.getRootClass(); JClass jc = jf.getRootClass();
String classSnippet = generateClassSnippet(jc); String classSnippet = generateClassSnippet(jc);
return String.format("%s\n%s = %s.%s.value;", classSnippet, fieldName, jc.getName(), rawFieldName); return String.format("%s\n%s = %s.%s.value;", classSnippet, fieldName, jc.getName(), rawFieldName);
} }
public Boolean isOverloaded(MethodNode methodNode) { public Boolean isOverloaded(MethodNode methodNode) {
ClassNode parentClass = methodNode.getParentClass(); return methodNode.getParentClass().getMethods().stream()
List<MethodNode> methods = parentClass.getMethods();
return methods.stream()
.anyMatch(m -> m.getName().equals(methodNode.getName()) .anyMatch(m -> m.getName().equals(methodNode.getName())
&& !Objects.equals(methodNode.getMethodInfo().getShortId(), m.getMethodInfo().getShortId())); && !Objects.equals(methodNode.getMethodInfo().getShortId(), m.getMethodInfo().getShortId()));
} }
private String parseArgType(ArgType x) { private String parseArgType(ArgType x) {
StringBuilder parsedArgType = new StringBuilder("'"); String typeStr;
if (x.isArray()) { if (x.isArray()) {
parsedArgType.append(TypeGen.signature(x).replace("/", ".")); typeStr = TypeGen.signature(x).replace("/", ".");
} else { } else {
parsedArgType.append(x); typeStr = x.toString();
} }
return parsedArgType.append("'").toString(); return "'" + typeStr + "'";
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册