Last active
September 5, 2016 13:55
-
-
Save DinisCruz/cb434226ae7e974e7cfe3ea7f1c890bd to your computer and use it in GitHub Desktop.
javap helper to quickly extract list of methods called from method
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ....appsec.utils; | |
import java.io.PrintWriter; | |
import java.io.StringWriter; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
public class JavapHelper { | |
public Class target; | |
public JavapHelper(Class clazz) | |
{ | |
target = clazz; | |
} | |
public String pathToClass() | |
{ | |
return this.target.getResource("/" + this.target.getName().replace(".","/") + ".class").toString(); | |
} | |
/** | |
* returns the result of javap with option -v on the provided class | |
*/ | |
public String decompileClass() { | |
String path = this.pathToClass(); // full path to class to map | |
String[] args = new String[] {"-v", path}; // trigger javap -v option | |
StringWriter stringWriter = new StringWriter(); // create StringWritter | |
PrintWriter printWriter = new PrintWriter(stringWriter); // for PrintWriter | |
com.sun.tools.javap.Main.run(args, printWriter); // that is used by the javap main.run method | |
printWriter.close(); | |
return stringWriter.toString(); // get result as string | |
} | |
/** | |
* returns class contant pool values as hashmap | |
*/ | |
public HashMap<String,List<String>> constantPool() | |
{ | |
String rawData = this.decompileClass(); | |
String[] lines = rawData.split("\n"); | |
HashMap<String,List<String>> results = new HashMap<String,List<String>>(); | |
boolean insideConstantPool = false; | |
for (String line :lines) { | |
if(line.equals("Constant pool:")) // start of Constant pool data | |
{ | |
System.out.println(line); | |
insideConstantPool = true; | |
continue; | |
} | |
if(insideConstantPool) | |
{ | |
if (line.equals("{")) | |
break; | |
String[] data = line.split("=",2) // extract the data to the right of the first = | |
[1].trim() // [0] is the id [1] is the rest of the line | |
.split(" ", 2); // split the constant pool name and its value | |
if (data.length == 2) { | |
String key = data[0]; // constant pool name | |
String value = data[1]; // constant pool value | |
if (!results.containsKey(key)) // if it is the first time we see this key | |
results.put(key, new ArrayList<>()); | |
results.get(key).add(value.trim()); // add key's value to key's list<String> | |
} | |
} | |
} | |
return results; | |
} | |
/** | |
* returns list of methodsRef found in constant pool (these are the methods called by class' methods | |
*/ | |
public List<String> methodRefs() | |
{ | |
ArrayList<String> methodRefs = new ArrayList<>(); | |
HashMap<String,List<String>> constantPool = this.constantPool(); | |
for(String entry : constantPool.get("Methodref")) // for each methodRef | |
{ | |
String[] items = entry.split("//", 2); // split by comment | |
methodRefs.add(items[1].trim()); // use the right-hand side | |
} | |
return methodRefs; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ....appsec.utils; | |
import org.junit.Before; | |
import org.junit.Test; | |
import java.util.HashMap; | |
import java.util.List; | |
import static org.hamcrest.CoreMatchers.*; | |
import static org.hamcrest.MatcherAssert.assertThat; | |
import static org.hamcrest.Matchers.greaterThan; | |
public class JavapHelperTest { | |
JavapHelper javapHelper = null; | |
Class target = null; | |
@Before | |
public void beforeClass() | |
{ | |
target = JavapHelper.class; | |
javapHelper = new JavapHelper(target); | |
} | |
@Test | |
public void pathToClass() | |
{ | |
String result = javapHelper.pathToClass(); | |
assertThat(result, containsString(".../appsec/utils/JavapHelper.class")); | |
} | |
@Test | |
public void decompileTest() { | |
String result = javapHelper.decompileClass(); | |
assertThat(result, containsString("public java.lang.String decompileClass();")); | |
assertThat(result, containsString("13: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;")); | |
} | |
@Test | |
public void constantPool() throws Exception { | |
HashMap<String,List<String>> result = javapHelper.constantPool(); | |
assertThat(result.keySet().toArray(), is(new String[] { "Methodref", "Fieldref", "Utf8", "NameAndType", "Class", "String", "InterfaceMethodref"})); | |
} | |
@Test | |
public void methodsRefs() throws Exception { | |
List<String> result = javapHelper.methodRefs(); | |
assertThat(result.size(), greaterThan(10)); | |
assertThat(result, hasItem("java/lang/Object.\"<init>\":()V")); | |
assertThat(result, hasItem("java/lang/StringBuilder.\"<init>\":()V")); | |
assertThat(result, hasItem("java/lang/Class.getResource:(Ljava/lang/String;)Ljava/net/URL;")); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment