mac Charles v4.0.2详细破解教程

背景

Charles是一款十分优秀的抓包软件,尤其是在mac操作系统下。Charles是一款商用软件,其体验版虽然能够使用全部功能,但是有以下几个使用上不方便的地方:

  1. 启动时有10s的提示购买窗口,并且每过4分钟,当你再次点击Charles进行操作时,还会弹出一个持续5s的提示购买窗口。提示购买窗口截图如下:

  2. 一旦运行超过30分钟,就会弹出下面的error提示窗口,并且终止程序:

出于学习和研究目的,在成功破解了Charles之后,发现Charles破解可以作为一个十分典型的Jar包破解教学,因为其破解流程具有以下几个特点:

  1. Jar经过了代码混淆。
  2. 破解思路多。
  3. 可以利用的破解工具多。

在详细地讲解Charles破解之前,我先介绍一下环境:

  • macOS 10.11.6
  • charles v4.0.2
  • jdk 1.8

好了,接下来,让我们来详细地讲解一下如何对Charles进行破解。

破解流程

思路一

代码分析和定位

在背景中我们介绍过了,Charles体验版未对功能做过阉割,所以第一种破解思路是取消掉Charles对体验版做的限制。不管怎么样,所有Jar包破解的第一步,都是通过反编译软件来阅读代码。这里我们使用的是JD-GUI,这是一款十分优秀的java反编译软件,除了能够阅读反编译之后的代码之外,还可以进行搜索。

我们首先进入Charles,在mac下可以通过右键Charles的图标,然后选择显示包内容。进入到Java目录,然后用JD-GUI打开charles.jar:

经过观察之后,我们发现charles.jar经过了代码混淆,这样程序内部的很多逻辑只能靠经验去猜测了。由于提示购买窗口那里有个"Delay",所以我们先搜索所有出现过"Delay"字符串的地方。通过分析搜索结果,我们大胆猜测SplashWindow是用来处理窗口的相关逻辑,并且setDelay方法是用来设置窗口的显示时间:

然后我们搜索所有调用setDelay方法的代码,十分幸运的是,我们一下子就发现了设置启动界面10s delay时间和设置每过4分钟后的5s delay时间的代码位置。

删除启动界面的10s delay

第一处是位于com.xk72.charles.gui的V.class中:

为了给我们接下来的操作打好基础,我们首先需要对jar包进行解压缩。但是由于Charles做过了基于类名的代码混淆,这会导致jar包无法在文件名不区分大小写的操作系统上解压出来(比如a.class会在解压的过程中被A.class给覆盖掉)。这是一种十分常见的混淆技术,由于我们最常用的windows和mac操作系统都是不区分文件名大小写的操作系统,所以这种混淆办法可以将大部分的bad boy给拦截在外。下图为ProGuard混淆工具开启类名混淆的截图:

为了解决这种情况,一般我都会使用Linux系统来解压经过类名混淆过的Jar包。解压之后,我们通过JBE字节码修改工具来对V.class的字节码进行修改。对于JBE的使用方法,大家可以参考我写的另一篇文章:http://www.jianshu.com/p/a61f0f44705b。修改V.class的方法很简单,只需要将run方法对应的字节码删除,只留下return即可。

删除每过4分钟的5s delay

第二处位于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名称方法

我们大胆猜测该方法是用来显示License名称的,我们将其修改为返回一个固定的字符串(自己想叫什么就叫什么)。读者如果对java字节码不是很熟悉的话,有一种最简单的做法是自己先写一个demo java程序,然后用JBE查看对应的字节码:

ldc "wooyoo"
areturn

继续运行时又抛出了VerifyError:

这个错误是JVM字节码校验失败产生的。该问题很大概率是因为JBE的bug,为了解决这个问题,我们有以下3种解决方法:

  1. 关闭JVM的字节码校验。
  2. 使用javassist来修改字节码。
  3. 自己编译License
关闭JVM的字节码校验

为了关闭JVM的字节码校验,我们需要添加额外的JVM启动参数。由于我的电脑的java环境是1.8,所以只能通过添加-noverify参数,如果是1.7的话,还可以使用-XX:-UseSplitVerifier。我们可以在Charles程序目录下的info.plist文件里面添加关闭参数:

......
<key>JVMOptions</key>
<array>
<string>-noverify</string>
......
使用javassist来修改字节码

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语句,来达到仅执行自己逻辑的效果。

自己编译License

该方法也是参考了网络上另一个人的破解文章:http://blog.csdn.net/endlu/article/details/52175787,我这里就不再赘述了,有兴趣的读者可以看这篇文章。

最后

将上述hack过的License.class文件打包进原来的jar包中。这里我们不一定要在Linux系统下完成打包,可以借用jar命令直接完成class文件的替换:jar -uvf charles.jar com/xk72/charles/License.class。然后将新的jar包替换原来charles app下的charles.jar,启动后我们发现已被成功破解。

总结

再次声明以上教程都是基于学习和研究的目的,我们强烈建议大家有能力的话还是要购买正版软件。好了我们来总结一下通过这次破解我们需要掌握的知识点:

  • 经过类名混淆过的Jar无法在不区分文件名大小写的操作系统上进行压缩或者解压缩。我们可以借用Linux操作系统来完成压缩或者解压缩操作。
  • 破解的思路一般都是修改处理"License"的逻辑。但是我们不能局限于此,比如在本例中,我们可以去除掉体验版的限制,同样达到破解的目的。
  • 某些情况下如果破解不成功,我们可以通过命令行启动程序,然后通过观察控制台输出的错误堆栈来看到底是哪里出了问题。另外如果程序有日志文件的话,我们还可以去日志文件中分析错误原因。
  • 我们可以通过JBE、javassist甚至是自己重新编译的方式来修改原来的字节码。

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容