其他分享
首页 > 其他分享> > android – 在APK中简单隐藏/混淆字符串?

android – 在APK中简单隐藏/混淆字符串?

作者:互联网

有时您需要在应用程序本身中存储密码,例如用于与您自己的服务器通信的用户名/密码.在这些情况下,不可能遵循存储密码的正常过程 – 即散列密码,存储散列,与散列用户输入进行比较 – 因为您没有任何用户输入来比较散列.密码需要由应用程序本身提供.那么如何保护APK中存储的密码呢?如下所示的密码生成功能是否合理安全?

纯文本:

String password = "$()&HDI?=!";

简单的混淆:

private String getPassword(){
    String pool = "%&/@$()7?=!656sd8KJ%&HDI!!!G98y/&%=?=*^%&ft4%(";
    return pool.substring(4, 7) + pool.substring(20, 24) + pool.substring(8, 11);
}

我知道ProGuard有一些混淆功能,但我很好奇上面的“混淆”技术在编译时会做什么,以及通过查看APK和/或使用其他更复杂的东西来弄清楚它有多难技术?

解决方法:

tl; dr如果您知道如何反编译APK,无论代码如何混淆,您都可以轻松获取密码.不要在APK中存储密码,这是不安全的.

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?

我会告诉你它有多容易.这是我们将反编译的Android SSCCE

MyActivity.java:

public class MyActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        TextView text = (TextView) findViewById(R.id.text);
        text.setText(getPassword());
    }

    private String getPassword() {
        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"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/text"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"/>

在编译并运行后,我们可以看到$()& HDI?=!在TextView上.

让我们反编译APK:

>解压缩myapp.apk或右键单击APK并在此处解压缩.
出现classes.dex文件.
>使用dex2jar将classes.dex转换为JAR文件.执行dex2jar.sh classes.dex后,classes_dex2jar.jar文件
出现.
>在classes_dex2jar.jar上使用一些Java反编译器,例如JD-GUI,我们从MyActivity.class中检索这样的Java代码:

public class MyActivity extends Activity
{
    private String getPassword()
    {
        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);
    }

    public void onCreate(Bundle paramBundle)
    {
        super.onCreate(paramBundle);
        setContentView(2130903040);
        ((TextView)findViewById(2131034112)).setText(getPassword());
    }
}

ProGuard无济于事,代码仍然易于阅读.

基于以上所述,我已经可以给你一个这个问题的答案:

Would a password-generating function like the one below be reasonably
secure?

不可以.正如您所看到的,它会增加一点点读取反混淆代码的难度.我们不应该以这种方式混淆代码,因为:

>它给人一种安全感.
>浪费开发人员的时间.
>它降低了代码的可读性.

在官方Android文档中,在Security and Design部分中,他们建议保护您的Google Play公钥:

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.

好的,让我们试试看:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    TextView text = (TextView) findViewById(R.id.text);
    text.setText(xor("A@NCyw&IHY", "ehge13ovux"));
}

private String xor(String a, String b) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < a.length() && i < b.length(); i++) {
        sb.append((char) (a.charAt(i) ^ b.charAt(i)));
    }
    return sb.toString();
}

给$()& HDI?=!在TextView上,很好.

反编译版本:

public void onCreate(Bundle paramBundle)
{
    super.onCreate(paramBundle);
    setContentView(2130903040);
    ((TextView)findViewById(2131034112)).setText(xor("A@NCyw&IHY", "ehge13ovux"));
}

private String xor(String paramString1, String paramString2)
{
    StringBuilder localStringBuilder = new StringBuilder();
    for (int i = 0; (i < paramString1.length()) && (i < paramString2.length()); i++) {
        localStringBuilder.append((char)(paramString1.charAt(i) ^ paramString2.charAt(i)));
    }
    return localStringBuilder.toString();
}

和之前非常相似的情况.

即使我们有极其复杂的函数soStrongObfuscationOneGetsBlind(),我们也可以运行反编译代码并查看它产生的内容.或者一步一步地调试它.

标签:deobfuscation,android,decompiling,obfuscation
来源: https://codeday.me/bug/20191005/1855860.html