00 介绍
经过几个月的完善,我的工具 jar-analyzer 发布 1.0 版本了,总共接近五千行,不过代码质量不高。本文将从各个方面和大家介绍
首先可以做一个基本的介绍,程序的界面UI使用了 Swing 方式,并没有采用先进一些的 JavaFx 可能是因为我不太熟悉吧。另外原生的 Swing UI 非常丑,选择国外佬开发的 FlatLaf 皮肤即可变得美观许多
代码编辑器选用了 jsyntaxpane 开源项目,是一个很古老的项目,似乎是针对于 JDK 5/6 开发的,我对这个项目进行了魔改,拿过来放到这里
01 基本使用
以Log4j2为例,下载好 2.14.0 版本的 jar 包,直接搜索 Context 类的 lookup 方法,如图所示
可以发现下方有一个搜索结果
双击可以结果即可进行反编译,得到这个类的代码。并且我写了一个比较复杂的算法(暂且叫做算法吧)可以直接定位到这个方法
可以看到左边的游标直接定位到了调用方法的位置,关于这里如何精确定位,之后可能会写一篇文章和大家讲解分析。回到主题,在 IDEA 中我们可以 Ctrl + 左键来进入方法,技术有限我实现的方式是新建一个面板显示,可以在右侧的面板中看到这样的信息
这其中的每一条都是可以点击的,我们双击后就可以继续进入新的方法,并自动反编译,然后根据我写的算法精确定位到搜索方法
以此类推,你可以一路这样分析下去。如果不小心走错了线路,没关系,有一个历史面板,里面记录了你分析的历史,随时恢复到之前的状态
这里我还做了一个类似收藏夹的功能,你可以右键点击任何一个地方,保存这个项到右下角的面板。同样地在右下角面板右键可以删除保存的项
02 Spring分析
众所周知在 Java 开发中,离不开的就是 Spring 框架,所以有必要针对于 Spring 做一些事情。最终做到的效果是,输入一个 Jar 包直接得到所有的 Controller 和 Mapping 信息
当你点击 Controller 后即可显示出当前 Controller 中的所有 Mapping 信息,再次双击 Mapping 中的项,即可反编译并定位方法位置,同时会构建方法的调用关系与父类子类关系
03 文件树
可以像 JDGUI 等工具一样,在左侧浏览文件树,并且任意双击进行反编译
04 进阶搜索
首先解释下,什么是字符串搜索。我们任意写一个 Java 类
public static void main(String[] args) {
String a = "hello";
String b = "world";
System.out.println(a + b);
}
查看它的字节码可以发现方法中调用的字符串一般是 LDC 指令,因此通过分析该指令即可收集到绝大多数情况下的字符串的位置。其他的情况比如 GETSTATIC 指令从静态变量里拿也是一种方式
LDC "hello"
ASTORE 1
LDC "world"
ASTORE 2
回到工具本身,例如我们搜索 JNDI 字符串,可以定位到这里
不过要注意,输入字符串在其他搜索这里,不要错误输入到类名方法名那里。同时字符串支持包含搜索和正则搜索方式
另外和大家介绍下无脑搜索是什么,其实该功能我觉得并不好用,我是从类名/方法名/参数名等很多地方进行判断,如果包含了该字符串,将会全部显示出来,可能会有很多不需要的东西,如果你需要更加定制化的搜索,后面还有大招:表达式搜索
最后一种二进制搜索其实反而是最简单的,虽然 jar 和 class 是不可读的,但并不是完全的不可读,其中是会包含字符串的,如果你只希望粗略地搜索,这也是一种方式
05 表达式搜索
该功能应该是本工具最强大的功能了,定制化的搜索,可以满足绝大多数的需求,我将一步一步地和大家介绍
(1)基础搜索
例如我希望搜索方法名以 set 开头并以 value 结尾的方法
#method
.startWith("set")
.endWith("value")
例如我希望搜索类名包含 Context 且方法名包含 lookup 的方法
#method
.nameContains("lookup")
.classNameContains("Context")
例如我希望搜索返回 Process 类型共3个参数且第二个参数为 String 的方法
#method
.retureType("java.lang.Process")
.paramsNum(3)
.paramTypeMap(1,"java.lang.String")
(2)子类与父类
比如我们想找 javax.naming.spi.ObjectFactory 的所有子类(包括子类的子类等,程序内部会递归地寻找所有的类)
编写以下规则即可
#method
.isSubClassOf("javax.naming.spi.ObjectFactory")
如果想找某个类的所有父类,使用 isSuperClassOf 即可(注意全类名)
注意以上会直接找到所有符合条件类的所有方法,所以我建议再加一些过滤
#method
.isSubClassOf("javax.naming.spi.ObjectFactory")
.startWith("xxx")
.paramsNum(0)
(3)注解搜索
比如我们想找 @Controller 注解的所有类的所有方法
编写以下规则
#method
.hasClassAnno("Controller")
比如想找 @RequestMapping 注解的所有方法
#method
.hasAnno("RequestMapping")
同样地由于找到的是所有符合条件类的所有方法,所以我建议再加一些过滤
(4)实战分析
根据师傅们提供的 Swing RCE 条件:
必须有一个 set 方法
set 方法必须只有一个参数
这一个参数必须是 string 类型
该类必须是 Component 子类(包括间接子类)
因此我们编写一条规则
#method
.startWith("set")
.paramsNum(1)
.paramTypeMap(0,"java.lang.String")
.isSubClassOf("java.awt.Component")
效果如图
通过以上这些表达式,即可自定义搜索任何你需要的信息
另外,由于我使用了 SPEL 做底层支持,所以你可以 RCE 你自己
07 其他功能
我制作了一个插件搜索列表,只要双击你需要的内容,然后点击发送即可立即进行方法调用的搜索。目前我是写在代码中的,之后版本可能会开放出来这样的列表,自行配置使用
另外我调用了 ASM 的接口,可以直接查看字节码以及 ASM 代码,这个功能并没有什么用处其实,但可能个别情况下有一些意义
09 项目地址
项目地址为:https://github.com/4ra1n/jar-analyzer
提供了使用系统 exe 版本,使用内置 exe 版本,直接的 jar 包三种方式
欢迎大家反馈问题和意见,我会在工作之余抽空处理