|
|
|
|
| |
Credit:
The information has been provided by Stephen de Vries.
|
| |
The concept of encrypting Java class files to prevent de-compilition is fundamentally flawed because the Java Virtual Machine (JVM) cannot read encrypted class files. It can only read files which comply with the well defined Java class file format [2]. Therefore, the encrypted class files have to be delivered to the JVM in the standard, unencrypted format. An attacker who wishes to de-compile the class file can simply modify the Java class loader to extract the unencrypted class files [4][5]. These class files can then be decompiled using well known and freely available de-compilation tools such as Jode [3].
Proof of Concept:
The following code[4] was inserted in the defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain) method of the java/lang/ClassLoader.java file which is included in the JDK source code:
if (!name.startsWith("java")) {
String baseDir = "/Users/stephen/dump";
String dirName = baseDir + File.separatorChar + name.substring(0,name.lastIndexOf(".")).replace('.', File.separatorChar);
File dir = new File(dirName);
dir.mkdirs();
File dump = new File(baseDir + File.separatorChar + name.replace('.', File.separatorChar) + ".class");
FileOutputStream out = null;
try {
out = new FileOutputStream (dump);
out.write (b, off, len);
}
catch (Exception e){
e.printStackTrace ();
}
finally {
if (out != null) {
try {
out.close ();
}
catch (Exception e) {
}
}
}
}
This had the effect of writing the class file to a directory. The modified ClassLoader.class file was included in the JVM runtime. The "Game of life" encrypted sample application was then loaded using the new modified JVM. The raw class files were observed in the directory /Users/stephen/dump and these were loaded using Jode [3]. Jode was successful in decompiling many of the important class files to the extent that functional process flow and constant values were exposed. Some local variable names remained in obfuscated form, but these did not detract from the overall ability to view the source code. As an example, the following code is the original source code of the GameOfLifeCanvas constructor as provided with the sample application:
public GameOfLifeCanvas(GameOfLifeGrid gameOfLifeGrid, int cellSize) {
this.gameOfLifeGrid = gameOfLifeGrid;
this.cellSize = cellSize;
gameOfLifeGrid.clear();
addMouseListener(
new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
draw(e.getX(), e.getY());
}
public void mousePressed(MouseEvent e) {
saveCellUnderMouse(e.getX(), e.getY());
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
draw(e.getX(), e.getY());
}
});
}
The same method as decompiled by Jode:
public GameOfLifeCanvas(GameOfLifeGrid gameoflifegrid, int i) {
gameOfLifeGrid = gameoflifegrid;
cellSize = i;
gameoflifegrid.clear();
this.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent mouseevent) {
draw(mouseevent.getX(), mouseevent.getY());
}
public void mousePressed(MouseEvent mouseevent) {
saveCellUnderMouse(mouseevent.getX(), mouseevent.getY());
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent mouseevent) {
draw(mouseevent.getX(), mouseevent.getY());
}
});
}
Recommendations:
Simple class file encryption using a pure Java solution is a fundamentally flawed approach to protecting the intellectual property of software creators, and as this advisory shows it cannot be relied on to provide any protection from reverse engineering methods. As a permanent solution to this issue consider re-architecting Java applications who's bytecode contains sensitive intellectual property so that the sensitive areas are executed in secured environments (such as on a server). Alternatively, consider strengthening the obfuscation mechanisms to delay decompilation of class files. However, it should be noted that obfuscation will not provide a permanent solution to the problem, but will only delay a persistent attacker in obtaining the source code.
CVE Information:
CVE-2007-0014
References:
[1] http://www.chainkey.com/en/jcp/
[2] http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html
[3] http://jode.sourceforge.net
[4] Sergey Edunov's post: http://lists.owasp.org/pipermail/java-project/2006-October/000096.html
[5] http://www.javaworld.com/javaworld/javaqa/2003-05/01-qa-0509-jcrypt.html
|
|
|
|
|