如何使我的代码安全并防止反编译?

How to make my code secure and prevent from decompiling?

我创建了 android 应用程序,它运行良好。 问题是,当我们反编译应用程序时,我们可以看到所有代码,因此黑客可以看到我们的 API URLAPI 类 这样他们就可以克隆应用程序了。

所以我的问题是如何保护我的 android 应用程序,使其免受黑客攻击。

您可以使用 DexGuard。保护 Android 应用程序和 SDK 免受逆向工程和 hacking.DexGuard 提供广泛的自定义选项,使您能够根据您的安全性和性能调整应用的保护 requirements.DexGuard 防止攻击者深入了解您的源代码和修改它或从中提取有价值的信息。

ProGuard is a generic optimizer for Java bytecode. DexGuard is a specialized tool for the protection of Android applications.

阅读Dexguard-vs-Proguard

您可以在创建签名 apk 时使用 Android 工作室默认提供的混淆器,您可以参考下面的文档

Link: https://docs.google.com/document/d/1UgEZtKRoAIIXtPLKKHIds33txgU7hH33-3xsoBR4lWY/edit?usp=sharing

您可以使用 ProGuard 工具来保护您的代码。它使用简短无意义的名称重命名了剩余的 类、字段和方法。

API 端点将始终对最终用户开放。但是,如果您在 api 服务器中使用 https 和 SSL,数据将像大多数应用程序一样被加密。至于API端点,你不能做任何事情

我找到了一个可以帮助您反编译应用程序的网站 JavaDecompiler。我的研究结果是没有办法提供 100% 的代码安全性。所以我们可以做的是将条件放在前端和后端两侧。

我试过 dexguard,但它对我来说很贵,而且 proguard 对我来说效果不佳。

你的问题

I created android app and it is working fine. The issue is that when we decompile the app we can see all the code, so hacker can see our API URL and API Classes so they can clone the app.

无论您使用什么工具来混淆甚至加密代码,您的 API url 在某些时候都需要以明文形式显示,也就是当您执行 API请求,因此攻击者可以获取它。因此,如果攻击者无法通过静态二进制分析提取它,它将在运行时使用检测框架提取,例如 Frida:

Inject your own scripts into black box processes. Hook any function, spy on crypto APIs or trace private application code, no source code needed. Edit, hit save, and instantly see the results. All without compilation steps or program restarts.

所以基本上攻击者需要在代码中找到你发出 API 请求的地方,在上面挂钩 Frida,然后提取 URL 或任何随它传递的秘密identify/authorize 您在 API 服务器中的移动应用程序。

攻击者可以采取的另一种方法是在他控制的移动设备中执行 MitM 攻击,并拦截向 API 服务器发出的请求:

图片来源于文章:Steal that API key with a Man in the Middle Attack

正如您在上面的示例中看到的,拦截的 API 请求显示 API 服务器 url 和正在使用的 API 密钥。

可能的解决方案

So my question is that how can I secure my android app so I can protect it from hackers.

添加安全性时,无论是针对软件还是针对 material 事物,总是与层次有关,例如中世纪的城堡,它们不只有一层防御,它们有多层它。因此,您应该将相同的原则应用于您的移动应用程序。

我将列出一些你应该做的最少的事情,但不是详尽无遗的清单。

JNI/NDK

JNI/NDK:

The Native Development Kit (NDK) is a set of tools that allows you to use C and C++ code with Android, and provides platform libraries you can use to manage native activities and access physical device components, such as sensors and touch input.

this demo app I show how native C code is being used to hide the API key 中很容易通过静态二进制分析进行逆向工程,但正如您已经看到的那样,您在运行时通过 MitM 攻击获取了它。


#include <jni.h>
#include <string>
#include "api_key.h"

extern "C" JNIEXPORT jstring JNICALL
Java_com_criticalblue_currencyconverterdemo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {

    // To add the API_KEY to the mobile app when is compiled you need to:
    //   * copy `api_key.h.example` to `api_key.h`
    //   * edit the file and replace this text `place-the-api-key-here` with your desired API_KEY
    std::string JNI_API_KEY = API_KEY_H;

    return env->NewStringUTF(JNI_API_KEY.c_str());
}

如果您想详细了解如何在您的移动应用程序中实施它,请访问 Github 存储库。

混淆

您应该始终混淆您的代码。如果您负担不起最先进的解决方案,那么至少使用内置的 ProGuard 解决方案。这会增加检查代码所需的时间和技能。

加密

您可以使用加密来隐藏敏感代码和数据,快速 Google 搜索将产生大量资源和技术。

对于用户数据加密,您可以在 Android docs:

开始了解更多相关信息

Encryption is the process of encoding all user data on an Android device using symmetric encryption keys. Once a device is encrypted, all user-created data is automatically encrypted before committing it to disk and all reads automatically decrypt data before returning it to the calling process. Encryption ensures that even if an unauthorized party tries to access the data, they won’t be able to read it.

您可以在 Android docs 中阅读一些这样做的例子:

This document describes the proper way to use Android's cryptographic facilities and includes some examples of its use. If your app requires greater key security, use the Android Keystore system.

但请记住,使用 Frida 将允许攻击者挂入 returns 未加密数据的代码,并提取它,但也需要更多的技巧和时间来实现这一点。

移动应用认证

这个概念引入了一种新的方式来保护您的移动应用程序。

传统方法主要集中在客户端,但首先您要保护的数据位于 API 服务器中,您希望在此处拥有一种让您知道的机制发出请求的 确实是您的正版移动应用程序,与您上传到 Google Play 商店的应用程序相同。

在深入探讨移动应用证明的作用之前,我想首先澄清一个关于 什么 的误解执行 API 请求,我会引用 this article 我写的:

The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?

The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.

我写的另一篇文章 this section 中描述了移动应用证明角色,我从中引用了以下文字:

The role of a Mobile App Attestation service is to authenticate what is sending the requests, thus only responding to requests coming from genuine mobile app instances and rejecting all other requests from unauthorized sources.

In order to know what is sending the requests to the API server, a Mobile App Attestation service, at run-time, will identify with high confidence that your mobile app is present, has not been tampered/repackaged, is not running in a rooted device, has not been hooked into by an instrumentation framework (Frida, xPosed, Cydia, etc.) and is not the object of a Man in the Middle Attack (MitM). This is achieved by running an SDK in the background that will communicate with a service running in the cloud to attest the integrity of the mobile app and device it is running on.

On a successful attestation of the mobile app integrity, a short time lived JWT token is issued and signed with a secret that only the API server and the Mobile App Attestation service in the cloud know. In the case that attestation fails the JWT token is signed with an incorrect secret. Since the secret used by the Mobile App Attestation service is not known by the mobile app, it is not possible to reverse engineer it at run-time even when the app has been tampered with, is running in a rooted device or communicating over a connection that is the target of a MitM attack.

The mobile app must send the JWT token in the header of every API request. This allows the API server to only serve requests when it can verify that the JWT token was signed with the shared secret and that it has not expired. All other requests will be refused. In other words a valid JWT token tells the API server that what is making the request is the genuine mobile app uploaded to the Google or Apple store, while an invalid or missing JWT token means that what is making the request is not authorized to do so, because it may be a bot, a repackaged app or an attacker making a MitM attack.

因此,这种方法会让您的 API 服务器以非常高的置信度信任该请求确实来自您上传到 Google Play 商店的同一移动应用程序,如果 JWT 令牌具有有效的签名和过期时间,并将所有其他请求作为不可信的请求丢弃。

加倍努力

我忍不住向您推荐 OWASP 基金会的优秀作品,因为没有经过 The Mobile Security Testing Guide 的移动安全解决方案是完整的:

The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.

除了使用代码混淆,您无能为力。我建议使用 NDK 层来存储应用程序机密,因为 C++ 库不容易反编译。为此,您可以使用 https://github.com/nomtek/android-client-secrets 库。