ChatGPT解决这个技术问题 Extra ChatGPT

如何避免 APK 文件的逆向工程

我正在为 Android 开发一个支付处理应用程序,我想防止黑客访问 APK 文件中的任何资源、资产或源代码。

如果有人将 .apk 扩展名更改为 .zip,那么他们可以将其解压缩并轻松访问所有应用程序的资源和资产,并且使用 dex2jar 和 Java 反编译器,他们还可以访问源代码。对 Android APK 文件进行逆向工程非常容易 - 有关详细信息,请参阅 Stack Overflow 问题Reverse engineering from an APK file to a project

我使用了 Android SDK 提供的 Proguard 工具。当我对使用签名密钥库和 Proguard 生成的 APK 文件进行反向工程时,我得到了混淆代码。

但是,Android 组件的名称保持不变,一些代码(如应用中使用的键值对)保持不变。根据 Proguard 文档,该工具不能混淆 Manifest 文件中提到的组件。

现在我的问题是:

如何完全防止 Android APK 的逆向工程?这可能吗?如何保护应用程序的所有资源、资产和源代码,使黑客无法以任何方式破解 APK 文件?有没有办法让黑客攻击变得更加困难甚至不可能?我还能做些什么来保护我的 APK 文件中的源代码?

如果您的支付处理方案依赖于客户端的操作,那么听起来您可能正在使用“默默无闻的安全性”。
您是否考虑过用 C/C++ 编写代码的重要部分并将它们添加为编译库?它们可以被反汇编成汇编代码,但是从汇编逆向工程一个大型库是非常耗时的。
欢迎来到创建任何数字资产的基本问题。黑客可以深入到机器指令级别,因此如果计算机可以读取文件,那么它就可以被黑客打开/复制,再多的混淆或 DRM 也无法完全阻止一个坚定的黑客。如果您需要安全性,请确保私钥永远不会出现在源代码中,并且在设计阶段就知道只有隔离(远程和/或专用硬件)才能保护它们。
请注意,根据您的支付处理应用程序的功能,可能存在影响您的应用程序的监管和法律政策,并可能使您面临严厉的处罚:请参阅 PCI 合规性,从 pcicomplianceguide.org/pcifaqs.php#11 开始。

P
Peter Mortensen

1. 如何完全避免Android APK的逆向工程?这可能吗?

AFAIK,没有任何技巧可以完全避免逆向工程。

@inazaruk 也说得很好:无论您对代码做什么,潜在的攻击者都能够以她或他认为可行的任何方式对其进行更改。您基本上无法保护您的应用程序不被修改。您在那里放置的任何保护都可以被禁用/删除。

2. 如何保护应用程序的所有资源、资产和源代码,使黑客无法以任何方式破解APK文件?

不过,您可以采取不同的技巧来提高黑客攻击的难度。例如,使用混淆(如果是 Java 代码)。这通常会显着减慢逆向工程的速度。

3. 有没有办法让黑客攻击变得更加困难甚至不可能?我还能做些什么来保护我的 APK 文件中的源代码?

正如每个人所说,并且您可能知道,没有 100% 的安全性。但谷歌内置的 Android 的起点是 ProGuard。如果您可以选择包含共享库,您可以在 C++ 中包含所需的代码以验证文件大小、集成等。如果您需要在每次构建时将外部原生库添加到 APK 的库文件夹中,那么您可以使用它通过以下建议。

将库放在项目文件夹中默认为“libs”的本机库路径中。如果您为“armeabi”目标构建了本机代码,则将其放在 libs/armeabi 下。如果它是用 armeabi-v7a 构建的,则将其放在 libs/armeabi-v7a 下。

<project>/libs/armeabi/libstuff.so

对于支付交易,我使用了 ISO 8585 标准,现在这个标准的模式是在键值对中使用 Java 的 HashMap 集合&当我对 apk 进行逆向工程时,我会得到所有模式。是否可以避免模式获取通过逆向工程暴露。?您对共享库的最后建议在这种情况下有用吗?您是否有任何链接,以便我可以接触到 android 中的共享库。
如何在代码中加密你的字符串并在运行时解密它们?如果您像其他人建议的那样在远程服务器上进行解密,则不会遇到解密密钥在源中的问题。
是的,加密是一种方式,但不确定不会被黑客入侵。如果我正在加密字符串以解密它们,我需要在代码中使用一个唯一的 id。如果有人能够反编译它,那么获得唯一 ID 将非常容易。
为什么你添加编辑的东西?都是正常的。
@hotveryspicy:是的,我现在已经从答案中删除了“已编辑”标记。我已经编辑了我的答案,因为他想更多地了解共享库在这种情况下如何有用。
R
Raghav Sood

AFAIK,您无法保护 /res 目录中的文件,而现在它们受到保护。

但是,您可以采取一些措施来保护您的源代码,或者至少它的作用(如果不是全部)。

使用 ProGuard 等工具。这些会混淆你的代码,并且在反编译时使其更难阅读,如果不是不可能的话。将服务中最关键的部分从应用程序中移出,移到 Web 服务中,隐藏在像 PHP 这样的服务器端语言之后。例如,如果你有一个算法花了你一百万美元来编写。您显然不希望人们从您的应用程序中窃取它。移动算法并让它处理远程服务器上的数据,然后使用应用程序简单地为其提供数据。或者使用 NDK 将它们原生地写入 .so 文件,与 apks 相比,这些文件被反编译的可能性要小得多。我认为 .so 文件的反编译器现在甚至不存在(即使它存在,它也不会像 Java 反编译器那样好)。此外,正如@nikolay 在评论中提到的,您应该在服务器和设备之间进行交互时使用 SSL。在设备上存储值时,不要以原始格式存储它们。例如,如果您有一个游戏,并且您将用户拥有的游戏货币数量存储在 SharedPreferences 中。假设它是 10000 个硬币。与其直接保存 10000,不如使用 ((currency*2)+1)/13 之类的算法保存。因此,您将 1538.53846154 保存到 SharedPreferences 中,而不是 10000。然而,上面的例子并不完美,你必须努力想出一个不会因舍入错误等而损失货币的等式。你可以对服务器端任务做类似的事情。现在举个例子,让我们以您的支付处理应用为例。假设用户必须支付 200 美元。与其向服务器发送原始的 200 美元值,不如发送一系列较小的预定义值,加起来为 200 美元。例如,在您的服务器上有一个将单词与值等同的文件或表。假设查理对应 47 美元,约翰对应 3 美元。因此,您可以发送四次查理和四次约翰,而不是发送 200 美元。在服务器上,解释它们的意思并加起来。这可以防止黑客向您的服务器发送任意值,因为他们不知道哪个词对应于什么值。作为额外的安全措施,您也可以有一个类似于第 3 点的等式,并且每 n 天更改一次关键字。最后,你可以在你的应用程序中插入随机无用的源代码,让黑客大海捞针。插入包含来自互联网的片段的随机类,或者只是用于计算诸如斐波那契数列之类的随机事物的函数。确保这些类可以编译,但不会被应用程序的实际功能使用。添加足够多的这些虚假类,黑客将很难找到你的真实代码。

总而言之,没有办法 100% 保护您的应用程序。你可以让它变得更难,但并非不可能。您的网络服务器可能会受到攻击,黑客可以通过监控多个交易金额和您为其发送的关键字来找出您的关键字,黑客可能会煞费苦心地检查源代码并找出哪些代码是伪代码。

你只能反击,但永远不会赢。


不要对发送到服务器的值进行技巧,而是使用 SSL 并正确验证服务器证书。默默无闻的安全通常是一个坏主意。
您可以将随机无用的源代码插入您的应用程序。这也无济于事。这只会使您的应用程序膨胀,同时也使其更难维护。
更难?是的。但它们除了给你一种虚假的安全感外,什么都没有。清除永远不会执行的代码并不难,所以为什么要这样做。
如果您的算法价值一百万美元,那么仅仅因为没有针对 .so 文件的反编译器并不意味着我无法读取程序集 :) 其中大多数都落入了同一个陷阱,只是混淆而不是正确保护自己。混淆只有在不值得攻击者花时间跟进的情况下才有效,所以如果你在这些技术上构建一些东西,你最好希望它们不会流行,否则你会被搞砸,因为突然间你的代码库是不可维护的,而且它需要巨大的改变。
我不明白为什么这个答案有这么高的分数。 3. 和 4. 因为一个人简直是愚蠢的,根本就没有安全感。
t
tylerl

在计算历史上,当您将软件的工作副本提供给攻击者时,从来没有可能阻止软件的逆向工程。而且,在最有可能的情况下,这永远不可能。

了解了这一点,就有了一个明显的解决方案:不要将你的秘密透露给攻击者。虽然您无法保护 APK 的内容,但您可以保护的是您未分发的任何内容。通常,这是用于激活、支付、规则执行和其他有趣代码的服务器端软件。您可以通过不在您的 APK 中分发有价值的资产来保护它们。相反,设置一个服务器来响应来自您的应用程序的请求,“使用”资产(无论这可能意味着什么),然后将结果发送回应用程序。如果此模型不适用于您心目中的资产,那么您可能需要重新考虑您的策略。

此外,如果您的主要目标是防止应用盗版:请不要打扰。您在这个问题上花费的时间和金钱比任何反盗版措施都可能希望拯救您的时间和金钱还要多。解决这个问题的投资回报率是如此之低,以至于考虑它都没有意义。


第一段是最好的答案。如果您的攻击者控制了硬件,他们将始终能够以某种方式击败您的软件。任何真正需要保护的东西都必须保留在您控制的硬件上,就这么简单。最后一段,关于投资回报率,也很到位。
C
Community

应用程序安全的第一条规则:攻击者获得不受限制的物理或电子访问权限的任何机器现在都属于您的攻击者,无论它实际在哪里或您为此支付了什么费用。应用程序安全的第二条规则:任何离开攻击者无法渗透的物理边界的软件现在都属于您的攻击者,无论您花了多少时间编写它。第三条规则:任何离开攻击者无法穿透的物理边界的信息现在都属于你的攻击者,无论它对你有多有价值。

信息技术安全的基础基于这三个基本原则;唯一真正安全的计算机是锁在保险箱里、法拉第笼子里、钢笼子里的那台。有些计算机的大部分使用寿命都处于这种状态。每年(或更少)一次,他们为受信任的根证书颁发机构生成私钥(在众多目击者面前,用摄像头记录他们所在房间的每一英寸)。

现在,大多数计算机都不是在这些类型的环境下使用的;它们实际上是在户外,通过无线电频道连接到互联网。简而言之,它们很容易受到攻击,就像它们的软件一样。因此,他们不值得信任。计算机及其软件必须知道或做某些事情才能发挥作用,但必须注意确保它们永远不会知道或做的事情足以造成损坏(至少不会超出单台机器的范围造成永久性损坏) )。

你已经知道了这一切;这就是您试图保护应用程序代码的原因。但是,这是第一个问题;混淆工具可以使代码变得一团糟,人类试图挖掘,但程序仍然必须运行;这意味着应用程序的实际逻辑流程及其使用的数据不受混淆的影响。只要有一点韧性,攻击者就可以简单地对代码进行去混淆处理,在某些情况下,这甚至是不必要的,因为他正在查看的内容只能是他正在寻找的内容。

相反,您应该努力确保攻击者无法对您的代码做任何事情,无论他多么容易获得它的清晰副本。这意味着,没有硬编码的秘密,因为一旦代码离开您开发它的建筑物,这些秘密就不是秘密了。

您硬编码的这些键值应从应用程序的源代码中完全删除。相反,它们应该位于三个位置之一;设备上的易失性内存,攻击者更难(但仍然不是不可能)获得离线副本;永久在服务器集群上,您可以用铁腕控制对它的访问;或在与您的设备或服务器无关的第二个数据存储中,例如物理卡或用户的内存中(这意味着它最终将在易失性内存中,但不必长时间)。

考虑以下方案。用户将他们的应用程序凭据从内存输入到设备中。不幸的是,您必须相信用户的设备尚未被键盘记录器或木马入侵;在这方面,您可以做的最好的事情是实施多因素安全性,通过记住有关用户使用的设备(MAC/IP、IMEI 等)的难以伪造的识别信息,并通过以下方式提供至少一个额外的通道可以验证在不熟悉的设备上的登录尝试。

凭据一旦输入,就会被客户端软件混淆(使用安全散列),并丢弃纯文本凭据;他们已经达到了他们的目的。混淆后的凭证通过安全通道发送到经过证书验证的服务器,服务器再次对其进行哈希处理以生成用于验证登录有效性的数据。这样,客户端永远不知道实际与数据库值进行比较的是什么,应用服务器永远不知道它接收到的用于验证的明文凭据,数据服务器永远不知道它存储的用于验证的数据是如何产生的,并且一个人在即使安全通道遭到破坏,中间人也只会看到胡言乱语。

一旦经过验证,服务器就会通过通道发回一个令牌。令牌仅在安全会话中有用,由随机噪声或会话标识符的加密(因此可验证)副本组成,客户端应用程序必须在同一通道上将此令牌作为任何请求的一部分发送到服务器做某事。客户端应用程序会多次这样做,因为它不能做任何涉及金钱、敏感数据或任何其他可能对其自身造成破坏的事情;它必须改为要求服务器执行此任务。客户端应用程序永远不会将任何敏感信息写入设备本身的持久内存中,至少不会以纯文本形式;客户端可以通过安全通道向服务器请求对称密钥来加密服务器将记住的任何本地数据;在以后的会话中,客户端可以向服务器请求相同的密钥来解密数据以在易失性存储器中使用。该数据也不会是唯一的副本;客户端存储的任何内容也应该以某种形式传输到服务器。

显然,这使您的应用程序严重依赖 Internet 访问;如果没有与服务器的正确连接和验证,客户端设备将无法执行其任何基本功能。真的,和 Facebook 没有什么不同。

现在,攻击者想要的计算机是您的服务器,因为它而不是客户端应用程序/设备可以让他赚钱或让其他人为他的享受而痛苦。没关系;与尝试保护所有客户端相比,花费金钱和精力来保护服务器会获得更多的收益。该服务器可以位于各种防火墙和其他电子安全系统之后,此外还可以在钢筋、混凝土、钥匙卡/密码访问和 24 小时视频监控之后进行物理保护。您的攻击者确实需要非常复杂才能直接获得对服务器的任何类型的访问权限,并且您将(应该)立即知道它。

攻击者能做的最好的事情就是窃取用户的电话和凭据,并以客户端的有限权限登录服务器。如果发生这种情况,就像丢失信用卡一样,应该指示合法用户拨打 800 号码(最好容易记住,而不是在他们随身携带的钱包、钱包或公文包中的卡片背面与移动设备一起被盗)从他们可以访问的任何电话直接连接到您的客户服务。他们声称他们的手机被盗,提供了一些基本的唯一标识符,并且帐户被锁定,攻击者可能能够处理的任何交易都被回滚,攻击者又回到了原点。


完美的答案!我只是喜欢你用一些加密令牌从服务器获取数据的方式,我认为这之后几乎不可能解码。
我知道这有点晚了,但是如何访问访问服务器部分。像 Microsoft azure 这样的服务为您提供了类似的东西来访问他们的服务器: MobileServiceClient mClient = new MobileServiceClient("MobileServiceUrl", // Replace with the above Site URL "AppKey", // replace with the Application Key this) 几乎任何人有权访问,可以访问他们的服务器端编辑它
@edwinj - 计算机科学中没有不能用另一层间接解决的问题。您的代码片段提供了访问 Azure 移动客户端服务的基本思路;它为 Microsoft 前门的“偷渡”提供了基本级别的安全保护。反过来,您可以添加额外的层,例如在任何服务调用中需要会话密钥(基本上是加密令牌),并且要获得该密钥,他们必须首先结合凭据和加密方案的知识进行身份验证。
最好的答案之一。
m
matthias krull

1. 如何完全避免Android APK的逆向工程?这可能吗?

这是不可能的

2. 如何保护应用程序的所有资源、资产和源代码,使黑客无法以任何方式破解APK文件?

当有人将 .apk 扩展名更改为 .zip 后,解压缩后,有人可以轻松获取所有资源(Manifest.xml 除外),但使用 APKtool 可以获取清单文件的真实内容也是如此。再次,不。

3. 有没有办法让黑客攻击变得更加困难甚至不可能?我还能做些什么来保护我的 APK 文件中的源代码?

再说一次,不,但你可以在某种程度上阻止,也就是说,

从 Web 下载资源并执行一些加密过程

使用预编译的原生库(C、C++、JNI、NDK)

始终执行一些散列(MD5/SHA 密钥或任何其他逻辑)

即使使用 Smali,人们也可以使用您的代码。总而言之,这是不可能的。


@TrevorBoydSmith:当操作系统是开源且可root时,加密没有多大帮助。系统需要一个密钥来解密 APK 并运行东西。如果系统有密钥,并且我可以不受限制地访问系统,那么我知道在哪里可以找到密钥并且可以得到它。意思是我现在也有钥匙。
@TrevorBoydSmith:不过,“如何做”部分扼杀了整个想法。根本没有办法直接执行加密代码;在某些时候,解密的代码必须可用。这意味着(1)必须有一个密钥(我,作为 root,可能可以访问),并且(2)我什至可以在 RAM 中找到清晰的副本,而不必担心加密。
@TrevorBoydSmith:问题是,在这种情况下,您根本无法提高成本以使其不值得。我们在这里不是在谈论暴力破解密钥。我们谈论的是已经拥有它们——操作系统必须有密钥,而我们有操作系统。解决这个问题的唯一方法是使操作系统无法启动。祝你好运;连苹果都管不了。 :)
@TrevorBoydSmith:我不认为提高成本一般是不可能的。我认为(并说)特别是,您的建议是不可能的——因为它是。 MATLAB 不是 Android,它具有 Android 所没有的某些自由。特别是,它本身具有混淆性;隐藏加密密钥要困难得多。安卓做不到。任何拥有源代码的人都会知道密钥隐藏在哪里,并且会在功能发布后的 10 分钟内拥有一个工具来检索它们。不仅可以做到这一点。这简直是微不足道的。
@TrevorBoydSmith:我没有坚持这样的要求。我坚持的是静态、变化、移动等无关紧要。在开源操作系统中,仅靠加密无法保护代码免受任何可能对其进行逆向工程的人的侵害。因为我可以读取进行解密的代码,无论密钥是如何获取、使用和/或存储的,我都可以看到你是如何做到的并复制它——甚至比我能逆转一些超级秘密更容易应用程序代码。
P
Peter Mortensen

100% 避免对 Android APK 进行逆向工程是不可能的,但您可以使用这些方法来避免提取更多数据,例如源代码、APK 中的资产和资源:

使用 ProGuard 混淆应用程序代码 使用 C 和 C++ 的 NDK 将您的应用程序核心和安全部分代码放在 .so 文件中 为了保护资源,不要将所有重要资源包含在带有 APK 的 assets 文件夹中。在应用程序首次启动时下载这些资源。


第三个是真正减轻攻击者的工作。嗅探网络通信比逆向工程更容易。
要解决第三个问题,可以加密下载的内容和/或使用加密连接(例如 SSL/TLS)
加密连接可以防止嗅探或修改流量的人。如果用户自己是恶意的(即他有你的apk并且他试图破解它),他仍然会通过使用你的应用程序来获取内容,以root用户身份提取资源;但是是的,它确实有助于抵御简单的嗅探攻击。
除此之外:4)使用 dexguard 进行更高的混淆,但它是付费的 5)在下载应用程序时使用 OBB 文件进行资产下载,这也有助于减小应用程序大小
S
Sahil Mahajan Mj

开发人员可以采取以下步骤来防止 APK 以某种方式被盗,

最基本的方法是使用 ProGuard 之类的工具来混淆他们的代码,但到目前为止,要完全阻止某人反编译应用程序是相当困难的。

我也听说过一个工具 HoseDex2Jar。它通过在 Android APK 中插入无害的代码来阻止 Dex2Jar,从而混淆和禁用 Dex2Jar 并保护代码免于反编译。它可以以某种方式阻止黑客将 APK 反编译为可读的 Java 代码。

仅在需要时才使用某些服务器端应用程序与应用程序进行通信。它可以帮助防止重要数据。

根本无法完全保护您的代码免受潜在黑客的攻击。不知何故,您可能会使他们反编译您的代码变得困难且令人沮丧。最有效的方法之一是编写本机代码(C/C++)并将其存储为编译库。


HoseDex2Jar 几乎没用。它只会“混淆” dex2jar 并且很容易被阻止。 smali/apktool 等可以很好地与“软管”APK 配合使用。
@NikolayElenkov 你知道 HoseDex2Jar 是如何工作的吗?他们用来避免或混淆 dex2jar。因为我无法将我的 apk 文件上传到网络以使用 HoseDex2Jar。如果我可以做类似 HoseDex2Jar 之类的事情来混淆 dex2jar,那么使用 dex2jar 工具将很难破解。
也许你误解了我的意思:HoseDex2Jar 所做的是重新打包你的 APK,这样流行的 dex2jar 工具就不能(开箱即用)逆转它。但是其他工具可以,并且通常很容易击败它。使用它没有任何意义。没有人提到 Dexguard 我的东西(ProGuard 的作者;不是免费的),但它是工作看的。它比“常规”混淆做了更多的事情。
C++永远无法逆转?这很困难,但可能。并且有像 hex-rays.com/products/decompiler/index.shtml 这样的工具可以帮助您(是的,他们有 ARM 版本。不是那么容易获得)。
是的,@VikartiAnatra:我还提到了不知何故,你可以让它变得困难
P
Peter Mortensen

您可以尝试以下几种方法:

使用混淆和 ProGuard 等工具。加密部分源代码和数据。在应用程序中使用专有的内置校验和来检测篡改。引入代码避免在调试器中加载,即让应用程序具有检测调试器并退出/杀死调试器的能力。将身份验证分离为在线服务。使用应用程序多样性 在对设备进行身份验证之前,使用指纹技术,例如,来自不同子系统的设备的硬件签名。


P
Peter Mortensen

1. 如何完全避免Android APK的逆向工程?这可能吗?

不可能的

2. 如何保护应用程序的所有资源、资产和源代码,使黑客无法以任何方式破解APK文件?

不可能的

3. 有没有办法让黑客攻击变得更加困难甚至不可能?我还能做些什么来保护我的 APK 文件中的源代码?

更难——可能,但实际上对于普通用户来说会更难,他们只是在谷歌上搜索黑客指南。如果有人真的想破解您的应用程序 - 它迟早会被破解。


C
Community

1. 如何完全避免Android APK的逆向工程?这可能吗?

那是不可能的

2. 如何保护应用程序的所有资源、资产和源代码,使黑客无法以任何方式破解APK文件?

开发人员可以采取措施,例如使用 ProGuard 之类的工具来混淆他们的代码,但到目前为止,要完全阻止某人反编译应用程序是相当困难的。

这是一个非常棒的工具,可以增加“逆向”代码的难度,同时缩小代码的占用空间。

集成的 ProGuard 支持:ProGuard 现在与 SDK 工具一起打包。开发人员现在可以将他们的代码混淆为发布构建的一个集成部分。

3. 有没有办法让黑客攻击变得更加困难甚至不可能?我还能做些什么来保护我的 APK 文件中的源代码?

在研究过程中,我了解了 HoseDex2Jar。该工具将保护您的代码免于反编译,但似乎无法完全保护您的代码。

一些有用的链接,您可以参考它们。

Proguard、Android 和许可服务器

保护 Android LVL 应用程序

Stack Overflow 问题 真的不可能保护 Android 应用免受逆向工程吗?

Stack Overflow 问题 如何防止对 Android APK 文件进行逆向工程以保护代码?


P
Peter Mortensen

这里的主要问题是 dex 文件是否可以反编译,答案是它们可以是“某种”。有像 dedexersmali 这样的反汇编程序。

ProGuard,正确配置,会混淆您的代码。 DexGuard 是 ProGuard 的商业扩展版本,可能会有所帮助。但是,您的代码仍然可以转换为 smali,具有逆向工程经验的开发人员将能够从 smali 中弄清楚您在做什么。

也许选择一个好的许可证并以最好的方式依法执行。


附带说明(免责声明:IANAL)-许可证不会在所有情况下保护所有司法管辖区的应用程序(例如,在欧洲的某些国家/地区,它允许拆卸以增加兼容性)。
第二个链接断了一半。
s
straya

你的客户应该雇佣一个知道自己在做什么、能做出正确决定并能指导你的人。

上面谈论你有能力改变后端的事务处理系统是荒谬的——你不应该被允许做这样的架构改变,所以不要指望能够做到。

我对此的理由:

由于您的域是支付处理,因此可以安全地假设 PCI DSS 和/或 PA DSS(以及潜在的州/联邦法律)对您的业务很重要 - 要合规,您必须证明您是安全的。要不安全,然后(通过测试)发现您不安全,然后修复、重新测试等,直到可以在合适的级别验证安全性 = 昂贵、缓慢、高风险的成功方式。做正确的事,提前思考,让有经验的人才投入工作,以安全的方式开发,然后测试、修复(更少)等等(更少),直到可以在合适的水平上验证安全性 = 便宜、快速、低风险的成功之路。


P
Peter Mortensen

作为在支付平台上广泛工作的人,包括一个移动支付应用程序 (MyCheck),我想说您需要将此行为委托给服务器。支付处理器(无论是哪个)的用户名或密码都不应存储或硬编码在移动应用程序中。这是您最不想要的,因为即使您混淆了代码,也可以理解源代码。

此外,您不应在应用程序上存储信用卡或支付令牌。一切都应该再次委托给您构建的服务。它还可以让您以后更轻松地符合 PCI 标准,并且信用卡公司不会对您嗤之以鼻(就像他们为我们所做的那样)。


K
Kaz

如果我们想让逆向工程(几乎)不可能,我们可以将应用程序放在一个高度防篡改的芯片上,该芯片在内部执行所有敏感的东西,并与一些协议进行通信,以使主机上的控制 GUI 成为可能。即使是防篡改芯片也不是 100% 防裂的;他们只是设定了比软件方法高得多的标准。当然,这很不方便:应用程序需要一些小的 USB 疣来固定要插入设备的芯片。

这个问题并没有揭示出如此嫉妒地想要保护这个应用程序的动机。

如果目的是通过隐藏应用程序可能存在的任何安全漏洞(已知或其他)来提高支付方式的安全性,那是完全错误的。如果可行的话,安全敏感位实际上应该是开源的。您应该让任何审查您的应用程序的安全研究人员尽可能轻松地找到这些位并仔细检查他们的操作,并与您联系。支付应用程序不应包含任何嵌入式证书。也就是说,不应该有服务器应用程序仅仅因为设备具有工厂的固定证书而信任它。支付交易应仅根据用户的凭据进行,使用正确设计的端到端身份验证协议,该协议排除信任应用程序、平台或网络等。

如果目标是防止克隆,没有防篡改芯片,那么您就无法保护程序不被逆向工程和复制,因此有人将兼容的支付方式合并到他们自己的应用程序中,给上升为“未经授权的客户”。有一些方法可以使开发未经授权的客户变得困难。一种是基于程序完整状态的快照创建校验和:所有状态变量,适用于所有内容。 GUI,逻辑,等等。克隆程序不会具有完全相同的内部状态。当然,它是一个状态机,具有相似的外部可见状态转换(可以通过输入和输出观察到),但内部状态几乎不一样。服务器应用程序可以询问程序:您的详细状态是什么? (即给我所有内部状态变量的校验和)。这可以与在服务器上并行执行的虚拟客户端代码进行比较,通过真正的状态转换。第三方克隆必须复制正版程序的所有相关状态更改才能给出正确的响应,这将阻碍其开发。


S
Sarel Botha

这里其他赞成的答案是正确的。我只想提供另一种选择。

对于您认为重要的某些功能,您可以在您的应用程序中托管 WebView 控件。然后,该功能将在您的 Web 服务器上实现。它看起来像是在您的应用程序中运行。


@Sarel Botha 是的,对于 IMP 屏幕,我已经使用了 webview,是的,这也是维护安全的一种方式,我接受你的回答。
我只是想到了WebView LMAO。
P
Peter Mortensen

在这里同意@Muhammad Saqib:https://stackoverflow.com/a/46183706/2496464

@Mumair 提供了良好的起步步骤:https://stackoverflow.com/a/35411378/474330

假设您分发到用户设备的所有内容都属于用户,这始终是安全的。干净利落。您也许可以使用最新的工具和程序来加密您的知识产权,但没有办法阻止有决心的人“研究”您的系统。即使当前的技术可能使他们难以获得不必要的访问权限,明天或什至下一小时可能会有一些简单的方法!

因此,这里出现了等式:

谈到金钱,我们总是假设客户是不受信任的。

即使在游戏内经济这么简单。 (尤其是在游戏中!那里的“老练”用户更多,漏洞在几秒钟内蔓延!)

我们如何保持安全?

大多数(如果不是全部)我们的关键处理系统(当然还有数据库)都位于服务器端。在客户端和服务器之间,存在加密通信、验证等。这就是瘦客户端的想法。


P
Peter Mortensen

我建议你看看 Protect Software Applications from Attacks。这是一项商业服务,但我朋友的公司使用了它,他们很高兴使用它。


P
Peter Mortensen

没有办法完全避免 APK 文件的逆向工程。为了保护应用程序资产、资源,您可以使用加密。

如果不解密,加密将使其更难使用。选择一些强大的加密算法会使破解更加困难。

在主逻辑中添加一些恶搞代码,使其更难破解。

如果您可以用任何母语编写您的关键逻辑,那肯定会更难反编译。

使用任何第三方安全框架,例如 Quixxi


重新“用任何母语编写你的关键逻辑”:在编译之前混淆代码不是更容易吗?
P
Peter Mortensen

Android 7.0 (Nougat) 中的 APK 签名方案 v2

PackageManager 类现在支持使用 APK 签名方案 v2 验证应用程序。 APK 签名方案 v2 是一种全文件签名方案,通过检测对 APK 文件的任何未经授权的更改,显着提高了验证速度并加强了完整性保证。

为了保持向后兼容性,APK 必须先使用 v1 签名方案(JAR 签名方案)进行签名,然后才能使用 v2 签名方案进行签名。使用 v2 签名方案,如果您在使用 v2 方案签名后使用附加证书对 APK 进行签名,则验证将失败。

APK 签名方案 v2 支持将在稍后的 N 开发者预览版中提供。

http://developer.android.com/preview/api-overview.html#apk_signature_v2


Apk 签名 v2 仅防止资源被篡改,但不会使逆向工程变得更加困难……
此外,您可以删除签名并重新签名。 v2 签名只是 APK 文件中的一个数据块。
P
Peter Mortensen

基本上是不可能的。这永远不可能。不过,还是有希望的。您可以使用 obfuscator 来实现,这样一些常见的攻击就更难执行了,包括:

重命名方法/类(所以在反编译器中你会得到像 aa 这样的类型) 混淆控制流(所以在反编译器中代码很难阅读) 加密字符串和可能的资源

我敢肯定还有其他的,但这是主要的。我在一家名为 PreEmptive Solutions 的公司工作,使用 .NET 混淆器。他们还有一个适用于 Android 的 Java 混淆器以及一个名为 DashO 的混淆器。

不过,混淆总是要付出代价的。值得注意的是,性能通常更差,并且通常需要一些额外的发布时间。但是,如果您的知识产权对您来说极其重要,那么它通常是值得的。

否则,您唯一的选择就是让您的 Android 应用程序直接通过服务器,该服务器托管您的应用程序的所有真实逻辑。这有其自身的问题,因为这意味着用户必须连接到 Internet 才能使用您的应用程序。

此外,不只是安卓有这个问题。这是每个应用商店的问题。这只是获取包文件的难度问题(例如,我不相信在 iPhone 上这很容易,但仍然有可能)。


不幸的是,如果有人破解客户端(应用程序),他们将能够看到通信格式并创建自己的服务器:(
P
Peter Mortensen

源代码和资源的 100% 安全在 Android 中是不可能的。但是,你可以让逆向工程师有点困难。您可以在以下链接中找到更多详细信息:

访问 Saving constant values securelyMobile App Security Best Practices for App Developers


P
Peter Mortensen

如果您的应用程序如此敏感,那么您应该考虑服务器端的支付处理部分。尝试更改您的付款处理算法。仅将 Android 应用程序用于收集和显示用户信息(即帐户余额),而不是在 Java 代码中处理付款,使用带有加密参数的安全 SSL 协议将此任务发送到您的服务器。创建一个完全加密且安全的 API 来与您的服务器进行通信。

当然,它也可能被黑客入侵,它与源代码保护无关,但请考虑它是另一个安全层,以使黑客更难欺骗您的应用程序。


P
Peter Mortensen

完全避免逆向工程是不可能的,但是通过使它们在内部变得更复杂,您可以使攻击者更难看到应用程序的清晰操作,这可能会减少攻击向量的数量。

如果应用程序处理高度敏感的数据,各种技术会增加逆向工程代码的复杂性。一种技术是使用 C/C++ 来限制攻击者的简单运行时操作。有大量非常成熟且易于集成的 C 和 C++ 库,并且 Android 提供了 JNI

攻击者必须首先绕过调试限制才能在低级别攻击应用程序。这进一步增加了攻击的复杂性。 Android 应用程序应在应用程序清单中设置 android:debuggable=”false”,以防止攻击者或恶意软件轻松操纵运行时。

跟踪检查 - 应用程序可以确定它当前是否正在被调试器或其他调试工具跟踪。如果被跟踪,应用程序可以执行任意数量的可能的攻击响应操作,例如丢弃加密密钥以保护用户数据、通知服务器管理员或其他此类响应以试图保护自己。这可以通过检查进程状态标志或使用其他技术来确定,例如比较 ptrace attach 的返回值、检查父进程、进程列表中的黑名单调试器或比较程序不同位置的时间戳。

优化 - 为了隐藏高级数学计算和其他类型的复杂逻辑,利用编译器优化可以帮助混淆目标代码,使其不易被攻击者反汇编,使其攻击者更难理解特定代码。在 Android 中,这可以通过使用带有 NDK 的本机编译库来更轻松地实现。此外,使用 LLVM 混淆器或任何保护器 SDK 将提供更好的机器代码混淆。

剥离二进制文件 – 剥离本机二进制文件是增加攻击者查看应用程序低级函数构成所需的时间和技能水平的有效方法。通过剥离二进制文件,二进制文件的符号表被剥离,因此攻击者无法轻松调试或反向工程应用程序。您可以参考 GNU/Linux 系统上使用的技术,例如 sstriping 或使用 UPX

最后,您必须注意混淆和 ProGuard 等工具。


你这是从哪里抄来的?来自博文 Increase Code Complexity and Use Obfuscation
P
Peter Mortensen

我知道一些银行应用程序正在使用 DexGuard,它提供类、字符串、资产、资源文件和本机库的混淆和加密。


P
Peter Mortensen

我可以看到这个问题有很好的答案。除此之外,您还可以使用 Facebook ReDex 来优化代码。 ReDex 在 .dex 级别上工作,而 ProGuard 作为 .class 级别。


P
Peter Mortensen

工具:在您的应用程序中使用 ProGuard,可以限制对您的应用程序进行逆向工程


我总是使用 Proguard,它有助于限制逆向工程。
P
Peter Mortensen

当你把它放在最终用户手中时,没有什么是安全的,但一些常见的做法可能会使攻击者更难窃取数据。

将您的主要逻辑(算法)放在服务器端。

与服务器和客户端通信;确保服务器和客户端之间的通信通过 SSL 或 HTTPS 得到保护;或使用其他技术生成密钥对算法(ECC 和 RSA)。确保敏感信息保持端到端加密。

使用会话并在特定时间间隔后使它们过期。

加密资源并按需从服务器获取它们。

或者您可以制作一个混合应用程序,通过 webview 访问系统保护服务器上的资源 + 代码

多种方法;很明显,您必须在性能和安全性之间做出牺牲。


P
Peter Mortensen

Trusted Platform Module (TPM) 芯片不是应该为您管理受保护的代码吗?

它们在个人电脑(尤其是苹果电脑)上变得越来越普遍,而且它们可能已经存在于今天的智能手机芯片中。不幸的是,还没有任何操作系统 API 可以使用它。希望有一天,Android 会增加对此的支持。这也是清除内容 DRM(Google 正在为 WebM 开发)的关键。


P
Peter Mortensen

如何保护应用程序的所有资源、资产和源代码,使黑客无法以任何方式破解 APK 文件?

APK 文件受 SHA-1 算法保护。您可以在 APK 的 META-INF 文件夹中看到一些文件。如果您提取任何 APK 文件并更改其任何内容并再次压缩它,当您在 Android 机器上运行该新 APK 文件时,它将无法工作,因为 SHA-1 哈希值永远不会匹配。


这是真实的;但是退出 APK(使用不同的证书)很简单,一切都会重新开始。可以从应用程序本身检查哪个签名已用于对 APK 进行签名,如果证书更改,则会出错,但在应用程序之外编辑此代码只是稍微不那么简单。
这可能会阻止 android 设备运行修改后的代码,但您仍然可以轻松地提取相关代码并在您想要的 PC 上编写新代码。
u
user3742860

当他们在手机上安装该应用程序时,他们可以完全访问它的内存。因此,如果您想防止它被黑客入侵,您可以尝试使其无法使用调试器直接获取静态内存地址。如果他们有地方可以写并且有限制,他们可以进行堆栈缓冲区溢出。所以尽量做到这一点,当他们写东西时,如果你必须有一个限制,如果他们发送的字符多于限制,如果(输入>限制)然后忽略,所以他们不能把汇编代码放在那里。