破解Charles 4.5.1
本帖最后由 scz 于 2019-11-14 12:23 编辑标题: Charles 4.5.1逆向工程
创建: 2019-10-17 09:37
更新: 2019-10-24 17:14
链接: http://scz.617.cn:8/misc/201910170937.txt
https://www.52pojie.cn/thread-1039171-1-1.html
Charles
https://www.charlesproxy.com/
https://www.charlesproxy.com/assets/release/4.5.1/charles-proxy-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()设断,命中时:
javax.swing.AbstractButton.setText (AbstractButton.java:297), pc = 0
javax.swing.AbstractButton.init (AbstractButton.java:2,128), pc = 6
javax.swing.JButton.<init> (JButton.java:131), pc = 18
javax.swing.JButton.<init> (JButton.java:104), pc = 3
com.xk72.charles.gui.frames.RegisterFrame.<init> (null), pc = 45
com.xk72.charles.gui.menus.HelpMenu$4.actionPerformed (null), pc = 8
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", "" ) );
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();
Stringstr = RegisterFrame.TryJ( this.tEdg ).getText().trim();
if ( ( paramActionEvent.length() > 0 ) && ( str.length() > 0 ) )
{
ObjectlocalObject;
/*
* 为了注册成功,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 )
{
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-18 17:17 scz
ZTZ问我剁过CobaltStrike没。这是你们黑客用的工具,像我这样正直的程序员,绝
对不会接触它。以为是个很难搞的目标,不然特意问它干啥。一搜破解漫天飞,只不
过原包不是官方公开下载而已。KINGX写过一篇怎么剁:
手把手教你破解CobaltStrike 3.12 -
https://kingx.me/CobaltStrike-Patch.html
这种剁起来实在太没有难度,也没必要啥都自己剁,搜着用吧。
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
SHA256d29cf6a1cf0ed00f096caed6a94f6633db1ce1b91490467ba39d394a45153a90
2019-10-24 17:14 scz
不要再用本文所说破解方案,看续篇:
《Charles 4.5.1逆向工程(2)》
http://scz.617.cn:8/misc/201910241714.txt
https://www.52pojie.cn/thread-1042815-1-1.html
TEAM MESMERiZE提供了通杀3.x、4.x的keygen。 private String RjRQ() {
return this.Rarr;
switch(gTDF.tEdg) {
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 总是报错,不知道怎么解决 xman55555 发表于 2019-10-22 15:23
private String RjRQ() {
return this.Rarr;
switch(gTDF.tEdg
没仔细看吧,有一句话,"只Patch这5个public method,其他private的扔掉即可",我给的那个YQUd.java就是最终形态,不是缩略版本。 顶顶顶顶顶顶顶顶顶
新人不懂....
借用这个"javassist.jar" 来处理更方便快捷~
虽然看不懂,但是破解某个东西是为了涨知识,支持正版是为了鼓励别人心血。赞赞赞
ixsec 发表于 2019-10-17 13:22
新人不懂....
借用这个"javassist.jar" 来处理更方便快捷~
这个场景用Javassist或任何其他字节码编辑器直接处理class并没有什么优势,最后的java无任何依赖,编译时毫无压力,还可以自己加注释留存备忘。一般只有碰上复杂class时才考虑直接修改class,不管是Javassist还是其他工具。 大佬说的这些都不太懂...毕竟我就不会java{:1_936:} 大佬,你用什么反编译Charles 4.5.1那个jar包的?4.5.1相对于4.2.8,那几个主要的方法被额外保护了,用jadx反编译失败。{:1_924:}
下断点?OD吗?我对PC端不了解{:1_937:}
大佬,可否帮忙解惑一下?{:1_889:} 感谢大佬分享!!! 平时用Fiddler更多 太棒了!学习中。。。