混淆不足以通过渗透测试
适当的渗透测试将分析应用的静态和运行时行为,因此运行时行为根本不会仅通过混淆来覆盖
但也仅考虑您将要进行的静态分析,您远非安全
我将为您提供一个简单实用的示例,因为您建议的两种工具之间的差异已经在另一个答案中报告了
假设您有一个原始的未经混淆的MainActivity,由:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
// lines for adding the shortcut in the home screen
appPreferences = PreferenceManager.getDefaultSharedPreferences(this);
isAppInstalled = appPreferences.getBoolean("isAppInstalled", false);
if(isAppInstalled == false)
addShortcut();
地点:
private void addShortcut() {
//Adding shortcut
// ...
addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
// ...
SharedPreferences.Editor editor = appPreferences.edit();
editor.putBoolean("isAppInstalled", true);
editor.commit();
}
这些是被 ProGuard 混淆并通过online Java decompiler 获取的合作伙伴
结论:
1) 如您所见 - 尽管有 proguard 混淆 - 您处于攻击者可以轻松修改代码流的位置 [e.g.将if (!this.f2293p) 转换为if (this.f2293p)] 并轻松理解您必须做什么才能修改应用程序中的值,尽管存在混淆。在这种情况下,这是一个简单的愚蠢的“isAppInstalled”偏好,但当然它可能更敏感,例如:
public boolean appIsPurchased(){
return settings.getBoolean(keyPurchase,false);
}
PS 存储未加密的共享首选项 [尤其是在包含敏感数据的情况下] 是一种非常糟糕的做法,这只是一个用于演示目的的快速示例。在有根设备中检索此文件就等于浏览到系统文件夹并搜索 xml 文件
2) 此外,通常这种纯粹的混淆不会隐藏任何硬编码的内容。我们已经看到了:
editor.putBoolean("isAppInstalled", true);
被转化为:
this.f2293p = this.f2292o.getBoolean("isAppInstalled", false);
另一个简单的例子可以是:
if (barcode.equals("123456")) {
return "Hat";
}
if (barcode.equals("234567")) {
return "Jumper";
}
if (barcode.equals("345678")) {
return "Pants";
}
return "Troubles detecting the new item";
混淆后生成:
return str.equals("123456") ? "Hat" : str.equals("234567") ? "Jumper" : str.equals("345678") ? "Pants" : "Troubles detecting the new item";
对于那些意图破坏您的纯混淆应用程序的人来说,这些字符串是厚颜无耻的暗示。例如,任何人都可以使用您的端点字符串
因此,您需要像 DexGuard 这样的工具或其他能够产生比简单混淆更复杂的商业解决方案的工具
这是 ProGuard + 第三方安全工具的最终结果示例 [我没有 DexGuard,我使用另一个通过拖放原始未受保护的 apk 自动应用保护的工具]
这是新的onCreate() 方法:
protected void onCreate(Bundle bundle) {
//...
this.f1859o = PreferenceManager.getDefaultSharedPreferences(this);
this.f1860p = this.f1859o.getBoolean(k09kcah9u6scvhh4ab059fbmtq.itg7jcg3c4din73t0cib8n7eau("~"), false);
if (!this.f1860p) {
m3099j();
}
}
虽然这是第二个使用硬编码字符串的示例,这些字符串已经完全隐藏在黑客的视野中:
public String m3101a(String str) {
PrintStream printStream = System.out;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(k09kcah9u6scvhh4ab059fbmtq.itg7jcg3c4din73t0cib8n7eau("}}"));
stringBuilder.append(str);
String stringBuilder2 = stringBuilder.toString();
return str.equals(k09kcah9u6scvhh4ab059fbmtq.itg7jcg3c4din73t0cib8n7eau("}|")) ? k09kcah9u6scvhh4ab059fbmtq.itg7jcg3c4din73t0cib8n7eau("}s") : str.equals(k09kcah9u6scvhh4ab059fbmtq.itg7jcg3c4din73t0cib8n7eau("}r")) ? k09kcah9u6scvhh4ab059fbmtq.itg7jcg3c4din73t0cib8n7eau("~{") : str.equals(k09kcah9u6scvhh4ab059fbmtq.itg7jcg3c4din73t0cib8n7eau("~z")) ? k09kcah9u6scvhh4ab059fbmtq.itg7jcg3c4din73t0cib8n7eau("~y") : k09kcah9u6scvhh4ab059fbmtq.itg7jcg3c4din73t0cib8n7eau("~x");
}
这是您通过渗透测试所需的保护程度
最后 - 作为一项额外的安全措施 - 这种专业工具还可以检测受保护的“不可读”代码中的修改,并在检测到对受保护版本的篡改操作时停止应用执行。而且,与简单 [但美观] ProGuard 不同,它实现了对模拟器、root 设备和其他潜在危险场景的检测
请注意代码是如何通过这些步骤强化的。没有人是 100% 免受黑客攻击的。你的工作只是让事情变得尽可能困难,仅此而已