吾爱破解 - LCG - LSG |安卓破解|病毒分析|破解软件|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

搜索
查看: 6517|回复: 71

[原创] 破解Charles 4.5.1

  [复制链接]
scz 发表于 2019-10-17 12:48
本帖最后由 scz 于 2019-10-22 16:42 编辑

标题: 破解Charles 4.5.1

创建: 2019-10-17 09:37
更新:
链接: http://scz.617.cn:8/misc/201910170937.txt

Charles
https://www.charlesproxy.com/
https://www.charlesproxy.com/ass ... oxy-4.5.1-win64.msi

前两天剁了Burp Pro 2.1.04,今天写写如何破解Charles 4.5.1。

这事是这么来的。当时还没剁Burp,上网找它的最新版及其破解,只是想用用。一
般这种时候会先去问几个搞WEB安全的兄弟,假设他们手里有久经考验的版本。有天
问一个兄弟,你现在用什么版本的Burp?他很高冷地说他现在不怎么用Burp,用
Charles多些。懒得理他,他看我不理他,直接把他购买的License发给我,好吧,我
被动拥有了一个Key。当时一心想用Burp,Charles暂放一边。剁完Burp收拣临时文档
时又看到Charles的Key,Burp已经上刑场了,大家都是Java帮的,有难要同当,给
Burp找几个陪斩的吧,故剁之。

Charles如果未注册,启动时有个10s倒计时,30天试用期,每运行30分钟就自动退出。

Charles缺省是用其自带JDK 11启动的:

C:\Program Files\Charles\jdk\

正常注册流程是:

启动Charles->Help->Register Charles->输入Registered Name/License Key

这里会弹一个对话框,有Register、Cancel两个按钮。如何找到Register按钮对应的
代码?假设Register按钮用到了JButton,在按钮上显示"Register"这个字符串时会
用到javax.swing.AbstractButton.setText(),查看它的调用栈回溯,或许就能定位
Register按钮对应的代码。

对javax.swing.AbstractButton.setText()设断,命中时:

[1] javax.swing.AbstractButton.setText (AbstractButton.java:297), pc = 0
[2] javax.swing.AbstractButton.init (AbstractButton.java:2,128), pc = 6
[3] javax.swing.JButton.<init> (JButton.java:131), pc = 18
[4] javax.swing.JButton.<init> (JButton.java:104), pc = 3
[5] com.xk72.charles.gui.frames.RegisterFrame.<init> (null), pc = 45
[6] com.xk72.charles.gui.menus.HelpMenu$4.actionPerformed (null), pc = 8
[7] javax.swing.AbstractButton.fireActionPerformed (AbstractButton.java:1,967), pc = 83

爽到了,关注"com.xk72.charles.gui.frames.RegisterFrame.class"。

比起Burp Pro 2.1.04,Charles 4.5.1的混淆程度太弱,说是一马平川不为过。据说
Charles早期版本没有混淆过,比如4.0.2,我以前没接触过。

反编译

C:\Program Files\Charles\lib\charles.jar

com.xk72.charles.gui.frames.RegisterFrame.class

--------------------------------------------------------------------------
public class RegisterFrame extends JDialog
{
    private final JTextField    tName;
    private final JTextField    tSerial;
    /*
     * Register按钮
     */
    private final JButton       bRegister;
    /*
     * Cancel按钮
     */
    private final JButton       bCancel;

    public RegisterFrame ( Frame paramFrame )
    {
        super( paramFrame, true );
        setTitle( "Register Charles" );
        this.tName      = new JTextField( 20 );
        this.tSerial    = new JTextField( 20 );
        this.bRegister  = new JButton( "Register" );
        this.bCancel    = new JButton( "Cancel" );

        Container   localContainer;

        (localContainer = getContentPane()).setLayout( new MigLayout( "wrap,fill", "[label][fill,grow]" ) );

        localContainer.add( new JLabel( "Registered Name:" ) );
        localContainer.add( this.tName );
        localContainer.add( new JLabel( "License Key:" ) );
        localContainer.add( this.tSerial );
        localContainer.add( this.bCancel, "tag cancel,split 2,span,center" );
        localContainer.add( this.bRegister, "tag ok" );
        this.bCancel.addActionListener( new gTDF( this ) );
        /*
         * 在此添加Register按钮的处理代码,据此关注
         *
         * com.xk72.charles.gui.frames.PeRA.class
         */
        this.bRegister.addActionListener( new PeRA( this ) );
        pack();
        if ( paramFrame != null )
        {
           ( paramFrame = new Point( paramFrame.getLocation() ) ).translate( 20, 20 );
            setLocation( paramFrame );
        }
        getRootPane().setDefaultButton( this.bRegister );
        getRootPane().getInputMap(1).put( KeyStroke.getKeyStroke( "ESCAPE" ), "escape" );
        getRootPane().getActionMap().put( "escape", new RegisterFrame.3( this ) );
    }
--------------------------------------------------------------------------

com.xk72.charles.gui.frames.PeRA.class

--------------------------------------------------------------------------
import com.xk72.charles.YQUd;

final class PeRA implements ActionListener
{
    PeRA( RegisterFrame paramRegisterFrame )
    {
    }

    public final void actionPerformed ( ActionEvent paramActionEvent )
    {
        paramActionEvent    = RegisterFrame.tEdg( this.tEdg ).getText().trim();

        String  str = RegisterFrame.TryJ( this.tEdg ).getText().trim();

        if ( ( paramActionEvent.length() > 0 ) && ( str.length() > 0 ) )
        {
            Object  localObject;

            /*
             * 为了注册成功,YQUd.tEdg()必须返回null。据此关注
             *
             * com.xk72.charles.YQUd.class
             */
            if ( ( localObject = YQUd.tEdg( paramActionEvent, str ) ) != null )
            {
                /*
                 * 注册失败
                 */
                ExtendedJOptionPane.tEdg( this.tEdg, localObject, "Charles Registration", 2 );
                return;
            }
            /*
             * 注册成功,显示注册信息
             */
            ExtendedJOptionPane.tEdg( this.tEdg, "Thank you for registering. Charles will now close. Please start Charles again to continue.", "Charles Registration", 1 );
            ( localObject = CharlesContext.getInstance() ).getConfiguration().getRegistrationConfiguration().setName( paramActionEvent );
            ( ( CharlesContext )localObject ).getConfiguration().getRegistrationConfiguration().setKey( str );
            ( ( CharlesContext )localObject ).exit( 0, true );
        }
    }
}
--------------------------------------------------------------------------

YQUd.class共有5个public method:

public com.xk72.charles.YQUd();
public static boolean tEdg();
public static void TryJ();
public static java.lang.String NCuT();
public static java.lang.String tEdg(java.lang.String, java.lang.String);

com.xk72.charles.YQUd.class

--------------------------------------------------------------------------
public final class YQUd
{
    private static YQUd TryJ;
    /*
     * 为true时表示已注册
     */
    private boolean     NCuT;

    public YQUd ()
    {
        this.NCuT   = false;
        this.Rarr   = "Unregistered";
    }

    /*
     * 为true时表示已注册
     */
    public static boolean tEdg ()
    {
        YQUd    var0    = TryJ;

        return TryJ.NCuT;
    }

    public static void TryJ ()
    {
        TryJ    = new YQUd();
    }

    /*
     * 这是要显示到"About Charles"的内容
     */
    public static String NCuT ()
    {
        YQUd    var0    = TryJ;

        switch( gTDF.tEdg[var0.aqrV.ordinal()] )
        {
        case 1:
            return var0.Rarr;
        case 2:
            return var0.Rarr + " - Site License";
        case 3:
            return var0.Rarr + " - Multi-Site License";
        default:
            return var0.Rarr;
        }
    }

    /*
     * 务必让本函数返回null
     */
    public static String tEdg ( String var0, String var1 )
    {
        YQUd    var3;

        try
        {
            var3    = new YQUd( var0, var1 );
        }
        catch ( LicenseException var2 )
        {
            return var2.getMessage();
        }
        TryJ    = var3;
        return null;
    }
--------------------------------------------------------------------------

编辑YQUd.java:

--------------------------------------------------------------------------
package com.xk72.charles;

public final class YQUd
{
    /*
     * 只Patch这5个public method,其他private的扔掉即可
     */

    public YQUd ()
    {
    }

    /*
     * 为true时表示已注册
     */
    public static boolean tEdg ()
    {
        return( true );
    }

    public static void TryJ ()
    {
    }

    /*
     * 这是要显示到"About Charles"的内容,这个内容任意
     */
    public static String NCuT ()
    {
        return "Anyting - Site License";
    }

    /*
     * 务必让本函数返回null
     */
    public static String tEdg ( String var0, String var1 )
    {
        return null;
    }
}
--------------------------------------------------------------------------

编译YQUd.java得到新的YQUd.class,替换charles.jar中的YQUd.class。

比起Burp,破解Charles实在是太简单了。要点是定位YQUd.class,每个版本混淆后
的名字都不一样,需要重新定位。由于已经讲清楚原理,以后破解都不需要动态调试
设断,直接在反编译器中静态定位。

最后说一下,前面那个购买License的兄弟,他是因为用了这么多年Charles破解版,
良心发现,决定支持一下正版,他做的对,我做的不对,不是反话。有些人可能认识
他,同盾马院长。

2019-10-22 16:34 scz

怎么还有人要class?前面写得很详细了,文中的YQUd.java就是最终形态,不是缩略
版本。可能有些人只搞WWW安全,不太看得懂前文。最终的替换包:

http://scz.617.cn/private/Charles_4_5_1.7z
http://scz.617.cn:8/private/Charles_4_5_1.7z

charles.jar
MD5     da5c25ab0d93b6ee726c42f4b87e1f7f
SHA256  d29cf6a1cf0ed00f096caed6a94f6633db1ce1b91490467ba39d394a45153a90

YQUd.class.7z

358 Bytes, 下载次数: 15, 下载积分: 吾爱币 -1 CB

怎么还有人要class,怪哉

免费评分

参与人数 24威望 +1 吾爱币 +27 热心值 +22 收起 理由
monika8 + 1 用心讨论,共获提升!
jason19659 + 1 + 1 思路非常棒
adolphzhang_ + 1 + 1 谢谢@Thanks!
抱歉、 + 1 + 1 谢谢@Thanks!
wapjxb + 1 谢谢@Thanks!
jxp1991 + 1 我很赞同!
5omggx + 1 + 1 膜拜大神
zhengjim + 1 + 1 我很赞同!
笙若 + 1 + 1 谢谢@Thanks!
liuyang10k + 1 + 1 热心回复!
pojieit + 1 + 1 我很赞同!
399 + 1 我很赞同!
huoxingshueva + 1 + 1 我很赞同!
三木零 + 1 + 1 热心回复!
WD丶活着 + 1 热心回复!
hellopojie + 1 + 1 4哥6666
Janem + 1 + 1 热心回复!
泳诗 + 1 我很赞同!
solleook + 1 + 1 热心回复!
LOLQAQ + 1 + 1 我很赞同!
夏雨微凉 + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Hmily + 1 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Danger_Robot + 1 + 1 用心讨论,共获提升!
hextest + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

xman55555 发表于 2019-10-22 15:23
    private String RjRQ() {
        return this.Rarr;
        switch(gTDF.tEdg[this.aqrV.ordinal()]) {
            case 1:
                return this.Rarr;
            case 2:
                return this.Rarr + " - Site License";
            case 3:
                return this.Rarr + " - Multi-Site License";
            default:
                return this.Rarr;
        }
    }

这个 gTDF.tEdg[this.aqrV.ordinal()] 总是报错,不知道怎么解决
 楼主| scz 发表于 2019-10-22 16:23
xman55555 发表于 2019-10-22 15:23
private String RjRQ() {
        return this.Rarr;
        switch(gTDF.tEdg[this.aqrV.ordinal() ...

没仔细看吧,有一句话,"只Patch这5个public method,其他private的扔掉即可",我给的那个YQUd.java就是最终形态,不是缩略版本。
hextest 发表于 2019-10-17 13:04
ixsec 发表于 2019-10-17 13:22
新人不懂....
借用这个"javassist.jar" 来处理更方便快捷~
1522770407cl 发表于 2019-10-17 13:23
虽然看不懂,但是破解某个东西是为了涨知识,支持正版是为了鼓励别人心血。赞赞赞
 楼主| scz 发表于 2019-10-17 13:40
ixsec 发表于 2019-10-17 13:22
新人不懂....
借用这个"javassist.jar" 来处理更方便快捷~

这个场景用Javassist或任何其他字节码编辑器直接处理class并没有什么优势,最后的java无任何依赖,编译时毫无压力,还可以自己加注释留存备忘。一般只有碰上复杂class时才考虑直接修改class,不管是Javassist还是其他工具。
ixsec 发表于 2019-10-17 13:41
大佬说的这些都不太懂...毕竟我就不会java
TwilightZ 发表于 2019-10-17 13:58
感谢分享,很好很强大!
xmhwws 发表于 2019-10-17 14:04
大佬,你用什么反编译Charles 4.5.1那个jar包的?4.5.1相对于4.2.8,那几个主要的方法被额外保护了,用jadx反编译失败。
下断点?OD吗?我对PC端不了解
大佬,可否帮忙解惑一下?
ly765893958 发表于 2019-10-17 14:06
感谢大佬分享!!!
夏雨微凉 发表于 2019-10-17 14:19
平时用Fiddler更多

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
happy曲月 + 1 + 1 兄台能否交流下fid的使用

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:禁止回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2019-11-14 02:00

Powered by Discuz!

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表