声明

本文内容相对简单和初级,也是个人的总结和记录。本文提供内容和方法仅供学习交流使用,严禁用于商业用途。

本文开头感谢Ethan、大脸猫和刘菲哥。

事出皆有因,昨天晚上做梦梦见在学习破解,正好前几天看见了freebuf看见有一篇《从Charles破解历程了解Javassist使用》的文章,文中破解的版本是windows版的charles。作为java大菜鸡,让我萌生了一个想法,尝试和复现一下破解的过程,此处留下了没有技术的眼泪。当然charles也不贵,本人正版用户,此文纯属娱乐。

工具

  • javassist-3.3

    https://mvnrepository.com/artifact/javassist/javassist
  • charles-4.2.7

    https://www.charlesproxy.com/assets/release/4.2.7/charles-proxy-4.2.7.dmg
  • IntelliJ IDEA

  • JadxGUI

    https://github.com/skylot/jadx.git

过程

首先先拷贝一份/Applications/Charles.app/Contents/Java/charles.jar,作为破解和备份使用

使用jadx-gui加载

未注册版打开时会提示This is a 30 day,搜索This is a 30 day关键字找到对应类

imgs

我们可以看见showRegistrationStatus和showRegistrationStatus方法
顾名思义showRegistrationStatus是判断用户有没有注册的方法

imgs

public void showRegistrationStatus() {
    if (kKPk.lcJx()) {
        showStatus("Registered to: " + kKPk.JZlU());
    } else {
        showSharewareStatus();
    }
}

虽然不怎么懂java代码,但是编程的思想是想通的,上面的逻辑很简单,如果没有注册显示使用信息。
  • kKPk是判断有没有注册的核心类

  • kKPk.lcJx() 判断是否注册的方法

  • kKPk.JZlU() 获取注册人姓名的方法

imgs

查看kKPk类我们发现,该类的成员变量JZlU和yNVB为破解关键

  • JZlU

    默认值为false,判断是否注册

  • yNVB

    yNVB是注册人信息

imgs

通过freebuf文章分析可知,作者想通过重写kkPK类的构造方法,将JZlU和yNVB重写。我仔细看了一下kkPK三个重载方法,哇好怀念啊!其实我们只需要将类的这两个成员变量在初始化改写即可,苦于自己太菜,不会直接使用javassist去修改私有方法,这里引用原作者的代码

import javassist.*;

import java.io.IOException;

public class crack {
    // 实例化类型池
    public static ClassPool pool = ClassPool.getDefault();

    public static void main(String[] args) throws
            NotFoundException, CannotCompileException, IOException, ClassNotFoundException {
        // 获取默认类型池对象
        pool.insertClassPath("/Users/lordsky/Desktop/charles.jar");
        // 从类型池中读取指定类型
        CtClass oFTR = pool.get("com.xk72.charles.kKPk");
        try {// 获取指定方法
            CtMethod ct = oFTR.getDeclaredMethod("JZlU");
            // 修改原方法
            ct.setBody("return \"lordsky test crack\";");

            // 为类设置构造器,获得全部的构造方法
            // 这里我进行了改动,因为有三个方法,索性全部覆盖
            CtConstructor[] cca = oFTR.getDeclaredConstructors();
            cca[0].setBody("{this.yNVB = \"lordsky test crack\";\nthis.JZlU = true;}");
            cca[1].setBody("{this.yNVB = \"lordsky test crack\";\nthis.JZlU = true;}");
            cca[2].setBody("{this.yNVB = \"lordsky test crack\";\nthis.JZlU = true;}");
            //将上面构造好的类写入到指定的工作空间中
            oFTR.writeFile("/Users/lordsky/Desktop/crack/class/");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

然后进入工作空间中,将原先的charles.jar也复制到com文件夹的同级目录

class tree
.
├── charles.jar
└── com
    └── xk72
        └── charles
            └── kKPk.class

jar -uvf charles.jar com

然后将该目录重新生成的charles.jar 替换/Applications/Charles.app/Contents/Java/charles.jar即可。

imgs
imgs

参考

http://www.freebuf.com/column/205620.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注