感谢scz、surferxyz、h3110w0r1d-y等各位老师傅在前面开路,这篇文章只是跟着前面的老师傅脚步走,用了自己的方式(ClassFileTransformer)开刀。
基于burpsuite_pro_v2022.3.9.jar
cfr - 反编译工具
jadx - 反编译gui工具,可以查找引用
btrace - 运行状态跟踪工具
arthas - 用起来比btrace更方便的跟踪工具
IDEA
这里直接用h3110w0r1d-y老师傅的jar开看
启动方式:java -javaagent:BurpLoaderKeygen.jar -noverify -jar burpsuite_pro_v2022.3.9.jar
关于javaagent的详细介绍,可以看知道创宇的paper 认识 JavaAgent
上jadx,先看看老师傅们都搞了啥.
这里很明显,找到Class里面包含751a8be34c1a9ed9633d04be3ba075a7
的Class文件进行修改,变量p以及p2是负责定位要修改的位置,找到位置后进行patch.
先照搬进IDEA看看到底干了啥
这里可以看到,修改的地方其实很相近,那就dump整个class下来看看情况.
dump的办法
然后调用下
得到两个class文件
还记得之前的启动参数么,-noverify,由于这里简单粗暴的修改了原class的byte,导致jvm的字节码校验失败,根据这个道理,很容易就能找到师傅们干了什么,直接上图把.
用cfr反编译后,直接找empty
两个if被改成empty了,但是到这里我们还是不知道老师傅这么干的道理,继续往下走把.
根据之前cfr反编译出来的源码,能看到两个超级混淆的办法,void a以及bool b,知道类名跟方法名了,直接写个btrace,把调用链弄出来.
过滤后,得到以下输出
这里能看出,很多类都是动态加载进去的,想知道怎么调用还是得看看上一个调用类干了什么.
还记得之前的javaagent工程里面写了writeModifyClass方法不,把他放到最外层,然后修改下即可dump整个burp加载的class.
分析后发现...pev.class其实就是把nls.class从string数组变成byte数组然后解密加载
无实质性进展..尝试硬啃混淆过的验证类
首先,nls里面有两个核心方法,一个void a,另外一个boolean b
这里看到b方法,直接调用了a方法,其中var_9是new的object array,内容是var3_3的byte array,整个传入a方法第一个参数就是object [][],第二个参数就是固定的一串字符串
再查找整个nls.a调用,发现整个文件就两次调用,第二次调用也是差不多
那就可以认定,nls.a的第二个参数是固定的字符串,第一个参数是object [][]类型,具体传入了什么上arthas看看传入
由于是Windows,写个bat放到arthas的目录方便arthas attach到burp的进程
这里有个小技巧,如果burp调用太快手速不够,可以进入主界面后,用help->License->Update License来触发验证类的调用
用老师傅的jar先启动,然后运行bat就行
这里监控用watch 类名 方法名 -b -s -x 4
先输入个错误的license key,看看nls类里面方法a跟b什么情况
这里输入的是abcd,所以对着的是97,98,99,100,那就知道了其实nls.a传入的是字符串的byte array再放进Object[]
再尝试正确的License Key,根据之前代码进行分析得到下面的结论
结合注册流程,可以得知
有了以上信息,尝试构造nls.a的调用
之前有dump过破解跟原版的验证class,使用破解后的class用jar打包
jar -cvf burp.jar burp/nls.class
作为依赖塞进IDEA的工程,这里注意Run的配置要加上jvm参数-noverify
这里能成功解密了,现在就是这串License Key是怎么生成的问题了
继续用jadx查看Loader的注册机部分
这里很明显了,DES加密,key在最顶上是祖传的burpr0x!
大体流程就是字符串数组然后转成byte array用0作为分隔,再进行DES加密,最后base64
那么我们就可以根据这个流程反向写出解密函数
这里没什么好说的,直接跟着原理,先base64解码,然后des解密成byte array,转化成字符串后再用0分割成字符串数组
这里注意,解密出来的字符串数组长度会比原生的nls.a解密出来的字符串数组长,需要根据字符串数组长度删减返回的数组长度
其中长度是7的是License Key解密,长度10的是Activation Respond解密
到这里就差不多了,可以开始写自己的javaagent了
要把上面的java代码覆盖到原来的文件,我用的org.ow2.asm这个库,当然你用其他的库也可以,例如bytebuddy.
首先把java方法变成asm库的代码,这里我直接用asm库里面的asmifier(org.ow2.asm:asm-util:9.3)
在manifest定义Premain-Class以及Agent-Class
实现接口ClassFileTransformer
覆写激活类的方法
代码部分我就不详说了,有兴趣的可以自己围观
测试版本burpsuite_pro_v2022.5.1.jar
自己还是太菜不会用动态debug,只能用这样的笨方法来研究,代码附上,成品附上,欢迎各位大佬指导.
在这里感谢各位老师傅的路子,让刀burp不用找具体激活类具体是哪个,方便我这种后来破解的小白.
截至写完本文,2022.5.1还能这么刀
文件名称: E:\xxx\burp_latest\BurpLoaderKeygen.jar
文件大小:
18.1
KB (
18
,
580
字节)
修改时间:
2021
年
07
月
23
日,
10
:
20
:
48
MD5: B7E345B5594331516F49A709C04A3E41
SHA1: B9F4E9CA60E7493E459E21019441D115D2F43D98
SHA256:
63BE39F1AEEBEA9B86477ACEBBEFEE469A7562216BA8B253A4BB87B0A7A68566
CRC32: BCF7BD4F
计算时间:
0.00s
文件名称: E:\xxx\burp_latest\BurpLoaderKeygen.jar
文件大小:
18.1
KB (
18
,
580
字节)
修改时间:
2021
年
07
月
23
日,
10
:
20
:
48
MD5: B7E345B5594331516F49A709C04A3E41
SHA1: B9F4E9CA60E7493E459E21019441D115D2F43D98
SHA256:
63BE39F1AEEBEA9B86477ACEBBEFEE469A7562216BA8B253A4BB87B0A7A68566
CRC32: BCF7BD4F
计算时间:
0.00s
import
org.openjdk.btrace.core.annotations.
*
;
import
org.openjdk.btrace.core.BTraceUtils;
@BTrace
(unsafe
=
true)
public
class
nls {
@OnMethod
(clazz
=
"burp.nls"
, method
=
"a"
)
public static void void_a(
Object
[] var1,
Object
var2) {
BTraceUtils.println(
"calleded void a"
);
BTraceUtils.println(
"1st arg"
);
BTraceUtils.println(
"arg length: "
+
var1.length);
BTraceUtils.printArray(var1);
byte[] my_var1
=
(byte [])var1[
0
];
BTraceUtils.println(new String(my_var1));
BTraceUtils.println(
"2nd arg"
);
String var2_str
=
String.valueOf(var2);
BTraceUtils.println(var2_str);
BTraceUtils.println(
"-----------"
);
}
@OnMethod
(clazz
=
"burp.nls"
, method
=
"b"
)
public static void bool_b(
Object
[] var1,
Object
var2) {
BTraceUtils.println(
"called boolean b"
);
BTraceUtils.println(
"1st arg"
);
BTraceUtils.println(
"arg length: "
+
var1.length);
BTraceUtils.printArray(var1);
BTraceUtils.println(
"2nd arg"
);
String var2_str
=
String.valueOf(oos);
BTraceUtils.
print
(var2_str);
BTraceUtils.jstack();
BTraceUtils.println(
"-----------"
);
}
}
import
org.openjdk.btrace.core.annotations.
*
;
import
org.openjdk.btrace.core.BTraceUtils;
@BTrace
(unsafe
=
true)
public
class
nls {
@OnMethod
(clazz
=
"burp.nls"
, method
=
"a"
)
public static void void_a(
Object
[] var1,
Object
var2) {
BTraceUtils.println(
"calleded void a"
);
BTraceUtils.println(
"1st arg"
);
BTraceUtils.println(
"arg length: "
+
var1.length);
BTraceUtils.printArray(var1);
byte[] my_var1
=
(byte [])var1[
0
];
BTraceUtils.println(new String(my_var1));
BTraceUtils.println(
"2nd arg"
);
String var2_str
=
String.valueOf(var2);
BTraceUtils.println(var2_str);
BTraceUtils.println(
"-----------"
);
}
@OnMethod
(clazz
=
"burp.nls"
, method
=
"b"
)
public static void bool_b(
Object
[] var1,
Object
var2) {
BTraceUtils.println(
"called boolean b"
);
BTraceUtils.println(
"1st arg"
);
BTraceUtils.println(
"arg length: "
+
var1.length);
BTraceUtils.printArray(var1);
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2023-1-16 16:47
被kanxue编辑
,原因: