如何破解ZKM22以及代码定位
开篇
你可能都没有听说过。 嘿嘿
如果你不知道他的强度,你可以尝试去使用反编译器去反编译 idea 的jar文件.
然后你会发现一堆狗屎调用,而且它会对每个函数的参数进行修改,可以说ZKM是市面上最好的java层混淆.
但是本篇文章主要是讲解定位代码,在网上都有很多关于ZKM的破解方法,但是不同版本方法名不一样,就无从下手了.
本文还会介绍了另外一种调试方法,而且不需要使用javaagent,且本文介绍的方法涉及的字节码操作较少,较为简单.
本文只透露大致方法,不会对每一个细节都深入描写,根据个人调试发现 ZKM15-ZKM23 试用版本的检测基本没有发生改变.
总结
这边提前总结一下
这一个方法,是在一次水群突然想到的操作,没想到最后居然成了.
总之,对于ZKM开发方个人还是建议可以把同验证相关的indy调用进行排除.
可以很大限度的隐藏很多的暗桩(虽然现在也很难找就是了)
关于ZKM的验证
ZKM 属于离线 许可证,即本地验证与一些其他的混淆器联网不同.
如果你想让试用版同正式版功能几乎一直,那么你就需要找到以下限制代码
- 系统时间检测
- ZIP时间检测
- 混淆过程的时间检测
- Flow流程控制1-2个限制
- 一个奇怪的Flow检测(本文就不写了),如果你超过2了就会报错.
总之,ZKM的检测分为 加载阶段
和 混淆阶段
. 后者本人没有深入调试,具体流程也不得而知.
反Javaagent检测
这玩意写在了ZKM的 static 方法内,通过破坏加密后des字符串,导致解密失败(挺妙的)
我们可以直接对 RuntimeMXBean
类中的 getInputArguments
进行特征删除字符串.
此外还有一个我个人没有调试出来,其被检测到后会在Flow混淆后也会提示栈堆不平衡,这个检测非getInputArguments
调用.
目前没定位出来,不会有任何提示捏.
思路方法
不难发现,对应的加密类型 例如: 字符串 整数型 长整数型 加密都通过indy来获得,且解密函数都是当前的类里
以下是 com.zelix.ZKM
类中的解密字符串函数:
1 | private static Object b(MethodHandles.Lookup lookup, MutableCallSite mutableCallSite, String string, Object[] objectArray) { |
以及发现调用都为 invokedynamic
, 有 method
也包括 field
,以下是代码
1 | public static Object a(MethodHandles.Lookup lookup, MutableCallSite mutableCallSite, String string, MethodType methodType, Object[] objectArray) { |
关于上面的函数 rjj.a("l", (Object)v32, (long)-2994513164395422785L, (long)var1_1);
其中字符串 l 为上面的string参数,剩余则存进了 objectArray 中
其中第五行,为设置绑定目标代码, 我们可以通过hook下面的代码,进行调试,方便查看调用情况
1 | public static MethodHandle a(MethodHandles.Lookup lookup, MutableCallSite mutableCallSite, String string, MethodType methodType, long l, long l2) { |
有了上面的方法,我们分别对每个函数进行 hook
,
我们则可以对ZKM的各种调用以及 字符串 数值 进行拦截或者修改,可以通过 StackTracer 来获取得到caller className methodName直接分析方法的调用情况.
相对 arthas 一步一步调试方便了许多,也不需要ognl表达式来调用,我们可以直接从输出的log本文直接查询,就能快速定位了.
时间检测
ZKM 是通过加密long
值成一段成一段字符串
.
有了上面的操作,我们要找到时间的字符串
,在此基础上对调用数据进行修改,即可达到通过时间检测.
这边假设你已经对indy的函数进行hook,通过输出我们可以找到3个连着输出的字符串
那个字符串就是时间加密后的字符串,我们可以在invoke后对数据返回进行一个修改
返回一个正确的时间即可
我对 System.currentTimeMillis 进行拦截修改,这是我的一个写在 上方代码块的第16行
后的 例子
1 | if (methodName.equals("currentTimeMillis")) { |
还有一些关于时间的过检测,这边就不写出来了,让大伙自己探索一下
Flow混淆限制
经过个人测试,ZKM_log中的提示的 MESSAGE: Obfuscating control flow in only one or two methods in each class
其中的方法包括 <init>
<clinit>
和 其他方法
,但是 <init>
和 <clinit>
并不会在ZKM_log.txt
中输出实际上可能会1-3的方法
而我们的具体定位方法是用的字符串hook,也许你注意到每一个混淆的方法都会输出一则语句 Obfuscated flow in method '
这就是特征点
具体的内部字节码分析,可以由你自己进行分析和修改,在你修改好后你就会发现加密的方法变多了(那肯定)
关于Flow混淆限制,我还修改了另外一个地方,这里就不写了,感兴趣的自己去探索探索.