这些反破解盲区,你踩了几个

最近破解了不少软件练手,发现了一些憨到可爱的反破解,于是就决定写这篇文章


0x0 验证挺严密,就是可以绕过

典例:某手势app,验证序列号使用了native层lib,通过调用下面的方法完成验证

.method public static native validateActivateCode(Ljava/lang/String;Ljava/lang/String;)Z
.end method

验证逻辑位于libnative-lib.so

众所周知,native文件要反编译非常困难,要各种动态分析,一般破解者没这功夫。但是这个app被我秒破了

原因很简单:注意这个方法,返回的是整数Z

在dex里搜索调用这个验证方法的地方,我们可以发现下面一处

invoke-static {v0, v1}, L***保护开发者***Util;->validateActivateCode(Ljava/lang/String;Ljava/lang/String;)Z
move-result v0
if-eqz v0, :cond_76
const-string v0, "已激活,感谢您的支持~"
invoke-virtual {p0, v0}, L***保护开发者***ActivateActivity;->setTitle(Ljava/lang/CharSequence;)V

我们可以分析出,这个native层的验证逻辑就是输入序列号,如果可用则返回1,不可用则返回0

知道这个逻辑,就好办了。我们找到每个调用这个验证的地方,手动给返回值赋值1就好了,在if-eqz上方添加const/4 v0,0x1,破解完成!

这个app被轻松破解的关键在于验证太容易被分析出逻辑从而绕过,返回的整数Z很容易让破解者顺藤摸瓜下去,如果自定义一个Object就会难很多了。另外既然都用上native层了,不如把部分关键代码全部native化,增加反编译难度。同时缺少混淆导致方法的用途能被一眼望到底也是被快速破解的原因之一。


0x1 技能树完全点歪

典例:2.x版本的tx加固

最初的tx加固非常好dump,直接drizzleDumper就完事了,后来tx不断加强各种反调试手段和防dump手段,但是还是一直被秒脱

因为过了几个版本之后,大家根本就没有用调试和dump来脱...

tx一直没有换过加密算法,以至于过了几个版本,静态脱壳机就出来了...

这些反破解盲区,你踩了几个

部分脱壳机源码

大家都在静态脱壳,把dex丢进去处理就完事了,加强的反调试和防dump根本用不上...

对于开发者,发现自己的作品被破解后,第一时间是要定位被破解的地方,dir的开发者曾召集破解者有奖破解,收集破解方法,这点就做的很好,知道怎么被破解的,才能有针对的加强防护,而不是按照自己的想法点歪技能树


0x2 如果免费用户的权限和付费用户一样大...

典例:某内存盘工具

该工具免费用户只能创建1023m的内存盘,需要更大空间则需要购买付费版本。

因为官网只有一个版本可以下载,且有验证序列号(联网)模块,判定免费版和付费版的主程序一致,为内部逻辑限制

因为是C井,直接dnspy拖入最大的dll(dnspy会自动加载其他必须的dll),搜索license,没有找到可以下脚的地方。截止到这里,这个工具反破解还做的挺好的

但是...无意间发现了一条变量...MaxMegabytes...初始赋值1023

直接1023改成999999,回编译,破解完成!

这个工具最大的问题在于忽视了破解并不一定要完全伪装到付费用户,只要我能用到付费用户的功能,破解就成功了。虽然我没有在许可证上伪装成付费用户,但是我把免费用户的权限解锁到了和付费用户一样,这样就不用解决序列号验证了,毕竟序列号验证还要联网比较难以破解。

要避免这类破解,也不难。对于不同级别用户权限不等的变量,不要上来就按照免费用户的权限赋值,初始赋值都设为0,依靠license manager类来统一按权限赋值。同时为了增加分析难度,混淆非常有必要。对于大型项目,还可以在不同的dll里添加互相验证文件完整性的逻辑,以避免被破解


就先聊聊这三个典例,以后遇到更多精彩的案例再写


分享到:


相關文章: