对于我的应用程序的付费版本,我选择了解锁程序应用程序路由,因为它易于实现,允许开发人员控制台中的各个统计信息,但主要是因为我不需要维护2个代码库(一个用于免费版和另一个付费版)。即使我使用了CVS(我这样做),仍然需要保持合并功能和错误修复。解锁器应用程序更容易实现整体...
但这有一个严重的缺点,它很容易超出安全检查;除非我在这里遗漏了什么。
无论我做什么,这样的实现总会导致一个简单的if
,如下所示:
if(Program.isPremiumVersion()) {
// Remove ads...
}
isPremiumVersion()
方法负责检查付费解锁器应用安装的所有工作,如果证书匹配和所有这些东西。是的,解锁器应用程序受LVL保护(虽然我已经阅读了一些提到LVL不安全的文章,但现在不是重点)。但最终,无论isPremiumVersion()
中的代码有多复杂,都会导致返回true
或false
值。
覆盖此类安全功能只需对代码进行逆向工程,并使其始终返回true
。不是吗?我们如何保护我们的Android应用免受此攻击?是的,代码使用ProGuard进行混淆。不过,对于足够熟练的人来说,不应该太难。
请注意,我不是在试图打击破解者,我们根本无法获胜。我不会为此而失眠,在“完美解决方案”上浪费了无数个小时。我只是在寻找一种让它更安全的方法。至少在理论上,这似乎很容易破解。我错了吗?
有什么想法可以提高此类功能的安全性吗?
答案 0 :(得分:7)
没有简单的方法。
你必须试图掩盖它。以下是一些提示:
提示1:返回布尔值太明显了。尝试返回一个值(例如int)。然后,使用比较来查看它是否是有效的已知返回值。
例如:获取包含某些内容的字符串的md5,您可以从中判断它是否为溢价。假设你在每个应用程序上都有一个静态的最终字符串。也许一个的md5以9开始,另一个以1开始。在这种情况下,计算md5并查看它是否大于“随机”数字,你知道它在其他两个数字之间。假设“premium”的md5是987,而“free”的md5是123.你可以计算md5并将其与456进行比较。
提示2 - 更好:复制一些代码并每次使用不同的值(而不是456)!希望这会使解码混淆代码变得更加困难。
我知道所有这些检查最终都会映射到布尔值(if(1 > 2)
将被评估为if(true)
)但是对应用程序进行逆向工程应该更加困难。
提示3 :不要在最明显的地方运行“isPremium”检查。例如,在启动应用程序时不要进行检查,因为这是最明显的地方。如果你想根据应用程序的版本拥有条件逻辑,可能很难避免某些明显的点,但在这里尽力而为!
提示4:构建并混淆您的应用。针对apk运行逆向工程工具。阅读它,看看它的外观。
最后,每天早餐时观看此Google IO演示文稿:Evading Pirates and Stopping Vampires using License Verification Library, In-App Billing, and App Engine
[编辑 - 更多提示]
提示6:尝试使用您用来检查完全有效位置的代码。这可能会掩盖你在那里真正做的事情。这可能包括调用代码来检查这是哪个版本的应用程序,但对它没有任何意义。或者,在我之前的例子中,将md5与012或999进行比较,只是为了稀释这些变量的实际用途。
提示7:而不是依赖于单个字符串,您可能会考虑在运行时构造字符串。总决赛和静力学也可能引起太多关注,所以避免这些可能是一件好事。
提示8 永远使用google教程中提供的LVL代码。修改它。很多!
注意:我不确定这些技巧是否真的会产生重大影响,但你应该有机会至少让黑客的生活变得更加困难。
答案 1 :(得分:1)
您可能已经看过这个,但这里有一些代码用于实现您所说的内容:
它检查免费和解锁器应用程序上的签名是否相同。因此,不可能有人以正确的名称创建一个具有正确名称的应用程序,因为签名会有所不同。然而,人们仍然可以通过手机撕掉apk并分发它。解决这个问题的唯一方法是使用某种服务器身份验证,但这会增加成本和复杂性。