I just used the new ProGuard tool in eclipse to obfuscation my application. The I decompiled it using dex2Jar and JD-GUI to inspect what happened.
I noticed that everything from the R class has been converted to a random number like the following.
new SimpleCursorAdapter(localActivity, 2130903058, localCursor, arrayOfString, arrayOfInt);
2130903058 was a layout file. Strings an arrays get the same treatment.
There is no R class in the decompiled code, where has it gone? Where are the references to the original strings?
All references are integers. If you look at R.string, you'll notice all the members are ints. This is because they are pointers to the actual strings. For example, android.R.string.cancel is always 17039360, which points to the string Cancel. What ProGuard does is it replaces these references with the actual numbers they represent, so if you use android.R.string.cancel, it will replace it with 17039360.
Edit: There is no R class because it is not needed anymore (all references to it have been replaced).
Related
Please explain me what is the purpose and meaning of classes like StringsKt__StringsKt (i.e. doubled class name with one or more underscores in between) and, similarly, StringsKt__StringsJVMKt?
Strings are not the only example, there are many others too. I see them when looking into the structure of the classes.dex file in my .apk.
screenshot here
I'm asking because I faced a situation where I had to explicitly state some of them in my proguard-rules. The app crashed without it.
It is a generated file. A file like that will be generated if there are several Kotlin files named with same JvmName.
Let's take Strings.kt and StringNumberConversions.kt as an example:
// StringNumberConversions.kt
#file:kotlin.jvm.JvmMultifileClass
#file:kotlin.jvm.JvmName("StringsKt")
...
// Strings.kt
#file:kotlin.jvm.JvmMultifileClass
#file:kotlin.jvm.JvmName("StringsKt")
...
Both of them have #file:kotlin.jvm.JvmName("StringsKt"), so StringsKt and StringsKt__StringNumberConversionsKt are generated to distinguish them.
When I obfuscate my code with Proguard, I have a line of code as follows:
String aString = getResources().getString(R.string.foo);
Even though I set my proguard configuration file to keep the R class an all its inner classes (and they're been kept), it obfuscates that line making foo a static field of a random renamed n class.
How can I make it not to make this specific change and inline the referred string at that point? Or reference the string by the id for that matter.
Give a try to -keepclassmembernames
It seems you are doing Android developing, in this case the default proguard configuration comes with Android Studio works perfect for me. If you are using other IDE, you can just copy that proguard configuration to your project.
I know in Proguard you are recommended to keep the fields names of the R inner classes like ID. Because ProGuard doesn't handle the layout xml files. You will end up with broken links
But is there away to obfuscate classes like R$id by some other means, even if it involves doing it before passing it to ProGuard, via Ant.
I am asking this because if you have a button with an id btnSaveArticle, for a hacker it becomes too easy to grasp what the code around is doing by looking at the name.
Could it be possible to copy all the source code, including the resource files to another folder and use ant to run regex to change the names of the R.ids as well as changing where they appear in the layout xml files, and then somehow running generate to re-create the R classes?
Or you could create translation class eg TR then map it to the fields in the R.class
eg.
TR.btnSaveArticle = R.id.DHTXM;
Where DHTXM is some meaning less word that can be used in the layout XML. But in the code you always refer to TR.btnSaveArticle, which will be obfuscated by proguard.
Are there ways to achieve this or am I wasting my time?
Just use below ,add it to you Proguard config file
-keepclassmembers class **.R$* {
public static <fields>;}
I am asking this because if you have a button with an id btnSaveArticle, for a hacker it becomes too easy to grasp what the code around is doing by looking at the name.
Using Hierarchy View, it would take them less than 30 seconds to determine the actual ID of the "Save Article" button, no matter what you name it. And I can envision even faster solutions with a bit of custom tooling.
am I wasting my time?
IMHO, yes.
With the default configuration for Android, ProGuard removes R classes entirely, unless your code performs introspection on them. In the latter case, ProGuard also preserves the fields with their original names, in order not to break the introspection.
That being said, the resource names can also be retrieved from the resource XML files, which ProGuard leaves untouched.
It is possible through Ant, as it allows you to set a different gen and res folder.
So what you do is copy from the originals to those folders and then you edit the files using regex to update to the new names.
You will need a translation class (eg D) like this to map it to the fields in the R.class, so in your code you can work with non obfuscated names.
public final class D{
public static final class id{
D.btnSaveArticle = R.id.btnSaveArticle //DHTXM;
Then you also need to create a different src folder and copy from the original folder. There you run a task to edit the D class so it becomes
D.btnSaveArticle = R.id.DHTXM;
I had to create a java program which is run through ant to swap the names to obfuscated names.
If you do something similar for strings, and styles your XML in the apk would end up looking like this:
<TextView
android:id="#+id/GnvCMa"
android:text="#string/OVuCbd"
style="#style/ZOVkuu.MGTRgZ" />
It is a little time consuming to setup, but once implemented it can be used for other projects.
I have been working on a simple android tutorial and while browsing through the project folders I found this R.java file in gen folder...
When I opened it seemed to me as a mess...
first R itself is a class.
it had multiple Inner classes defined within eg drawable,id,layout,etc.
and that inner classes had lots of variables declared as below which were assigned with hex values
public static final int addr=0x7f080003;
...
...
and much more
R is auto generated and acts as some pointer for other files
Questions for R.java
what it is basically for
how it works
why
values are in hex
what role did it performs while the actual application is running
"Acts as some pointer to other files" is actually absolutely correct, now the question is which files it points to how it is done.
What does it contain?
R file contains IDs for all the resources in the res folder of your project and also some additional IDs that you define on your own (in the layouts, for example). The IDs are needed for the Android resource management system to retrieve the files from the APK. Each ID is basically a number which corresponds to some resource in the resource management system.
The file itself is needed so you can access or reference the resource from code by giving the ID of the resource to the resource manager. Say, if you want to set the view in the activity, you call
setContentView(R.layout.main);
main in the R file contains the number which is understood by the Android resource management system as the layout file which is called main.
Why is it better than just plain file names?
It's harder to make a mistake with the generated fields. If you write the field name incorrectly, your program won't compile and you will know that there's an error immediately. If you write an incorrect string, however, the application won't fail until it is launched.
If you want to read more on this topic, you should check the Android documentation, especially the Accessing Resources part.
This holds your resource ids. So when you do something like
TextView tv = (TextView) findViewById(R.id.mytextview);
it looks up your id here for that View, layout, etc... This way the app has an easy way to look up your ids while you can use easy to remember names. Anytime you create a resource it automatically creates an id for it and stores it here. That's why you never want to try and edit this file yourself.
One way to think about how valuable R.java is, imagine a world without it. Its amazing how android brings the xml and java world together to help avoid coding the UI manually completely. With legacy java building UI using the java language was a pain. Invaluable.
With Android you can not only build your UI using only xml, but also see it while you build it. Invaluable.
Every element in the xml can be referenced in the java code WITHOUT writing a single line of code to parse the xml :). Just R.id.nameOfElement. Invaluable.
Rapid development is beautifully done in android. Imagine if iPhone would have 5000 screens to fit that one piece of code, they would crumble on their XCode. Google has done a wonderful job with just R.java. Invaluable.
there is this R.layout class in the standard library, but if I create my own files with xml editor in R.layout directory, they'll be all added to R-file and found from the R-file? This is a bit unclear to me how these go together.
http://developer.android.com/reference/android/R.layout.html
All the factory android R references are stored in a different place than yours. For example, in your java code, you'll access to your references using this:
R.layout.yourlayout
But the factory R references are accessed through:
android.R.layout.factorylayout
Same goes for xml. Your drawables should be:
#drawable/yourdrawable
And the factory references:
#android:drawable/factorydrawable
So, to sum up, R items are stored independently