Java Class Unpacker v0.6.0 released.
Plugin for Total Commander
Changes:
- fixed: abstract classes and methods
- added constant pool
- implemented decompilation of tableswitch and lookupswitch
- file offsets and hexa bytes in code
- renamed file to JavaClassUnpacker.wcx
Download: http://cid-511e6cc6d535b08d.skydrive.live.com/self.aspx/JavaClassUnpacker
Cheers,
Lula
Friday, November 27, 2009
Java Class Unpacker v0.6.0
Etiquetas:
bytecode,
java,
plugin,
total commander
Thursday, November 26, 2009
New Total Commander Plugin - Java Class Unpacker v0.5.0
I developed a new plugin for the amazing Total Commander. Using this plugin you can enter to class files as compressed files and see fields and methods as files.
Methods can be viewed using F3, the java bytecode is displayed as text.
I have no site so I uploaded to megaupload, you can download it from:
http://www.megaupload.com/?d=8BW30ZAD
Please feel free to send me bugs, comments or suggestions.
Enjoy!
Methods can be viewed using F3, the java bytecode is displayed as text.
I have no site so I uploaded to megaupload, you can download it from:
http://www.megaupload.com/?d=8BW30ZAD
Please feel free to send me bugs, comments or suggestions.
Enjoy!
Friday, November 13, 2009
J2ME: Fixing Cannot find class java/lang/NoClassDefFoundError at preverify
I had a strange error when preverifying a midlet.
[exec] Error preverifying class temp.TestMidlet
[exec] VERIFIER ERROR temp/TestMidlet.()V:
[exec] Cannot find class java/lang/NoClassDefFoundError
The midlet is ok, Eclipse doesn't display an error. Searching in all the library jars in WTK I found the class NoClassDefFoundError is inside cldcapi11.jar. I modified the cldc jar and nows compiles.
But is not enough for me, I'm not using float or doubles so I want to compile the midlet for CLDC10. So I continued playing and I found the reason: I'm using the field named "class" to obtain the name of a class.
E.g:
To obtain the Class object of class TestMidlet I'm using the following code:
Class clazz = TestMidlet.class;
this is ok for CLDC11 but for CLDC10 is wrong, I must use this.getClass or something similar.
I hope you can find this useful.
Cheers,
Lula
[exec] Error preverifying class temp.TestMidlet
[exec] VERIFIER ERROR temp/TestMidlet.
[exec] Cannot find class java/lang/NoClassDefFoundError
The midlet is ok, Eclipse doesn't display an error. Searching in all the library jars in WTK I found the class NoClassDefFoundError is inside cldcapi11.jar. I modified the cldc jar and nows compiles.
But is not enough for me, I'm not using float or doubles so I want to compile the midlet for CLDC10. So I continued playing and I found the reason: I'm using the field named "class" to obtain the name of a class.
E.g:
To obtain the Class object of class TestMidlet I'm using the following code:
Class clazz = TestMidlet.class;
this is ok for CLDC11 but for CLDC10 is wrong, I must use this.getClass or something similar.
I hope you can find this useful.
Cheers,
Lula
All mobile developer sites
Just for reference, I'm writing here all developer sites useful for mobile frikis:
Java Mobile
http://developers.sun.com/mobility
Sony
http://developer.sonyericsson.com
Motorola
http://developer.motorola.com
Nokia
http://www.nokia.com/developers
Samsung
http://innovator.samsungmobile.com
IPhone
http://developer.apple.com/iphone
Android
http://developer.android.com
Blackberry
http://na.blackberry.com/eng/developers
BREW
http://brew.qualcomm.com/brew/en/developer/overview.html
HTC
http://developer.htc.com
Windows Mobile
http://developer.windowsmobile.com
http://msdn.microsoft.com/en-us/windowsmobile/default.aspx
OpenGL ES
http://www.khronos.org/opengles
Let's go mobile!
Cheers,
Lula
Java Mobile
http://developers.sun.com/mobility
Sony
http://developer.sonyericsson.com
Motorola
http://developer.motorola.com
Nokia
http://www.nokia.com/developers
Samsung
http://innovator.samsungmobile.com
IPhone
http://developer.apple.com/iphone
Android
http://developer.android.com
Blackberry
http://na.blackberry.com/eng/developers
BREW
http://brew.qualcomm.com/brew/en/developer/overview.html
HTC
http://developer.htc.com
Windows Mobile
http://developer.windowsmobile.com
http://msdn.microsoft.com/en-us/windowsmobile/default.aspx
OpenGL ES
http://www.khronos.org/opengles
Let's go mobile!
Cheers,
Lula
Tuesday, November 10, 2009
Convert Android DEX to Java
I'm playing with a great Android to Java converter named UnDX. You can find it at
http://www.illegalaccess.org/undx
it uses BCEL to convert the files. It's in beta, has some errors.
So, I decided to create my own converter using ASM. The idea is simple:
- Create a DEX reader extending ClassReader. Here call all the Visitor events to generate the java code.
- Use ASM to manipulate the java bytecode.
- Create a DEX ClassWriter. It must be exactly the same for java, but after generating all the bytearrays it must use dx command to create de DEX file.
The idea is simple, I had some tests and it works! I'm generating the java code and I can manipulate it.
I'll tell you later what happens with some big DEX files.
Cheers,
Lula
http://www.illegalaccess.org/undx
it uses BCEL to convert the files. It's in beta, has some errors.
So, I decided to create my own converter using ASM. The idea is simple:
- Create a DEX reader extending ClassReader. Here call all the Visitor events to generate the java code.
- Use ASM to manipulate the java bytecode.
- Create a DEX ClassWriter. It must be exactly the same for java, but after generating all the bytearrays it must use dx command to create de DEX file.
The idea is simple, I had some tests and it works! I'm generating the java code and I can manipulate it.
I'll tell you later what happens with some big DEX files.
Cheers,
Lula
Thursday, November 5, 2009
How to manipulate bytecode in android
The following was tested successfully in Android SDK 1.1 and 2.0
Step 1: Create an android project in eclipse
Step 2: open the activity class and change the event onCreate with the following
boolean flag = false;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
if(flag){
tv.setText("CONGRATS! YOU CRACKED MY CODE! ;)");
} else{
tv.setText("NOT CRACKED YET... :(");
}
setContentView(tv);
}
Check the new variable named flag, it is our main objective.
Step 3: run the project in the emulator, you will see a screen showing the text "NOT CRACKED YET... :("
Step 4: go to the folder YOUR_PROJECT\bin and remove the signature from the APK file. If you don't know how to do it read my previous entry here
Step 5
/**
* Calculates the checksum for the
* given array, and modify the array to contain it.
*
* @param bytes non-null; the bytes of the file
*/
private static void calcChecksum(byte[] bytes) {
Adler32 a32 = new Adler32();
a32.update(bytes, 12, bytes.length - 12);
int sum = (int) a32.getValue();
bytes[8] = (byte) sum;
bytes[9] = (byte) (sum >> 8);
bytes[10] = (byte) (sum >> 16);
bytes[11] = (byte) (sum >> 24);
}
public static void main(String[] args) {
try {
File file = new File(args[0]);
FileInputStream fis = new FileInputStream(file);
byte[] data = new byte[fis.available()];
System.out.println("Reading DEX file");
fis.read(data);
System.out.println("Calculating new checksum");
calcChecksum(data);
fis.close();
System.out.println("Making backup");
file.renameTo(new File(args[0]+".bak"));
System.out.println("Writing new DEX file with checksum "+ Integer.toHexString(data[8]) +" "+ Integer.toHexString(data[9]) +" "+ Integer.toHexString(data[10]) +" "+ Integer.toHexString(data[11]));
FileOutputStream fos = new FileOutputStream(new File(args[0]));
fos.write(data);
fos.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I know it is a very small program and we know how the code works, but this is useful to see what can be done with bytecode manipulation.
Removing bytecode is not so simple, but you can try replacing the bytecode values in the lines you want to remove by zeros 00, it is the NOP bytecode.
Injecting bytecode is another story, lots of offsets must be modified in the classes.dex file. I will tell you later.
And I will test this in SDK 1.5, 1.6, but another day, i'm tired now :)
Enjoy!
Step 1: Create an android project in eclipse
Step 2: open the activity class and change the event onCreate with the following
boolean flag = false;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
if(flag){
tv.setText("CONGRATS! YOU CRACKED MY CODE! ;)");
} else{
tv.setText("NOT CRACKED YET... :(");
}
setContentView(tv);
}
Check the new variable named flag, it is our main objective.
Step 3: run the project in the emulator, you will see a screen showing the text "NOT CRACKED YET... :("
Step 4: go to the folder YOUR_PROJECT\bin and remove the signature from the APK file. If you don't know how to do it read my previous entry here
Step 5
- disassemble the file classes.dex. If you don't know how to do it read my previous entry here.
- Search the text "onCreate" to find the body of the onCreate method. You will find something like this:
Virtual methods -
#0 : (in La/a/Start;)
name : 'onCreate'
type : '(Landroid/os/Bundle;)V'
access : 0x0001 (PUBLIC)
code -
registers : 4
ins : 2
outs : 2
insns size : 27 16-bit code units
0003c4: |[0003c4] a.a.Start.onCreate:(Landroid/os/Bundle;)V
0003d4: 6f20 0900 3200 |0000: invoke-super {v2, v3}, Landroid/app/Activity;.onCreate:(Landroid/os/Bundle;)V // method@0009
0003da: 2200 0b00 |0003: new-instance v0, Landroid/widget/TextView; // class@000b
0003de: 7020 0a00 2000 |0005: invoke-direct {v0, v2}, Landroid/widget/TextView;.:(Landroid/content/Context;)V // method@000a
0003e4: 5521 0400 |0008: iget-boolean v1, v2, La/a/Start;.flag:Z // field@0004
0003e8: 3801 0b00 |000a: if-eqz v1, 0015 // +000b
0003ec: 1a01 0100 |000c: const-string v1, "CONGRATS! YOU CRACKED MY CODE! ;)" // string@0001
0003f0: 6e20 0b00 1000 |000e: invoke-virtual {v0, v1}, Landroid/widget/TextView;.setText:(Ljava/lang/CharSequence;)V // method@000b
0003f6: 6e20 0700 0200 |0011: invoke-virtual {v2, v0}, La/a/Start;.setContentView:(Landroid/view/View;)V // method@0007
0003fc: 0e00 |0014: return-void
0003fe: 1a01 1300 |0015: const-string v1, "NOT CRACKED YET... :(" // string@0013
000402: 6e20 0b00 1000 |0017: invoke-virtual {v0, v1}, Landroid/widget/TextView;.setText:(Ljava/lang/CharSequence;)V // method@000b
000408: 28f7 |001a: goto 0011 // -0009
catches : (none)
positions :
0x0000 line=15
0x0003 line=16
0x0008 line=17
0x000c line=18
0x0011 line=22
0x0014 line=23
0x0015 line=20
locals :
0x0008 - 0x001b reg=0 tv Landroid/widget/TextView;
0x0000 - 0x001b reg=2 this La/a/Start;
0x0000 - 0x001b reg=3 savedInstanceState Landroid/os/Bundle;
You need to understand how bytecode works. If you don't have any experience with bytecode manipulation please stop here.
- I marked in red the line we want to change, because it is a jump that involves the lines of code showing texts. We must invert the jump so the screen will display another text.
- edit in hexadecimal the file classes.dex and go to the offset 03E8, you will se the hex numbers 38 01 0b 00
Why? Check the following line:
0003e8: 3801 0b00 |000a: if-eqz v1, 0015 // +000b
the first number is the offset in the classes.dex file, the following numbers are the opcode and parameters.
If you check the opcode numbers HERE you can see the value 0x38 is for the opcode if-eqz, we must change this opcode to if-nez to invert the jump. Checking the opcodes list we see the value for if-nez is 0x39, so change the 38 value at offset 0x3E8 by 39
- Now you must fix the checksum or you will have errors when installing the app. You can calculate the checksum with the following code:
/**
* Calculates the checksum for the
.dex
file in the* given array, and modify the array to contain it.
*
* @param bytes non-null; the bytes of the file
*/
private static void calcChecksum(byte[] bytes) {
Adler32 a32 = new Adler32();
a32.update(bytes, 12, bytes.length - 12);
int sum = (int) a32.getValue();
bytes[8] = (byte) sum;
bytes[9] = (byte) (sum >> 8);
bytes[10] = (byte) (sum >> 16);
bytes[11] = (byte) (sum >> 24);
}
public static void main(String[] args) {
try {
File file = new File(args[0]);
FileInputStream fis = new FileInputStream(file);
byte[] data = new byte[fis.available()];
System.out.println("Reading DEX file");
fis.read(data);
System.out.println("Calculating new checksum");
calcChecksum(data);
fis.close();
System.out.println("Making backup");
file.renameTo(new File(args[0]+".bak"));
System.out.println("Writing new DEX file with checksum "+ Integer.toHexString(data[8]) +" "+ Integer.toHexString(data[9]) +" "+ Integer.toHexString(data[10]) +" "+ Integer.toHexString(data[11]));
FileOutputStream fos = new FileOutputStream(new File(args[0]));
fos.write(data);
fos.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- Put the new classes.dex inside your unsigned APK
- Sign the APK file again.
- Run the program and voila! The text displayed is "CONGRATS! YOU CRACKED MY CODE! ;)"
I know it is a very small program and we know how the code works, but this is useful to see what can be done with bytecode manipulation.
Removing bytecode is not so simple, but you can try replacing the bytecode values in the lines you want to remove by zeros 00, it is the NOP bytecode.
Injecting bytecode is another story, lots of offsets must be modified in the classes.dex file. I will tell you later.
And I will test this in SDK 1.5, 1.6, but another day, i'm tired now :)
Enjoy!
Wednesday, November 4, 2009
How to check the signature in APK files or JAR files
You can use the jarsigner tool from JDK.
JDKFOLDER\bin\jarsigner.exe -verify -verbose -certs myAndroidProgram.apk
or
JDKFOLDER\bin\jarsigner.exe -verify -verbose -certs myJavaProgram.jar
the output will be the list of files with a detail of the signature, as following:
sm 3366 Thu Nov 05 00:57:58 ART 2009 res/drawable/icon.png
X.509, CN=Android Debug, O=Android, C=US
[certificate is valid from 05/11/09 00:01 to 05/11/10 00:01]
sm 640 Thu Nov 05 00:57:58 ART 2009 res/layout/main.xml
X.509, CN=Android Debug, O=Android, C=US
[certificate is valid from 05/11/09 00:01 to 05/11/10 00:01]
sm 1248 Thu Nov 05 00:57:58 ART 2009 AndroidManifest.xml
X.509, CN=Android Debug, O=Android, C=US
[certificate is valid from 05/11/09 00:01 to 05/11/10 00:01]
sm 1012 Thu Nov 05 00:57:58 ART 2009 resources.arsc
X.509, CN=Android Debug, O=Android, C=US
[certificate is valid from 05/11/09 00:01 to 05/11/10 00:01]
sm 1984 Thu Nov 05 00:57:58 ART 2009 classes.dex
X.509, CN=Android Debug, O=Android, C=US
[certificate is valid from 05/11/09 00:01 to 05/11/10 00:01]
401 Thu Nov 05 00:57:58 ART 2009 META-INF/MANIFEST.MF
454 Thu Nov 05 00:57:58 ART 2009 META-INF/CERT.SF
771 Thu Nov 05 00:57:58 ART 2009 META-INF/CERT.RSA
s = signature was verified
m = entry is listed in manifest
k = at least one certificate was found in keystore
i = at least one certificate was found in identity scope
jar verified.
Cheers
JDKFOLDER\bin\jarsigner.exe -verify -verbose -certs myAndroidProgram.apk
or
JDKFOLDER\bin\jarsigner.exe -verify -verbose -certs myJavaProgram.jar
the output will be the list of files with a detail of the signature, as following:
sm 3366 Thu Nov 05 00:57:58 ART 2009 res/drawable/icon.png
X.509, CN=Android Debug, O=Android, C=US
[certificate is valid from 05/11/09 00:01 to 05/11/10 00:01]
sm 640 Thu Nov 05 00:57:58 ART 2009 res/layout/main.xml
X.509, CN=Android Debug, O=Android, C=US
[certificate is valid from 05/11/09 00:01 to 05/11/10 00:01]
sm 1248 Thu Nov 05 00:57:58 ART 2009 AndroidManifest.xml
X.509, CN=Android Debug, O=Android, C=US
[certificate is valid from 05/11/09 00:01 to 05/11/10 00:01]
sm 1012 Thu Nov 05 00:57:58 ART 2009 resources.arsc
X.509, CN=Android Debug, O=Android, C=US
[certificate is valid from 05/11/09 00:01 to 05/11/10 00:01]
sm 1984 Thu Nov 05 00:57:58 ART 2009 classes.dex
X.509, CN=Android Debug, O=Android, C=US
[certificate is valid from 05/11/09 00:01 to 05/11/10 00:01]
401 Thu Nov 05 00:57:58 ART 2009 META-INF/MANIFEST.MF
454 Thu Nov 05 00:57:58 ART 2009 META-INF/CERT.SF
771 Thu Nov 05 00:57:58 ART 2009 META-INF/CERT.RSA
s = signature was verified
m = entry is listed in manifest
k = at least one certificate was found in keystore
i = at least one certificate was found in identity scope
jar verified.
Cheers
Remove signature from APK file and sign it again
The APK file is just a zip file with another extension. To remove the signature just unzip it, remove the folder META-INF and zip it again.
but how to sign it again? You can use your own signature or the debug signature used by Android SDK named debug.keystore
You can copy the debug signature from C:\Documents and Settings\\Local Settings\Application Data\Android\
The data of the signature is the following:
* Keystore name: "debug.keystore"
* Keystore password: "android"
* Key alias: "androiddebugkey"
* Key password: "android"
* CN: "CN=Android Debug,O=Android,C=US"
for more details go to http://developer.android.com/guide/publishing/app-signing.html
Now, how to sign the apk again? Use the jarsigner.exe tool, this tool comes with the JDK.
JDKFOLDER\bin\jarsigner.exe -verbose -storepass android -keystore debug.keystore myprogram.apk androiddebugkey
replace myprogram.apk with your own unsigned apk.
Is this useful? Maybe, if you want to modify the build with reverse engineering or something similar, use your imagination.
voila!
but how to sign it again? You can use your own signature or the debug signature used by Android SDK named debug.keystore
You can copy the debug signature from C:\Documents and Settings\\Local Settings\Application Data\Android\
The data of the signature is the following:
* Keystore name: "debug.keystore"
* Keystore password: "android"
* Key alias: "androiddebugkey"
* Key password: "android"
* CN: "CN=Android Debug,O=Android,C=US"
for more details go to http://developer.android.com/guide/publishing/app-signing.html
Now, how to sign the apk again? Use the jarsigner.exe tool, this tool comes with the JDK.
JDKFOLDER\bin\jarsigner.exe -verbose -storepass android -keystore debug.keystore myprogram.apk androiddebugkey
replace myprogram.apk with your own unsigned apk.
Is this useful? Maybe, if you want to modify the build with reverse engineering or something similar, use your imagination.
voila!
Disassemble dex files
Android SDK comes with the tool dexdump.exe
To disassemble a dex file just use the following command:
dexdump.exe -d -f -h classes.dex >dexdump.txt
The output will be stored in the file dexdump.txt, and the format is dalvik bytecode, not java bytecode.
I will investigate how to modify this file.
To disassemble a dex file just use the following command:
dexdump.exe -d -f -h classes.dex >dexdump.txt
The output will be stored in the file dexdump.txt, and the format is dalvik bytecode, not java bytecode.
I will investigate how to modify this file.
Subscribe to:
Posts (Atom)