关于付费 APP 加密方式的一些疑问

2022-07-01 08:56:34 +08:00
 equationl

可能因为我的水平有限,我所能想到的加密方式似乎都没有实际用处。

比如,某个业务场景是付费用户可以创建无限的素材,而非付费用户只能创建不高于某数量的素材。

虽然我已经用了各种方式来加密这个“某数量”的值,不过不管前面写的多绕,但是最终还是会回归到一个 if 逻辑判断。

比如,针对上述场景,我是这样写的:

    val a = "RWM="
    val b = a.decodeBase64()?.string(Charset.forName("utf8")) ?: "${Char(0)}${Char(0)}"

    val realNum = 10

    if (realNum <= b.toCharArray()[1].code - b.toCharArray()[0].code) {
        println("pass")
    }
    else {
        println("you need pay first")
    }

但是反编译下来是这样的:

(节选)

      if (realNum <= var8 - var3) {
         var4 = "pass";
         System.out.println(var4);
      } else {
         var4 = "you need pay first";
         System.out.println(var4);
      }

不管你前面写的有多复杂,最终还是会回归到简单的 if 逻辑判断,别人修改时只需要删除或者直接改一下这个判断就能轻松破解了。

判断是否付费同理,不管前面写的多复杂,最终会回归到简单的逻辑判断。

所以我现在加密完全依赖于加固,但是加固也只能防的住“脚本小子”一键破解,如果是有大牛专门破解的话,也很容易被脱壳。

虽然防住“脚本小子”已经满足我的需求了,但是我还是想知道,应该怎么在不加固的情况下避免被“一键”破解呢?

据我所知,某个业内有名的 APP ,就没有使用加固,但是就是至今没被破解,甚至作者还专门搞了个悬赏,让别人区破解它。据我了解的是,至今没人破解成功。

补充:

  1. APP 性质决定了没法将需要加密的逻辑放到服务器避免被本地破解
  2. 上述代码只是做了一个示例,实际使用比这个复杂,而且核心代码也是写在 c++ 中的,不过正如我上述说的,即使写在 c++ 中,最终也是回归到 java 调用 c++的代码,然后做一个简单的逻辑判断
  3. 我想到的是把加密和业务逻辑混合在一起,但是自己实际测试过,即使这样反编译后效果也不理想。
6723 次点击
所在节点    程序员
67 条回复
0o0O0o0O0o
2022-07-01 11:25:38 +08:00
我觉得只要程序逻辑运行在本地能被破解者接触到,就没有防破解的可能。就算是鉴权后下发逻辑,也只能防第一次付费。后端加水印,破解者破解扩散后被发现了破解者可能也无所谓,大不了你封号拉黑呗,反正已经搞到手了。说到底,还是攻防双方成本的博弈。

MT 它不用知名厂商的加固产品你也不能说它没用加固,而且它的保护方案也被它定义成一种产品呢。

实在要说建议,那就建议学习一下 dex to c 、ollvm 、vmp 等相关知识,再在已有轮子基础上来做自定义保护。
shyrock
2022-07-01 13:43:45 +08:00
如果你所有的代码执行环境都在对方的手里,那意味着对方可以找到最近的分支最小改动绕过你的防护。整个业务逻辑全链路最简单的地方会成为破解的缺口,防不胜防。

但是如果你的部分代码不在客户端,应该就很难破解了。
CantSee
2022-07-01 14:10:03 +08:00
代码混淆?
equationl
2022-07-01 14:40:08 +08:00
@CantSee 混淆不是加密,最多增大破解难度
zlowly
2022-07-01 14:40:36 +08:00
如果不考虑离线情况,即用户总是联网使用付费功能,则可以考虑不对称加密方式。密钥在服务器上,客户端有公钥,素材的全体或部分用密钥加密后才保存在客户端。平时客户端用公钥解密来使用,这样就无法简单的绕过某个判断来使用完整功能了。
equationl
2022-07-01 14:41:47 +08:00
@shyrock 对的,就算我防护做的再好,万一人家用的特殊设备,都不按套路出牌,直接 hack 内存,压根没法防。

所以我的前提是:“怎么在不加固的情况下避免被“一键”破解呢?”
abc8678
2022-07-01 14:44:23 +08:00
@equationl 说的该不会就是某安评论区那些发破解版的人吧
murmur
2022-07-01 14:45:48 +08:00
@equationl 你想太多了,技术没用,得靠律师函,留个口子,让他产生真的破解了的错觉,然后疯狂往服务器发统计信息
newmlp
2022-07-01 14:47:31 +08:00
Java 不是可以动态执行字节码吗,把一些逻辑放在服务端,然后下发的客户端执行
equationl
2022-07-01 14:53:02 +08:00
@abc8678 哈哈哈,还真是
clino
2022-07-01 14:57:36 +08:00
“最终还是会回归到简单的 if 逻辑判断,别人修改时只需要删除或者直接改一下这个判断就能轻松破解了”
能不能让程序在删除或者修改 if 以后就不能正常工作呢?
比如说在判断里塞入一些不起眼的操作,如果没有这些操作,不能生成正常的素材,这种不正常是没法直接跟踪程序执行能够直接判断的,而是隐含在复杂的素材生成算法里面,这样破解的人就难以了解前后的因果关系
equationl
2022-07-01 15:03:04 +08:00
@clino 我想做到的就是这种效果,但是我技术储备不够,尝试了很久,还是实现不了
clino
2022-07-01 15:10:13 +08:00
我考虑的大概方向就是,不要把你的“不能工作”用那么明显的方式表现出来,比如说直接退出程序这种,而是隐含在功能的产出里,这种功能的产出应该是比较复杂有门槛的,否则你的产品也没什么保护的需要了,所以考虑你的功能里实现最复杂的部分,找地方加料让功能间接地不能正常工作,比如生成的素材有非常多的噪点,但是跟踪执行根本不知道噪点是哪里引入的,因为要搞懂就要了解里面的算法,但是算法没代码又非常难
i3x
2022-07-01 15:11:10 +08:00
@equationl 360 这个也不是解不了。虚拟机 dump 之类的都过时了。。。。暂时我还没发现安全的加固。只是难度不同罢了。我是个萌新,但是我目前木有发现解决不了的,解决不了的发给群里的大佬,几分钟就解决了,他们都有现成的环境。。。

冲你的目标,对付脚本小子来说,你自建一个混淆机制,不要用市场现有的,让他找不到脚本,没有真正的技术就解决不了了。

相关的防护我做的是比较多了。。。java php js 之类的代码保护,对于这些人来说,反倒是最不安全的自创逻辑混淆最安全。反而是你用标准的付费的高端的加密器,让他们很容易找到解密工具。先混淆到他们无法利用,在这个里边加几步授权,让这种人几乎完全无法利用就够了。

虽然对大佬来说写几个脚本就解密掉了。但是有一些逻辑也因为变量名字被替换,也是难以理解的,大佬对这种东西也不感兴趣,看一下结构自己都知道怎么写了,对破解这种东西根本就不感兴趣了。
至于你说混淆没有用,是因为你的逻辑太简单。你碰到一个授权不一定要在一个地方判断,很多地方判断搞好几十个逻辑,有的逻辑可能导致整个程序不可用,而有的逻辑会导致一部分比较恶心的东西。比如说有的地方校验不通过会随机性崩溃。程序不要做必然性的逻辑。还有存储这些判断逻辑,也不一定要存储一个固定的常量。可存储很多的值,有的数字是对的,但是是是而非。比如说你要存最大允许 10 个素材,你可以在一个地方出一个常量 10 。但是你根本就不调用这玩意儿,你调用的是 2*5 ,或者 9+1 。至于这个加减乘除怎么做你也不一定要存常量。可以从其它地方获得这个数字,就更难搜索定位了。有一些部分的逻辑自建类似于为加固的东西,用对称加密保护住。还有的功能做在网络上。虽然本地有逻辑,但是网络逻辑也作为额外的吊销手段。

当然只要你的东西足够有价值脚本小子没准就通过你的项目,成为大牛。。。
equationl
2022-07-01 15:11:38 +08:00
@clino 学习了,我研究研究
equationl
2022-07-01 15:13:27 +08:00
@i3x 学习了
timethinker
2022-07-01 15:25:51 +08:00
加固就行了,除非是特别特别需要防止别人破解的 APP ,这个时候才应该考虑在源代码级别上面进行特殊的逻辑处理,另外也可以花钱买专业的加固工具,权衡利弊选择适合的就可以啦。操作系统都能被破解,iOS 都能被越狱,更别说 APP 了。抱着学习的态度去尝试了解这一行也是有价值收获的。
equationl
2022-07-01 15:28:56 +08:00
@timethinker 目前是这样做的,只是 play 更新了政策,只能上传 aab 了,现在没有免费加固 aab 的服务了,收费加固的价钱不是我能承受的起的
cszchen
2022-07-01 15:32:44 +08:00
连温道斯和苹果系统都能被破解。
timethinker
2022-07-01 15:56:31 +08:00
我理解的你这个 APP 的激活是不是类似于签发密钥然后激活的单机授权模式,也就是用户在没有联网的情况下也能正常付费激活,比如私钥签名,然后 APP 校验,没问题的话就读取里面的授权信息,激活就算成功了?

如果破解者能够把你的授权部分修改掉,伪造出授权成功的信息通过校验,那么你的 APP 就会认为这确实是已经付费的正常用户。除此之外你在没有授权时做的任何校验都失去了存在的意义。

因此在你做各种校验之前,最好先考虑一下哪一部分才是最关键的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/863351

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX