ysoserial源码结构分析
1.前言
之前也花了几天晚上熟悉了一下commonscollections系列的构造,那么学习一下这个项目是如何设计的也挺重要,多学习大佬如何写代码应该也能对自己的代码能力有提升吧~2333
2.项目结构:
首先代码结构如上图所示
exploit文件夹下主要是放一些主要的利用模块,比如如下两个例子
这里用java -cp指定在包ysoserial/exploit的JRMPClinent中寻找主类来执行,那么其中的payload位于payloads文件夹下
比如就如RMIRegistryExploit.java举例:
首先main函数从命令行接收一些初始化参数,比如目标主机的地址和端口以及要执行的命令,接着访问远程注册表服务
初始化结束后,此时要初始化gadget,这里直接通过包名和payload的值确定我们要利用的类完整路径,比如这里payload用commonscollections1为例
这里将通过class.forname加载所需要的payload类,接着判断是否远程是否为ssl链接,如果不是默认非ssl的rmi请求,则upgrade为ssl的rmi请求
接着调用exploit进行payload发送,在exploit函数中这种调用方式还有点意思,封装了一个call方法
这里首先checkingSecurityManager初始化抛出异常
看看callWrapped函数,,这里如何就是个Clallable类的实例,可以看到这里调用call方法
而call是定义callable类时就定义好的,因此这里进入call方法内部,主要就是①根据之前的payload调用其getobject方法,来返回对应gadget的实例
然后②这处用了个releasePayload方法,传入了上文拿到的objectpayload和object,然后感觉这样设计只是为了代码的健壮性,这里最后验证通过class.forname加载的类调用newinstance后是否是releaseableObjectPayload的实例或其父类接口的实例,它父类接口就是ObjectPayload,如果if条件满足则调用releasese方法
payloads文件夹中主要包括注解和一些工具类,包括找class文件,以及生成gadget,判断java版本的,以及paloadrunner里本地测试gadget,以及也直接封装了一些反射的方法
比如payloadrun就可以直接调试gadget,默认也存储了一些命令
最后几个类封装的序列化和反序列化的类,以及封装的字符串操作的类,以及命令行下根据输入参数生成payload的generatePayload类
以cc1链为例,payloadRunner.run来测试gadget
那么添加自己的链也很容易,只需要实现ObjectPayload接口即可,只需要定义好getObject的返回类型即可
所以整个项目而言,主要包括:
1.exploit类,用于远程attack
2.payload生成类,用于根据gadget生成序列化字节码
3.辅助类,序列化、反序列化、字符串处理、反射等重复性操作封装为辅助类
4.gadget,主要定义为定义好的利用链