最近学习HTTP代理相关资料时,偶然间发现Mac上的charles是用java实现的,且很好破解(各种跳过License)。同时也很好奇它是怎么实现的。所以反编译了一下。刚好业务方有些功能需求charles目前没有,顺便探究下修改难度。
这是一个实操过程记录,并不打算深究底层原理。各位看官担待。
反编译jar
其中 charles.jar
就是我们要关注的。使用jadx反编译这个jar
这是Charles默认打开时的一个界面,我们在使用jadx反编译charles.jar之后,全局搜索一下“Loading Preferences”,
可以看到初始化这里的相关逻辑,刚好上面有个getVersionName
的方法,应该就是版本号的公开方法,我们尝试修改一下这个简单的方法试试效果。
使用javassist修改目标class
参考文档:如何修改jar包中的class文件
比如我们修改一下版本号,使用 javassist 修改字节码
public static void main(String[] args) {
//这个是得到反编译的池
ClassPool pool = ClassPool.getDefault();
try {
//取得需要反编译的jar文件,设定路径
pool.insertClassPath("/Users/okdude/Desktop/charles.jar");
//取得需要反编译修改的文件,注意是完整路径
CtClass cc1 = pool.get("com.xk72.charles.CharlesContext");
//取得需要修改的方法
CtMethod method = cc1.getDeclaredMethod("getVersionName");
//插入修改项,我们让他返回“This is fake version.”
method.insertBefore("{if(true) return \"This is fake version\";}");
//写入保存
cc1.writeFile();
} catch (NotFoundException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
以上程序使用javassist执行完成后,会在当前工程里生成修改后的CharlesContext.class
。我们需要用它覆盖charles.jar中原有的class。
替换CharlesContext.class
首先将 charles.jar 拷贝一份出来,使用以下步骤替换CharlesContext.class
# 解压charles.jar 到当前文件夹
jar xvf charles.jar
# 手动将修改后的CharlesContext.class放到 com/xk72/charles/ 文件夹下
# 更新charles.jar包
jar -uvf charles.jar com/xk72/charles/CharlesContext.class
参考
破解Charles 4.5.1
Javassist 使用指南(一)
如何把java App包装成Mac安装包 - How to create a macOS installer for a Java application (.jar)