Simple Hiding/obfuscation Of Strings In Apk?
Solution 1:
tl;dr If you know how to decompile APK, you can easily get the password, no matter how obfuscated the code was. Don't store passwords in APK, it's not secure.
I know ProGuard has some obfuscation capabilities, but I'm curious about what the above "obfuscation" technique does when it's compiled, and how hard it would be for someone to figure it out by looking in the APK and/or using other more sophisticated techniques?
I will show you how easy it is. Here is an Android SSCCE which we will decompile:
MyActivity.java
:
publicclassMyActivityextendsActivity {
@OverridepublicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView text = (TextView) findViewById(R.id.text);
text.setText(getPassword());
}
privateStringgetPassword() {
String pool = "%&/@$()7?=!656sd8KJ%&HDI!!!G98y/&%=?=*^%&ft4%(";
return pool.substring(4, 7) + pool.substring(20, 24) + pool.substring(8, 11);
}
}
main.xml
:
<?xml version="1.0" encoding="utf-8"?><TextViewxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/text"android:layout_width="fill_parent"android:layout_height="wrap_content"/>
After compiling it and running we can see $()&HDI?=!
on a TextView
.
Let's decompile an APK:
unzip myapp.apk
or right-click on the APK andUnzip here
.classes.dex
file appears.- Convert
classes.dex
to JAR file with dex2jar. After executingdex2jar.sh classes.dex
,classes_dex2jar.jar
file appears. Using some Java decompiler on
classes_dex2jar.jar
, for example JD-GUI, we retrieve such Java code fromMyActivity.class
:publicclassMyActivityextendsActivity { privateStringgetPassword() { return"%&/@$()7?=!656sd8KJ%&HDI!!!G98y/&%=?=*^%&ft4%(".substring(4, 7) + "%&/@$()7?=!656sd8KJ%&HDI!!!G98y/&%=?=*^%&ft4%(".substring(20, 24) + "%&/@$()7?=!656sd8KJ%&HDI!!!G98y/&%=?=*^%&ft4%(".substring(8, 11); } publicvoidonCreate(Bundle paramBundle) { super.onCreate(paramBundle); setContentView(2130903040); ((TextView)findViewById(2131034112)).setText(getPassword()); } }
ProGuard can't help much, the code will be still easily readable.
Based on the above, I can already give you an answer for this question:
Would a password-generating function like the one below be reasonably secure?
No. As you can see, it increases difficulty of reading deobfuscated code by a tiny bit. We should not obfuscate the code in such way, because:
- It gives an illusion of security.
- It is a waste of developer's time.
- It decreases readability of the code.
In the official Android documentation, in the Security and Design part, they're advising this to protect your Google Play public key:
To keep your public key safe from malicious users and hackers, do not embed it in any code as a literal string. Instead, construct the string at runtime from pieces or use bit manipulation (for example, XOR with some other string) to hide the actual key. The key itself is not secret information, but you do not want to make it easy for a hacker or malicious user to replace the public key with another key.
Ok, so let's try that:
@OverridepublicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView text = (TextView) findViewById(R.id.text);
text.setText(xor("A@NCyw&IHY", "ehge13ovux"));
}
privateStringxor(String a, String b) {
StringBuilder sb = newStringBuilder();
for (int i = 0; i < a.length() && i < b.length(); i++) {
sb.append((char) (a.charAt(i) ^ b.charAt(i)));
}
return sb.toString();
}
Gives $()&HDI?=!
on a TextView
, good.
Decompiled version:
publicvoidonCreate(Bundle paramBundle)
{
super.onCreate(paramBundle);
setContentView(2130903040);
((TextView)findViewById(2131034112)).setText(xor("A@NCyw&IHY", "ehge13ovux"));
}
privateStringxor(String paramString1, String paramString2)
{
StringBuilder localStringBuilder = newStringBuilder();
for (int i = 0; (i < paramString1.length()) && (i < paramString2.length()); i++) {
localStringBuilder.append((char)(paramString1.charAt(i) ^ paramString2.charAt(i)));
}
return localStringBuilder.toString();
}
Very similar situation like before.
Even if we had extremely complicated function soStrongObfuscationOneGetsBlind()
, we can always run decompiled code and see what is it producing. Or debug it step-by-step.
Post a Comment for "Simple Hiding/obfuscation Of Strings In Apk?"