Skip to content

Commit

Permalink
fix(gui): add template for constructor and void methods to Frida snip…
Browse files Browse the repository at this point in the history
…pet (#1714)
  • Loading branch information
skylot committed Nov 7, 2022
1 parent 4aaea2b commit bb4d88c
Showing 1 changed file with 41 additions and 42 deletions.
83 changes: 41 additions & 42 deletions jadx-gui/src/main/java/jadx/gui/ui/codearea/FridaAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import jadx.core.codegen.TypeGen;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.gui.treemodel.JClass;
Expand Down Expand Up @@ -76,45 +75,48 @@ private String generateFridaSnippet(JNode node) {
}

private String generateMethodSnippet(JMethod jMth) {
JavaMethod javaMethod = jMth.getJavaMethod();
MethodInfo methodInfo = javaMethod.getMethodNode().getMethodInfo();
String methodName = StringEscapeUtils.escapeEcmaScript(methodInfo.getName());

MethodNode mth = jMth.getJavaMethod().getMethodNode();
MethodInfo methodInfo = mth.getMethodInfo();
String methodName;
if (methodInfo.isConstructor()) {
methodName = "$init";
} else {
methodName = StringEscapeUtils.escapeEcmaScript(methodInfo.getName());
}

String callMethodName = methodName;
String shortClassName = javaMethod.getDeclaringClass().getName();

String functionUntilImplementation;
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);
String overload;
if (isOverloaded(mth)) {
String overloadArgs = methodInfo.getArgumentsTypes().stream()
.map(this::parseArgType).collect(Collectors.joining(", "));
overload = ".overload(" + overloadArgs + ")";
} else {
functionUntilImplementation = String.format("%s[\"%s\"].implementation", shortClassName, methodName);
overload = "";
}

List<String> methodArgNames = collectMethodArgNames(javaMethod);

String functionParametersString = String.join(", ", methodArgNames);
String logParametersString =
methodArgNames.stream().map(e -> String.format("'%s: ' + %s", e, e)).collect(Collectors.joining(" + ', ' + "));
if (logParametersString.length() > 0) {
logParametersString = " + ', ' + " + logParametersString;
List<String> argNames = collectMethodArgNames(jMth.getJavaMethod());
String args = String.join(", ", argNames);
String logArgs;
if (argNames.isEmpty()) {
logArgs = "";
} else {
String joinStr = " + ', ' + ";
logArgs = joinStr + argNames.stream().map(a -> "'" + a + ": ' + " + a).collect(Collectors.joining(joinStr));
}
String functionParameterAndBody = String.format(
"%s = function (%s) {\n"
+ " console.log('%s is called'%s);\n"
+ " let ret = this.%s(%s);\n"
+ " console.log('%s ret value is ' + ret);\n"
+ " return ret;\n"
+ "};",
functionUntilImplementation, functionParametersString, methodName, logParametersString, callMethodName,
functionParametersString, methodName);

return generateClassSnippet(jMth.getJParent()) + "\n" + functionParameterAndBody;
String shortClassName = mth.getParentClass().getShortName();
String classSnippet = generateClassSnippet(jMth.getJParent());
if (methodInfo.isConstructor() || methodInfo.getReturnType() == ArgType.VOID) {
// no return value
return classSnippet + "\n"
+ shortClassName + "[\"" + methodName + "\"]" + overload + ".implementation = function (" + args + ") {\n"
+ " console.log('" + shortClassName + "." + methodName + " is called'" + logArgs + ");\n"
+ " this[\"" + methodName + "\"](" + args + ");\n"
+ "};";
}
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) {
Expand Down Expand Up @@ -159,27 +161,24 @@ private String generateFieldSnippet(JField jf) {
break;
}
}

JClass jc = jf.getRootClass();
String classSnippet = generateClassSnippet(jc);
return String.format("%s\n%s = %s.%s.value;", classSnippet, fieldName, jc.getName(), rawFieldName);
}

public Boolean isOverloaded(MethodNode methodNode) {
ClassNode parentClass = methodNode.getParentClass();
List<MethodNode> methods = parentClass.getMethods();
return methods.stream()
return methodNode.getParentClass().getMethods().stream()
.anyMatch(m -> m.getName().equals(methodNode.getName())
&& !Objects.equals(methodNode.getMethodInfo().getShortId(), m.getMethodInfo().getShortId()));
}

private String parseArgType(ArgType x) {
StringBuilder parsedArgType = new StringBuilder("'");
String typeStr;
if (x.isArray()) {
parsedArgType.append(TypeGen.signature(x).replace("/", "."));
typeStr = TypeGen.signature(x).replace("/", ".");
} else {
parsedArgType.append(x);
typeStr = x.toString();
}
return parsedArgType.append("'").toString();
return "'" + typeStr + "'";
}
}

0 comments on commit bb4d88c

Please sign in to comment.