[General Questions and Answers] Wrongusername:
[Introduction]

So i wanted to poke around some android app and while at it get some idea about android/java reversing.

I've never dealt with java or android to any significant degree, all the more interesting stuff to discover.

I think what i discovered over past couple of day could be usefull to your community so i decided to share it.

Seems like it's a generally accepted fact on android scene that it's impossible to modify .class files at high level, as in by modifying their decompiled .java sources and everyone goes about it through disassembly to dalvik instructions(or perhaps smali is a bit higher level representation) and whatnot and then reassembling, using decompiled code just for reference...

When talking about programming languages/systems that compile to pseudo-code that's later jitted or translated into native code, i've dealt with something similar before

once before when i poked around flash/actionscript 3 reversing, while there were decompilers for actionscript 3 available and particular swf wasn't even obfuscated it wasn't really possible to use decompiled output to make some small changes to significally large project cause of decompiler errors, as in flash you have to compile it all at once or not at all.

There also existed tools that enabled disassembling to as3 AAVM opcodes level, making changes if you can wrap your head around that bytecode language and reassembling back.

But who is fluent in as3 or java or dalvik VM bytecode language except their creators and why would they be? Sure small changes are possible but a pain even at that...

When by some chance i ended up prodding some java i remembered hearing that people are making that Minecraft mods and they don't have original full sources, they just replace/add classfiles to minecraft.jar.

I though "hey that should be possible for android apps" and driven mostly with reverse-engineering curiousity set out to check my hypothesis.

Turns out there's no such thing as "android compiler", since android build process uses javac standard java sdk compiler and java allows compiling single class files and linking against .jar file containing compiled .class files as a library.

Requirements:

1. Dex2jar

2. Android adt bundle

3. Java jdk 1.7

4. Optional : apktool

The guide itself

1. Run dex2jar yourapp.apk

2. Use jd-gui or whatever to get source code of .class file you're interested in inside that apk.

Take note that decompilers don't always produce outright recompilable code

Simplest example jd-gui produces outputs that imports R.strings etc, while javac want it to be a single R import

You can try different java decompilers or fix up the code yourself. Some .class files most decomilers will fail to tackle but those are a minority.

If app is not proguarded it's mostly at your mercy.

3. Modify .java source code of class as you see fit.

4. (optional) You can also do some layout, drawable etc editing(obtained from apktool or whatnot) in a comfortable way if you re-import res folder contents into Eclipse project res.

5. Download android sdk stuff for android api version your app was made for with adt sdk manager tool You're interested particularly in android.jar library, perhaps andorid-support.jar. Maybe you can link against newer library versions, dunno. For my app developer stated minimum required android version so i linked against that jars, but as to how to find out what android version app requires, you can look at android folder in your undexed jar, android\support\v4

v4 = android api 4, android 1.6 version

6. javac -target 1.6(this is not android 1.6, it's java bytecode and source compliance, by default current jdk 1.7 produces "invalid magic cafebabe" error later from dx) -source 1.6 -classpath path_to\classes.jar(obtained from dex2jar);path_to_android_adt\sdk\platforms\android-(required version)\android.jar;(maybe include android-support classpath, worked for me without) path_to\your_modified_class(but named same as originally).java

Like

C:\Program Files\Java\jdk1.7.0_25\bin\javac -target 1.6 -source 1.6 -classpath C:\Users\User\Desktop\testapp\classes.jar;E:\adt-bundle-windows-x86-20130717\sdk\platforms\android-4\android.jar C:\Users\User\Desktop\testapp\someclass.java

If you fed javac valid java code it'll spit out valid .class file, otherwise read it's error output and perform steps to fix that errors.

7. Plug your newly created classfile back into it's jar, use winrar, windows explorer(by renaming it to zip) or whatever.

Javac can produce a differently fragmented classfile than one originally in jar so you may want to delete yourclassname.class

yourclassname$1.class yourclassname$2.class yourclassname$3$1.class ... from jar first.

8. Now it time for our java bytecode to go Dalvik

Dx your updated jar

E:\adt-bundle-windows-x86-20130717\sdk\build-tools\17.0.0\dx.bat --dex --no-optimize --output classes.dex classes.jar

9. Plug your updated classes.dex back into original apk

Delete META-INF folder from apk to "unsign" it while you're at it.

10. Re-sign apk with

C:\Program Files\Java\jdk1.7.0_25\bin\keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000

C:\Program Files\Java\jdk1.7.0_25\bin\jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore my_application.apk alias_name

11. Zipalign

E:\adt-bundle-windows-x86-20130717\sdk\tools\zipalign\zipalign -v 4 your_project_name-unaligned.apk your_project_name.apk

12. Install modified apk

This whole thing relies on the fact that while fully recompilable autmatic decompilation of java project of any complexity isn't feasible like always, decompilers are capable of producing large portion of mostly correct code, and java allows you to recompile exclusively that parts you're interested in which could very well end up being correctly decompiled outright or require just minor fixups and you don't have to deal with the fact that your decompiler produced thousands of errors in OTHER classfiles that your class depends on.

I guess even in case target app is obfuscated/proguarded having ability to deal with it on .java level and not disassemly level could still be of great benefit.