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

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

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

然而,Android组件的名称保持不变,一些代码(如应用程序中使用的关键值)保持不变。根据Proguard文档,该工具无法混淆Manifest文件中提到的组件。

现在我的问题是:

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


当前回答

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

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

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

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

其他回答

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

访问安全保存常量值以及针对应用程序开发人员的移动应用程序安全最佳实践。

在计算历史上,当您将软件的工作副本提供给攻击者时,从未有过阻止软件逆向工程的可能。而且,在大多数情况下,这是不可能的。

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

此外,如果你的首要目标是防止应用程序盗版,那就别费心了。你已经在这个问题上花费了比任何反盗版措施都能挽救你的时间和金钱。解决这一问题的投资回报率很低,甚至连思考都没有意义。

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

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

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

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

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

不过,你可以使用不同的技巧来提高黑客攻击的难度。例如,使用混淆(如果是Java代码)。这通常会大大降低逆向工程的速度。

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

正如大家所说的,正如你可能知道的,没有100%的安全性。但谷歌内置的安卓系统的起点是ProGuard。如果您可以选择包含共享库,则可以在C++中包含所需的代码,等。如果您需要在每次构建时将外部本机库添加到APK的库文件夹中,那么你可以根据以下建议使用它。

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

<project>/libs/armeabi/libstuff.so

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

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

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

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

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

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

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

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

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

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

现在,攻击者想要的计算机是你的服务器,因为它而不是客户端应用程序/设备是可以让他赚钱或让其他人痛苦的东西。没关系;与试图保护所有客户机相比,您花费金钱和精力来保护服务器会获得更大的回报。该服务器可以位于各种防火墙和其他电子安全装置的后面,此外,还可以在钢铁、混凝土、钥匙卡/插针访问和24小时视频监控的后面进行物理保护。您的攻击者需要非常老练才能直接访问服务器,而且您应该立即了解这一点。

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