本帖最后由 小炜 于 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. 执行反编译命令,这里我用的是[procyon-decompiler](https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler)
[Shell] 纯文本查看 复制代码 java -jar procyon-decompiler-0.5.30.jar -o output ~/Desktop/charles.jar
2. 在生成output文件夹搜索未注册的关键字
[Shell] 纯文本查看 复制代码
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工具来完成修改某个方法的内容,这恰好是我们需要的。感兴趣的可以自行搜下相关资料,这里就不细说了,直接附上修改字节码的代码:
[Java] 纯文本查看 复制代码
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[0].setBody("{this.ecCn = \"Cracked By Freeway www.58pojie.com\";\nthis.lktV = true;}");
cca[1].setBody("{this.ecCn = \"Cracked By Freeway www.58pojie.com\";\nthis.lktV = true;}");
oFTR.writeFile("/Users/fengyiwei/Desktop/");
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. 将修改后的字节码更新至jar中
[Shell] 纯文本查看 复制代码 jar -uvf charles.jar com
破解后的jar文件
链接: https://pan.baidu.com/s/1dEYWhd3 密码: jbxr
附:反编译的注册文件
[Java] 纯文本查看 复制代码
//
// 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[knIQ.RvLX.ordinal()]) {
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[this.RvLX.ordinal()]) {
case 1: {
return this.ecCn;
}
case 2: {
return this.ecCn + " - Site License";
}
case 3: {
return this.ecCn + " - Multi-Site License";
}
default: {
return this.ecCn;
}
}
}
// 为了减少页面篇幅,省略若干行无用代码......
} |