如何避免对APK文件进行逆向工程

How to avoid reverse engineering of an APK file

提问人:sachin003 提问时间:12/13/2012 最后编辑:Peter Mortensensachin003 更新时间:11/17/2021 访问量:265192

问:

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

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

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

但是,Android 组件的名称保持不变,某些代码(例如应用中使用的键值对)保持不变。根据 Proguard 文档,该工具无法对 Manifest 文件中提到的组件进行模糊处理。

现在我的问题是:

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

评论

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

答:

406赞 Bhavesh Patadiya 12/13/2012 #1

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

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

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

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

不过,您可以采取不同的技巧来使黑客攻击更加困难。例如,使用模糊处理(如果是 Java 代码)。这通常会大大减慢逆向工程的速度。

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

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

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

<project>/libs/armeabi/libstuff.so

评论

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

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

不可能的

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

不可能的

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

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

44赞 ρяσѕρєя K 12/13/2012 #3

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

  1. 使用 ProGuard 对应用程序代码进行模糊处理

  2. 使用 NDK 使用 C 和 C++ 将应用程序核心和安全部分代码放入文件中.so

  3. 要保护资源,请勿将所有重要资源都包含在 APK 的 assets 文件夹中。在应用程序首次启动时下载这些资源。

评论

14赞 totten 1/26/2015
第三,真正减轻了攻击者的工作。嗅探网络通信比逆向工程更容易。
0赞 10/16/2015
为了解决第三个问题,可以对下载的内容进行加密和/或使用加密连接(例如SSL / TLS)
2赞 Kevin Lee 3/14/2016
加密连接可防止嗅探或修改流量的人。在用户本身是恶意的情况下(即他有你的apk,他试图破解它),他仍然会通过使用你的应用程序来获取内容,以root用户的身份提取资源;但是,是的,它确实有助于防止简单的嗅探攻击。
0赞 Ashok Kumar 7/3/2019
除此之外:4)使用dexguard进行更高的混淆,但它是付费的 5)在下载应用程序时使用OBB文件进行资产下载,这也将有助于减小应用程序的大小
140赞 Raghav Sood 12/13/2012 #4

AFAIK,您不能再保护 /res 目录中的文件,因为它们现在受到保护。

但是,您可以采取一些步骤来保护您的源代码,或者至少保护它的作用(如果不是所有)。

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

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

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

评论

153赞 Nikolay Elenkov 12/13/2012
与其对发送到服务器的值进行技巧操作,不如使用 SSL 并正确验证服务器证书。通过隐蔽性实现安全性通常是一个坏主意。
62赞 Anirudh Ramanathan 12/13/2012
您可以将随机无用的源代码插入到您的应用程序中。这也无济于事。这只会让你的应用程序膨胀,同时也使它更难维护。
7赞 Anirudh Ramanathan 12/13/2012
难?是的。但它们除了给你一种虚假的安全感之外,什么都没有给你。清除从未执行的代码并不难,那么为什么要这样做呢?
20赞 Phoshi 12/13/2012
如果你的算法价值一百万美元,那么仅仅因为没有文件的反编译器并不意味着我不能读取汇编:)其中大多数都落入了同样的陷阱,只是混淆了而不是适当地保护自己。混淆只有在不值得攻击者花时间跟进时才有效,所以如果你在这些技术上构建一些东西,你最好希望它们不会流行,否则你就完蛋了,因为突然之间你的代码库无法维护,它需要巨大的改变。.so
29赞 Matti Virkkunen 11/9/2013
我不明白为什么这个答案有这么高的分数。3. 和 4.因为一个人只是愚蠢的,根本不等于安全。
21赞 Abhishek Sabbarwal 12/13/2012 #5

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

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

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

评论

4赞 Maciej Piechotka 12/13/2012
作为旁注(免责声明:IANAL) - 许可证不会在所有情况下保护所有司法管辖区的应用程序(例如,在欧洲的一些国家/地区,允许拆卸以增加兼容性)。
0赞 Peter Mortensen 7/23/2021
第二个链接已断开一半。
69赞 Mohammed Azharuddin Shaikh 12/13/2012 #6

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

这是不可能的

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

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

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

同样,不,但您可以防止到某种程度,即,

  • 从 Web 下载资源并执行一些加密过程
  • 使用预编译的本机库(C、C++、JNI、NDK)
  • 始终执行一些哈希(MD5/SHA 密钥或任何其他逻辑)

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

评论

9赞 cHao 12/14/2012
@TrevorBoydSmith:当操作系统是开源且可根的时,加密没有多大帮助。系统需要一个密钥才能解密APK并运行内容。如果系统有钥匙,而我可以不受限制地访问系统,那么我知道在哪里可以找到钥匙并可以到达它。这意味着我现在也有钥匙了。
4赞 cHao 12/15/2012
@TrevorBoydSmith:不过,是“如何做”的部分扼杀了整个想法。根本没有办法直接执行加密代码;在某些时候,解密的代码必须可用。这意味着 (1) 必须有一个密钥(我作为 root 用户可能有权访问),并且 (2) 我甚至可以在 RAM 中找到明文副本,无论如何都不必担心加密。
3赞 cHao 1/9/2013
@TrevorBoydSmith:问题是,在这种情况下,你根本无法将成本提高到足以使其不值得的程度。我们在这里不是在谈论暴力破解密钥;我们谈论的是已经拥有它们——操作系统必须有密钥,而我们有操作系统。解决此问题的唯一方法是使操作系统无法根。祝你好运;即使是苹果也无法管理它。:)
3赞 cHao 1/10/2013
@TrevorBoydSmith:我不认为提高成本总体上是不可能的。我认为(并特别说),你的建议是不可能的——因为它是。MATLAB 不是 Android,它具有 Android 所没有的某些自由。特别是,它有混淆;隐藏加密密钥要困难得多。Android 无法做到这一点。任何拥有源代码的人都会知道密钥的藏身之处,并且会有一个工具可以在功能发布后的 10 分钟内检索它们。这不仅是可能的;这是彻头彻尾的微不足道
6赞 cHao 1/11/2013
@TrevorBoydSmith:我没有坚持过这种事情。我坚持认为,静态、变化、移动等都无关紧要。在开源操作系统中,仅靠加密无法保护代码免受任何可能对其进行逆向工程的人的侵害。因为我可以读取解密的代码,无论密钥是如何获取、使用和/或存储的,我都可以看到你是如何做到的并复制它——甚至比我逆转一些超级机密的应用程序代码更容易。
135赞 tylerl 12/13/2012 #7

在计算史上,从来没有人能够阻止软件的逆向工程,因为你将软件的工作副本提供给你的攻击者。此外,最有可能的是,这永远是不可能的

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

此外,如果您的主要目标是防止应用程序盗版:甚至不要打扰。你已经在这个问题上花费了更多的时间和金钱,超过了任何反盗版措施可能希望拯救你的时间。解决这个问题的投资回报率如此之低,以至于连想都没意义。

评论

23赞 Daniel Pryden 12/14/2012
第一段是最好的答案。如果你的攻击者控制了硬件,他们总是能够以某种方式击败你的软件。任何真正需要保护的东西都必须保留在你控制的硬件上,就这么简单。最后一段,关于投资回报率,也很到位。
5赞 Talha 12/13/2012 #8

我建议你看看保护软件应用程序免受攻击。这是一项商业服务,但我朋友的公司使用了它,他们很高兴使用它。

12赞 straya 12/13/2012 #9

您的客户应该聘请知道自己在做什么、可以做出正确决定并可以指导您的人。

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

我对此的理由:

由于您的域名是支付处理,因此可以安全地假设 PCI DSS 和/或 PA DSS(以及潜在的州/联邦法律)将对您的业务产生重要影响 - 为了合规,您必须证明您是安全的。要不安全,然后(通过测试)发现你不安全,然后修复、重新测试等,直到安全性可以在合适的水平上得到验证=昂贵、缓慢、高风险的成功方式。要做正确的事情,前期要认真思考,让有经验的人才投入到工作中,以安全的方式进行开发,然后测试、修复(更少)等(更少),直到安全性可以在合适的水平上得到验证=廉价、快速、低风险的成功方式。

3赞 Earlz 12/13/2012 #10

基本上这是不可能的。这永远不可能。但是,还是有希望的。您可以使用混淆器来制作它,因此一些常见的攻击更难执行,包括:

  1. 重命名方法/类(因此在反编译器中,您可以获得类似a.a)
  2. 混淆控制流(因此在反编译器中,代码很难阅读)
  3. 加密字符串和可能的资源

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

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

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

此外,不仅仅是 Android 有这个问题。这是每个应用商店的问题。这只是获取包文件的难度问题(例如,我认为在 iPhone 上并不容易,但仍有可能)。

评论

0赞 Jocky Doe 1/10/2018
不幸的是,如果有人入侵客户端(应用程序),他们将能够看到通信格式并创建自己的服务器:(
103赞 KeithS 12/14/2012 #11

应用安全的第一条规则:攻击者获得不受限制的物理或电子访问权限的任何计算机现在都属于攻击者,无论它实际位于何处或您为此付出了什么。

应用安全的第二条规则:任何离开攻击者无法渗透的物理边界的软件现在都属于攻击者,无论您花了多少时间对其进行编码。

第三条规则:任何离开攻击者无法穿透的物理边界的信息现在都属于攻击者,无论它对您有多大价值。

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

现在,大多数计算机不在这些类型的环境中使用;它们在户外,通过无线电信道连接到互联网。简而言之,他们很脆弱,他们的软件也是如此。因此,他们不值得信任。计算机及其软件必须知道或做某些事情才能有用,但必须注意确保它们永远不会知道或做足以造成损害的事情(至少不会造成超出该台机器范围的永久性损害)。

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

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

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

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

输入凭据后,客户端软件(使用安全哈希)会对其进行模糊处理,纯文本凭据将被丢弃;他们已经达到了他们的目的。经过模糊处理的凭据通过安全通道发送到经过证书身份验证的服务器,服务器再次对它们进行哈希处理,以生成用于验证登录有效性的数据。这样一来,客户端永远不知道实际与数据库值相比的内容,应用服务器永远不知道它收到的用于验证的内容背后的明文凭据,数据服务器永远不知道它存储的用于验证的数据是如何生成的,而中间的人即使安全通道遭到破坏,也只能看到胡言乱语。

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

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

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

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

评论

1赞 dharmendra 7/15/2013
完美答案!!我只是喜欢你用一些加密令牌从服务器获取数据的方式,我认为这在那之后几乎不可能解码。
0赞 edwinj 8/6/2015
我知道这有点晚了,但是访问访问服务器部分呢?像 Microsoft azure 这样的服务为你提供了这样的东西来访问他们的服务器: MobileServiceClient mClient = new MobileServiceClient( “MobileServiceUrl”, // 替换为上面的站点 URL “AppKey”, // 替换为应用程序密钥 this) 并且几乎任何有权访问它的人都可以访问他们的服务器端编辑它
0赞 KeithS 1/25/2018
@edwinj - 在计算机科学中,没有问题不能用另一层间接来解决。代码片段提供了访问 Azure 移动客户端服务的基本思路;它提供了针对Microsoft前门“偷渡”的基本安全级别。反过来,您可以添加其他层,例如在任何服务调用中都需要会话密钥(基本上是加密令牌),并且要获取该密钥,它们必须首先使用凭据和加密方案的组合进行身份验证。
1赞 debo.stackoverflow 5/22/2019
最好的答案之一。
9赞 Sarel Botha 12/14/2012 #12

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

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

评论

0赞 sachin003 12/17/2012
@Sarel Botha 是的,对于 IMP 屏幕,我已经使用过 webview,是的,这也是维护安全性的一种方式,我接受你的回答。
0赞 Example person 9/26/2020
我只是想到了 WebView LMAO。
11赞 Kaz 12/14/2012 #13

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

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

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

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

23赞 RobinHood 12/14/2012 #14

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

这是不可能的

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

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

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

集成 ProGuard 支持:ProGuard 现在与 SDK 工具打包在一起。开发人员现在可以将其代码作为发布版本的集成部分进行模糊处理。

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

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

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

11赞 Itai Sagi 12/16/2012 #15

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

此外,您不应在应用程序上存储信用卡或支付令牌。同样,一切都应该委托给您构建的服务。它还将使您以后更容易地符合PCI标准,并且信用卡公司不会像他们为我们所做的那样让您喘不过气来。

1赞 Jeegar Patel 12/19/2012 #16

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

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

评论

0赞 David Given 4/24/2013
这是真的;但是重新签署 APK(使用不同的证书)是微不足道的,一切都会再次起作用。可以从应用程序本身中检查哪个签名用于对 APK 进行签名,如果证书发生更改,则会出现错误,但从应用程序中编辑此代码只是稍微不那么简单。
0赞 Sarel Botha 2/14/2014
这可能会阻止 android 设备运行修改后的代码,但您仍然可以轻松提取相关代码并在 PC 上编写新代码,以执行您想要的操作。
31赞 Shan 1/1/2013 #17

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

  1. 使用混淆ProGuard 等工具。
  2. 加密源代码和数据的某些部分。
  3. 在应用程序中使用专有的内置校验和来检测篡改。
  4. 引入代码以避免在调试器中加载,即让应用能够检测调试器并退出/终止调试器。
  5. 将身份验证分离为联机服务。
  6. 使用应用程序多样性
  7. 使用指纹技术,例如,在对设备进行身份验证之前,使用来自不同子系统的设备的硬件签名。
2赞 robUx4 1/8/2013 #18

受信任的平台模块 (TPM) 芯片不应该为你管理受保护的代码吗?

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

-1赞 stuckedunderflow 4/5/2013 #19

只是对上面已经很好的答案的补充。

我知道的另一个技巧是将有价值的代码存储为 Java 库。然后将该库设置为您的 Android 项目。作为 C .so 文件会很好,但 Android Lib 可以。

这样,存储在 Android 库中的这些有价值的代码在反编译后将不可见。

评论

5赞 Raghav Sood 4/11/2013
它们将可见,只是在不同的包下。
0赞 stuckedunderflow 4/11/2013
奇怪的是,在我的情况下不是。我有 4 个库。Google 许可 + Pretty Time + android.support.v4.ViewPagerIndicator + My Internal Lib 来自设置为库的 Android 项目。此 Android 项目作为 Lib 不可见。而其他 3 个是可见的。
0赞 Raghav Sood 4/11/2013
如果您反编译 classes.dex 文件并将其打开,它将可见
0赞 stuckedunderflow 4/14/2013
@Raghav,是的,我使用 dex2jar 和 jd 来模拟它。但我找不到它。你试过吗?
-3赞 user2563366 7/16/2013 #20

基本上,有五种方法可以保护您的APK文件:

  1. 隔离 Java 程序,
  2. 加密类文件,
  3. 转换为本机代码,
  4. 代码混淆
  5. 在线加密

我建议您使用在线加密,因为它既安全又方便。你不需要花太多时间来实现这一点。

例如APK Protect。这是一个 APK 的在线加密网站。它提供了Java代码和C++代码保护,以实现反调试和反编译效果。操作过程简单易行。

评论

9赞 1/13/2014
他在问这是否可能。你说是的,这很容易。你错了。这不可能。
0赞 user3742860 9/3/2015 #21

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

-5赞 cregox 11/12/2015 #22

不,做不到!

你的三个问题围绕着 100% 保护应用程序不被阅读。从原则上讲,这是做不到的。而且,你投入的越多,对你来说,它的体验就越差,最终,对于任何试图只读取你的应用程序的机器来说,它都会越糟糕。想想HTTPS本质上比HTTP慢得多,因为需要处理安全层和数学。层数越多,有人拆开包装的速度就越慢,但绝不是不可能的,因为你实际上希望它被阅读,这就是为什么它被制作成包装并交付的原因。

一个简单的类比是将任何给定的隐藏对象交给某人。如果那个人能看到里面的东西,他们也可以拍照并做一些完全类似的事情。更重要的是,在代码的情况下,足够敬业的人可以创建该对象的精确副本,即使使用完全不同的过程。

假安全感

作为一个处理应用程序,你不应该关心你认为你可以在二进制代码中创建的任何安全性,以及整个系统的完整性。假设来自客户端的任何内容都可能很快变得不可靠。保持应用程序简单、流畅和快速。相反,还要担心您的服务器。例如,制定严格的通信协议以轻松监控服务器。这是我们唯一可以依靠的。

现在,请继续与我讨论如何改进服务器端的另一个想法......

嘴巴在钱上

我正在开发一个支付处理应用程序

谷歌通过使用一种简单的财务方法来“保护”谷歌浏览器,在避免恶意黑客方面非常成功,我引用:

我们为参与者提供 50,000 美元的常设奖励,这些参与者可能会在访客模式下使用设备持久性来破坏 Chromebook 或 Chromebox

要真正接近 100% 的“安全性”,我们最好的选择是为我们的钱物有所值而选择正确的战斗。也许大多数人无法提供 50k 的奖励,但即使是 1k 的奖励也可以走很长的路,而且它也比将这笔钱投入到设计任何类型的错误捕手上要便宜得多。

投资人工智能来识别资金流动模式,预测潜在风险并发现小漏洞,也比试图通过任何工程来预防两者要便宜得多。

明显的例外

当然,这并不能保护我们免受“疯子”和“幸运恶作剧者”的侵害......但什么都不会。同时,如果设置得当,后一组在内部的时间很少,而系统会重新调整。而一个疯子,我们只需要担心,以防它大到足以成为克星。无论如何,这将是一个伟大的故事!:)

太长;没读过;

换句话说,也许问自己一个更好的问题,而不是“如何避免在我的应用程序中进行逆向工程”,可能是“如何设计一个更安全的支付处理系统”,并专注于你真正想要实现的目标:一个安全的系统

很久以前,我试着写更多关于上述所有内容的文章,以回答诸如为什么我将“安全”和“保护”放在引号中(它们的真正含义是什么?

评论

0赞 Sebi 11/17/2019
"换句话说,与其问“如何避免逆向工程”,不如问“如何设计一个防弹支付处理应用程序”。- 我不认为这是个好建议,特别是如果你建议在 StackOverflow 上提问。
0赞 cregox 11/17/2019
@Sebi也许那里的“系统”比“应用程序”更适合。但是,是的,我现在可以看到这句话在任何情况下听起来多么令人困惑。我仍然不明白的是,为什么人们对这个答案投了如此多的反对票,而没有任何评论。
2赞 Sebi 11/18/2019
郑重声明,我没有对这个答案投反对票。我认为人们可能已经投了反对票,因为答案建议花钱来获得答案——在我看来,如果你愿意投资,这可能是很好的补充帮助。我绝对同意你的最后一段,我认为 security.stackexchange.com 可能是询问整体设置的好地方。
0赞 cregox 11/21/2019
啊,好吧。。。现在我明白了,哈哈。是的,我什至没有考虑过这种解释!我会试着把它编辑掉,看看会发生什么......谢谢伙计。 :D
0赞 cregox 1/6/2020
现在是-3,我想以前是-5。不记得或真的不在乎......这一次,我的注意力被吸引到这里,因为一些被批准编辑成普通大小写,而不是我目前最喜欢的小写样式 #locaws(更多关于它的信息,见 cregox.net),我只是拒绝了它,以在帖子上保留我的身份(并导致我进入了一个令人讨厌的衍生任务 chat.stackoverflow.com/transcript/message/48255477#48255477)。就像在那种情况下一样,我在这里发表评论除了报告之外没有充分的理由。干杯!🥴😘
3赞 Sanket Prabhu 11/26/2015 #23

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

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

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

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

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

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

最后,您必须了解混淆和 ProGuard 等工具。

评论

0赞 Peter Mortensen 7/23/2021
你从哪里抄袭的?摘自博客文章增加代码复杂性并使用混淆
3赞 mumair 2/15/2016 #24

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

  • 把你的主要逻辑(算法)放在服务器端。
  • 与服务器和客户端通信;确保服务器和客户端之间的通信通过SSL或HTTPS进行保护;或使用其他技术进行密钥对生成算法(ECCRSA)。确保敏感信息保持端到端加密
  • 使用会话并在特定时间间隔后使其过期。
  • 加密资源并按需从服务器获取资源。
  • 或者,您可以制作一个混合应用程序,通过webview访问系统,保护服务器上的资源+代码

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

4赞 thiagolr 5/16/2016 #25

APK 签名方案 v2 在 Android 7.0 (Nougat)

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

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

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

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

评论

2赞 Louis CAD 10/21/2017
Apk 签名 v2 只能防止资源被篡改,但不会使逆向工程变得更加困难......
1赞 Robert 3/1/2018
此外,您只需删除签名并重新签名即可。v2 签名只是 APK 文件中的一个数据块。
4赞 immutable 10/12/2016 #26

没有办法完全避免对APK文件进行逆向工程。若要保护应用程序资产和资源,可以使用加密。

  • 加密将使它更难在不解密的情况下使用。选择一些强大的加密算法会使破解变得更加困难。
  • 在主逻辑中添加一些欺骗代码,使其更难破解。
  • 如果你能用任何本地语言编写你的批判性逻辑,那肯定会使反编译变得更加困难。
  • 使用任何第三方安全框架,如 Quixxi

评论

0赞 Peter Mortensen 7/23/2021
回复“用任何母语编写你的批判性逻辑”:在编译之前混淆代码不是更容易吗?
3赞 Saqib 9/13/2017 #27

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

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

7赞 Zennichimaro 1/25/2018 #28

同意@Muhammad Saqib的观点:https://stackoverflow.com/a/46183706/2496464

@Mumair给出了良好的开始步骤:https://stackoverflow.com/a/35411378/474330

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

因此,等式来了:

在金钱方面,我们总是假设客户是不可信的。

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

我们如何保持安全?

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

3赞 Mayank Nema 3/14/2018 #29

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

评论

0赞 Subham Naik 3/22/2021
我总是使用 Proguard,限制逆向工程很有帮助。
2赞 Asthme 9/5/2018 #30

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

4赞 Rajiv Ranjan 5/24/2019 #31

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

请访问安全保存常量值面向应用开发者的移动应用安全最佳实践

3赞 Hunter 5/8/2020 #32

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