Charles License 破解

破解的 Charles 版本 3.13.2, 下载路径:https://www.charlesproxy.com/download/previous-release

在线反编译 jar 工具: http://www.javadecompilers.com/, 使用 jd-gui 可以方便的把jar直接反编译

成java文件,在界面以只读的方式展现。 有可能某个工具反编译出来的代码在 IDEA 这种 IDE 会报

错,那是因为反编译不完整或者反编译出错,这时候就得多尝试几种反编译工具,找寻正确的核心代码。这

里具体的破解过程就不再赘述了,只记录核心思路。

实现破解方式

  1. 看源代码,找寻是否有 if ( check(license) ) {} else {} ** 这种类似的检查license** 的代码,如果找到了

可以修改这个类的字节码,把这里的判断条件强势改为 true, 就相当于绕过了检查license 判断,可以

实现该版本的破解了。

  1. 第一种方式太简单了,一般很少见。常见的是网上流传的各种失效的license key,思考一下,如果我们

自己是这个软件的开发者,有license key泄露了,会怎么做?安全的方式是将这个 license key 写死在

代码里进行判断,相当于一种黑名单的方式,那我们就根据这个license key 去代码里搜,找到对应的位置修

改字节码即可。

  1. 上面两种方式只能在对应的版本才能生效,只有找到它的激活码生成逻辑才能跨版本使用,才是最稳妥方

式。因为有高人指点,所以一开始就那用这种方式了。

经过一番折腾,找到 License 的校验代码:

 private long c(final String s, final String s2) {
        if (s2.length() != 18) {
            throw new LicenceException(this.a(0));
        }
        // 黑名单校验逻辑
        if (s2.equalsIgnoreCase("7055ce2f8cb4f9405f") || s2.equalsIgnoreCase("5bae9d8cdea32760ae") || s2.equalsIgnoreCase("f3264994d9ea6bc595") || s2.equalsIgnoreCase("b9930cef009d3a7865") || s2.equalsIgnoreCase("62bd6a5f95aa67998e") || s2.equalsIgnoreCase("a1c536c35904e64584") || s2.equalsIgnoreCase("d6e5590ecc05edd9b3") || s2.equalsIgnoreCase("8fbe36ce2726458b18") || s2.equalsIgnoreCase("042a8352caf1188945") || s2.equalsIgnoreCase("9d26d5088770221c3c") || s2.equalsIgnoreCase("e19b2a01905e4129bf") || s2.equalsIgnoreCase("68ebe4c9d792f31057") || s2.equalsIgnoreCase("4e4beb8a43e9feb9c7") || s2.equalsIgnoreCase("d04d85b44b306fc9ec") || s2.equalsIgnoreCase("2b5d21a38c9452e342") || s2.equalsIgnoreCase("88cb89c26a813bce44") || s2.equalsIgnoreCase("76c9ee78c8ab124054") || s2.equalsIgnoreCase("729db7c98163ac7d3d") || s2.equalsIgnoreCase("7c1d4761993c412472") || s2.equalsIgnoreCase("08bc0b7ec91cd0f4aa") || s2.equalsIgnoreCase("25bafae175decaedcc") || s2.equalsIgnoreCase("3181aae6822ef90ccd") || s2.equalsIgnoreCase("d7a8fe9dc9dc919f87") || s2.equalsIgnoreCase("728dae81d9d22aca03") || s2.equalsIgnoreCase("119a9b593348fa3e74") || s2.equalsIgnoreCase("04ab87c8d69667878e") || s2.equalsIgnoreCase("4b282d851ebd87a7bb") || s2.equalsIgnoreCase("ed526255313b756e42") || s2.equalsIgnoreCase("ed5ab211362ab25ca7") || s2.equalsIgnoreCase("18f4789a3df48f3b15") || s2.equalsIgnoreCase("67549e44b1c8d8d857") || s2.equalsIgnoreCase("4593c6c54227c4f17d") || s2.equalsIgnoreCase("1c59db29042e7df8ef") || s2.equalsIgnoreCase("a647e3dd42ce9b409b") || s2.equalsIgnoreCase("7e06d6a70b82858113") || s2.equalsIgnoreCase("ef4b5a48595197a373") || s2.equalsIgnoreCase("0ac55f6bebd0330640") || s2.equalsIgnoreCase("1beda9831c78994f43") || s2.equalsIgnoreCase("8a2b9debb15766bff9") || s2.equalsIgnoreCase("da0e7561b10d974216") || s2.equalsIgnoreCase("86257b04b8c303fd9a") || s2.equalsIgnoreCase("a4036b2761c9583fda") || s2.equalsIgnoreCase("18e69f6d5bc820d4d3")) {
            throw new LicenceException(this.a(1));
        }
        final long n = Long.parseLong(s2.substring(2, 10), 16) << 32 | Long.parseLong(s2.substring(10, 18), 16);
        final int int1 = Integer.parseInt(s2.substring(0, 2), 16);
        this.d(-5408575981733630035L);
        final long c;
        if (b(c = this.c(n)) != int1) {
            throw new LicenceException(this.a(1));
        }
        this.e = (int)(c << 32 >>> 32 >>> 24);
        if (this.e == 1) {
            this.f = 1;
        }
        else if (this.e == 3) {
            this.f = (int)(c << 32 >>> 32 >>> 16 & 0xFFL);
            if (this.f != 1 && this.f != 2 && this.f != 3) {
                throw new LicenceException(this.a(1));
            }
        }
        else {
            if (this.e <= 3) {
                throw new LicenceException(this.a(1));
            }
            this.f = (int)(c << 32 >>> 32 >>> 16 & 0xFFL);
        }
        this.d(8800536498351690864L);
        try {
            final byte[] bytes = s.getBytes("UTF-8");
            final int length;
            int n2;
            if ((n2 = (length = bytes.length) + 4) % 8 != 0) {
                n2 += 8 - n2 % 8;
            }
            final byte[] array = new byte[n2];
            System.arraycopy(bytes, 0, array, 4, length);
            array[0] = (byte)(length >> 24);
            array[1] = (byte)(length >> 16);
            array[2] = (byte)(length >> 8);
            array[3] = (byte)length;
            final byte[] c2 = this.c(array);
            int n3 = 0;
            byte[] array2;
            for (int length2 = (array2 = c2).length, i = 0; i < length2; ++i) {
                final int n4 = n3 ^ array2[i];
                n3 = (n4 << 3 | n4 >>> 29);
            }
            return 0xA58D19C600000000L | (long)(n3 ^ (int)(c >> 32)) << 32 >>> 32;
        }
        catch (UnsupportedEncodingException ex) {
            return -1L;
        }
    }

只能帮大家到这了,需要license的留言我帮你生成一个,全版本通用。这里记录点 tips

Tips

  1. 或运算的逆运算是 & ~. 如: x = a | b => b = x & ~b.
  2. 有些函数很复杂,找关键点,要这样想,这种验证的方式肯定不是开发者自己写的,大概率是网上开源的实现。善用搜索引擎,发现相似的源代码就能用了。(这里是RC5)
  3. 验证生成的license key是否有效,需要用到java的反射机制,调用这个方法,看返回值。
  4. 破解过程很有意思,多动脑,善用位运算,最好把它的每一步都理解到位,这样破解就很容易了。

你可能感兴趣的:(Charles License 破解)