Charles是一款十分优秀的抓包软件,尤为是在mac操做系统下。Charles是一款商用软件,其体验版虽然可以使用所有功能,可是有如下几个使用上不方便的地方:javascript
启动时有10s的提示购买窗口,而且每过4分钟,当你再次点击Charles进行操做时,还会弹出一个持续5s的提示购买窗口。提示购买窗口截图以下:html
一旦运行超过30分钟,就会弹出下面的error提示窗口,而且终止程序:java
出于学习和研究目的,在成功破解了Charles以后,发现Charles破解能够做为一个十分典型的Jar包破解教学,由于其破解流程具备如下几个特色:linux
在详细地讲解Charles破解以前,我先介绍一下环境:windows
好了,接下来,让咱们来详细地讲解一下如何对Charles进行破解。网络
在背景中咱们介绍过了,Charles体验版未对功能作过阉割,因此第一种破解思路是取消掉Charles对体验版作的限制。无论怎么样,全部Jar包破解的第一步,都是经过反编译软件来阅读代码。这里咱们使用的是JD-GUI,这是一款十分优秀的java反编译软件,除了可以阅读反编译以后的代码以外,还能够进行搜索。oracle
咱们首先进入Charles,在mac下能够经过右键Charles的图标,而后选择显示包内容。进入到Java目录,而后用JD-GUI打开charles.jar:app
通过观察以后,咱们发现charles.jar通过了代码混淆,这样程序内部的不少逻辑只能靠经验去猜想了。因为提示购买窗口那里有个"Delay",因此咱们先搜索全部出现过"Delay"字符串的地方。经过分析搜索结果,咱们大胆猜想SplashWindow是用来处理窗口的相关逻辑,而且setDelay方法是用来设置窗口的显示时间:框架
而后咱们搜索全部调用setDelay方法的代码,十分幸运的是,咱们一会儿就发现了设置启动界面10s delay时间和设置每过4分钟后的5s delay时间的代码位置。jvm
第一处是位于com.xk72.charles.gui的V.class中:
为了给咱们接下来的操做打好基础,咱们首先须要对jar包进行解压缩。可是因为Charles作过了基于类名的代码混淆,这会致使jar包没法在文件名不区分大小写的操做系统上解压出来(好比a.class会在解压的过程当中被A.class给覆盖掉)。这是一种十分常见的混淆技术,因为咱们最经常使用的windows和mac操做系统都是不区分文件名大小写的操做系统,因此这种混淆办法能够将大部分的bad boy给拦截在外。下图为ProGuard混淆工具开启类名混淆的截图:
为了解决这种状况,通常我都会使用Linux系统来解压通过类名混淆过的Jar包。解压以后,咱们经过JBE字节码修改工具来对V.class的字节码进行修改。对于JBE的使用方法,你们能够参考我写的另外一篇文章:www.jianshu.com/p/a61f0f447…。修改V.class的方法很简单,只须要将run方法对应的字节码删除,只留下return便可。
第二处位于SplashWindow的a方法中:
修改方法很简单,只须要将对应的字节码除了return以外所有删除,使其成为一个空方法便可。
最后,咱们须要删去半个小时退出的代码。定位代码的思路很简单,搜索error对话框中出现过的字符串便可,这里咱们经过JD-GUI搜索"unlicensed copy",从搜索结果中,咱们能够找到com.xk72.charles包下的e.class中有对应的逻辑:
修改方法同上,利用JBE将run方法对应的字节码除了return以外所有删除,使其成为一个空方法便可。
将上述全部hack过的class文件打包进原来的jar包中(必定要在linux系统下),替换原来charles app下的charles.jar,启动后咱们发现已被成功破解。
其实思路一并非一种常规思路,大部分状况下,咱们都会对处理"License"的方法进行破解。若是你们完整地走过一遍思路一的方法,那么确定会发如今com.xk72.charles包下有一个叫作License.class的类,而且该类的a方法常常被外部调用,用来判断是否已经注册成功,好比每过4分钟显示提示购买窗口的逻辑:
咱们能够大胆地认定该方法是用来判断是否已经注册的。顺着该思路,咱们先来尝试将该方法修改成永远返回true。经过JBE将a方法对应的字节码修改成:
iconst_1
ireturn复制代码
而后启动Chalres发现一直卡在Loading Preferences界面。为了找出缘由,再介绍一个小技巧,咱们能够经过命令行的方式来启动程序:java -jar ../Charles.app/Contents/Java/charles.jar
,而后咱们能够看到控制台会输出对应的错误堆栈。从错误堆栈中咱们能够看到有空指针的异常:
能够看到是License的b方法:
咱们大胆猜想该方法是用来显示License名称的,咱们将其修改成返回一个固定的字符串(本身想叫什么就叫什么)。读者若是对java字节码不是很熟悉的话,有一种最简单的作法是本身先写一个demo java程序,而后用JBE查看对应的字节码:
ldc "wooyoo"
areturn复制代码
继续运行时又抛出了VerifyError:
这个错误是JVM字节码校验失败产生的。该问题很大几率是由于JBE的bug,为了解决这个问题,咱们有如下3种解决方法:
为了关闭JVM的字节码校验,咱们须要添加额外的JVM启动参数。因为个人电脑的java环境是1.8,因此只能经过添加-noverify参数,若是是1.7的话,还可使用-XX:-UseSplitVerifier。咱们能够在Charles程序目录下的info.plist文件里面添加关闭参数:
......
<key>JVMOptions</key>
<array>
<string>-noverify</string>
......复制代码
javassist经常使用来动态地修改字节码,普遍地用于各个java框架里面(这里用它来破解软件真是有点很差意思)。修改代码以下:
public class Test {
public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException {
ClassPool classPool = ClassPool.getDefault();
classPool.insertClassPath("/path/to/charles.jar");
CtClass license = classPool.get("com.xk72.charles.License");
// 修改a方法
CtMethod aOldMethod = license.getDeclaredMethod("a", null);
CtMethod aNewMethod = CtNewMethod.copy(aOldMethod, license, null);
aOldMethod.setName("a_old");
aNewMethod.setBody("{return true;}");
aNewMethod.setName("a");
license.addMethod(aNewMethod);
// 修改b方法
CtMethod bOldMethod = license.getDeclaredMethod("b", null);
CtMethod bNewMethod = CtNewMethod.copy(bOldMethod, license, null);
bOldMethod.setName("b_old");
bNewMethod.setBody("{return \"wooyoo\";}");
bNewMethod.setName("b");
license.addMethod(bNewMethod);
// 输出新的License.class
license.writeFile("/path/to/License.class");
}
}复制代码
须要注意的是,在使用javassist的时候,咱们没法移除原来方法里面的逻辑。基于此,咱们有如下两种作法:
先copy原来方法,而后调用setBody方法往新方法中塞入本身的逻辑。上述代码采用的就是这种方法。
能够在原来的方法中调用insertBefore方法,好比:
CtMethod bMethod = license.getDeclaredMethod("b", null);
bMethod.insertBefore("{if(1<2) return \"wooyoo\"}")复制代码
咱们经过一个确定会执行的if语句,来达到仅执行本身逻辑的效果。
该方法也是参考了网络上另外一我的的破解文章:blog.csdn.net/endlu/artic…,我这里就再也不赘述了,有兴趣的读者能够看这篇文章。
将上述hack过的License.class文件打包进原来的jar包中。这里咱们不必定要在Linux系统下完成打包,能够借用jar命令直接完成class文件的替换:jar -uvf charles.jar com/xk72/charles/License.class
。而后将新的jar包替换原来charles app下的charles.jar,启动后咱们发现已被成功破解。
再次声明以上教程都是基于学习和研究的目的,咱们强烈建议你们有能力的话仍是要购买正版软件。好了咱们来总结一下经过此次破解咱们须要掌握的知识点: