小炜 发表于 2017-11-28 01:13

charles v4.2.1 破解方法

本帖最后由 小炜 于 2017-11-28 01:37 编辑

如果从事Server、App端开发,抓包工具是必不可少的,之前在Windows上抓包用的是Fiddler,它是基于.Net开发的,在Mac上使用需要安装Nano,同时对Retina屏幕的支持不是很好。
所以就换为这个工具了。用了一段时间觉得这个工具还是很不错的,它对请求是按照树形结构归类的,如果只关注某个域名下的请求,那就只需要关注这个目录就好了,便于查找。
附上程序启动截图:


工具准备
1. 反编译字节码工具
      1. cfr
      2. procyon
      3. Luyten
      4. Fernfolower
      5. BytecodeViewer
      6. JD-gui
2. 搜索文本工具
       1. Linux系统grep命令
      2. 或其他文本搜索工具
3. javassist (字节码修改工具)http://jboss-javassist.github.io/javassist/

破解思路

由于代码混淆的只是类名,通过反编译找到对应的注册类,修改掉几行代码可以了。反编译工具哪个能解析出来就用哪个。

1. 执行反编译命令,这里我用的是(https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler)
java -jar procyon-decompiler-0.5.30.jar -o output ~/Desktop/charles.jar

2. 在生成output文件夹搜索未注册的关键字

grep -R 'Unregistered' output
output/com/xk72/charles/oFTR.java:      this.ecCn = "Unregistered";
output/com/xk72/charles/oFTR.java:      this.ecCn = "Unregistered";


此时已经找到对应的注册类:/com/xk72/charles/oFTR.java(反编译文件在文章末尾)
注册的话肯定要调这个类里的某个public方法,搜public stataic关键字,得到4个方法,这几个方法用到了两个变量:
private boolean lktV;
private String ecCn;
根据反编译的代码猜测,第一个变量代表注册是否成功,第二个变量代表注册用户名。

3.修改反编译字节码
这里利用开源的javassist工具来完成修改某个方法的内容,这恰好是我们需要的。感兴趣的可以自行搜下相关资料,这里就不细说了,直接附上修改字节码的代码:


import javassist.*;

import java.io.IOException;

/**
* Created by fengyiwei on 2017/11/26.
*/
public class CrackCharles421 {
    public static ClassPool pool = ClassPool.getDefault();

    public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException, ClassNotFoundException {
      pool.insertClassPath("/Users/fengyiwei/Desktop/charles.jar");
      CtClass oFTR = pool.get("com.xk72.charles.oFTR");
      try {
            CtMethod ct = oFTR.getDeclaredMethod("lktV");
            ct.setBody("return \"By.Freeway   https://www.52pojie.cn\";");

            CtConstructor[] cca = oFTR.getDeclaredConstructors();
            cca.setBody("{this.ecCn = \"Cracked By Freeway www.58pojie.com\";\nthis.lktV = true;}");
            cca.setBody("{this.ecCn = \"Cracked By Freeway www.58pojie.com\";\nthis.lktV = true;}");
            oFTR.writeFile("/Users/fengyiwei/Desktop/");

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

4. 将修改后的字节码更新至jar中
jar -uvf charles.jar com

破解后的jar文件
链接: https://pan.baidu.com/s/1dEYWhd3 密码: jbxr

附:反编译的注册文件

//
// Decompiled by Procyon v0.5.30
//

package com.xk72.charles;

import java.io.UnsupportedEncodingException;

public final class oFTR
{
    private static String Yuaz = "Thanks for looking at the source. Please register Charles if you use it.";
    private static oFTR knIQ;
    private boolean lktV;
    private String ecCn;
   
    // 为了减少页面篇幅,省略若干行无用代码......

    public oFTR() {
      this.lktV = false;
      this.ecCn = "Unregistered";
    }
   
    private oFTR(final String s, final String s2) {
      this(s, s2, 4);
    }
   
    private oFTR(final String ecCn, final String s, final int n) {
      this.lktV = false;
      this.ecCn = "Unregistered";
      try {
            final int n2 = 4;
            final String replaceAll = ecCn.replaceAll("[ \u1680\u180e\u2000\u200a\u202f\u205f\u3000]", " ");
            if (!this.Yuaz(this.knIQ(replaceAll, s, n2)) && (replaceAll.equals(ecCn) || !this.Yuaz(this.knIQ(ecCn, s, n2)))) {
                throw new LicenseException(this.Yuaz(2));
            }
      }
      catch (NumberFormatException ex) {
            throw new LicenseException(this.Yuaz(1));
      }
      this.ecCn = ecCn;
      this.lktV = true;
    }
   
    // 为了减少页面篇幅,省略若干行无用代码......

    public static boolean Yuaz() {
      return oFTR.knIQ.lktV;
    }
   
    public static void knIQ() {
      oFTR.knIQ = new oFTR();
    }
   
    public static String lktV() {
      final oFTR knIQ = oFTR.knIQ;
      switch (VSCw.Yuaz) {
            case 1: {
                return knIQ.ecCn;
            }
            case 2: {
                return knIQ.ecCn + " - Site License";
            }
            case 3: {
                return knIQ.ecCn + " - Multi-Site License";
            }
            default: {
                return knIQ.ecCn;
            }
      }
    }
   
    public static String Yuaz(final String s, final String s2) {
      oFTR knIQ;
      try {
            knIQ = new oFTR(s, s2);
      }
      catch (LicenseException ex) {
            return ex.getMessage();
      }
      oFTR.knIQ = knIQ;
      return null;
    }
   
    private boolean ecCn() {
      return this.lktV;
    }
   
    private String dnGU() {
      switch (VSCw.Yuaz) {
            case 1: {
                return this.ecCn;
            }
            case 2: {
                return this.ecCn + " - Site License";
            }
            case 3: {
                return this.ecCn + " - Multi-Site License";
            }
            default: {
                return this.ecCn;
            }
      }
    }

    // 为了减少页面篇幅,省略若干行无用代码......
}

rt2ryu 发表于 2017-12-3 01:01

小炜 发表于 2017-11-29 23:09
不了解动态编译的破解方式,能说下大概思路么?

还是下断点,输入错误数据验证,拦截断点,搜索输入数据,看数据被哪些方法或函数调用,跟踪下去破解方法或函数,对付加密混淆的应该效率会好一些

小炜 发表于 2017-11-29 23:09

rt2ryu 发表于 2017-11-29 20:52
最难就是猜public的几个方法上了,上动态编译会不会好找一些?

不了解动态编译的破解方式,能说下大概思路么?

Tsiang 发表于 2017-11-28 01:28

感谢!!!

亲亲多美丽 发表于 2017-11-28 06:16

学习了,谢谢分享

冰海浮云 发表于 2017-11-28 06:21

感谢分享,论坛有你更精彩!

ekanshao 发表于 2017-11-28 07:17

谢谢楼主分享!棒棒的!!

洛十肆 发表于 2017-11-28 07:28

谢谢分享

八LLH 发表于 2017-11-28 07:31

感谢楼主分享

fly_hong 发表于 2017-11-28 08:05

谢谢楼主,辛苦了。。。

powerz9860 发表于 2017-11-28 08:15

感谢楼主分享

weliong 发表于 2017-11-28 08:23

收藏备用 谢谢分享
页: [1] 2 3 4 5 6 7
查看完整版本: charles v4.2.1 破解方法