Java安全之Javassist动态编程

作者 | nice_0e3
来源 | urlify.cn/M3U7Br
前言
在调试CC2链前先来填补知识盲区 , 先来了解一下Javassist具体的作用 。 在CC2链会用到Javassist以及PriorityQueue来构造利用链
1 Javassist 介绍Java 字节码以二进制的形式存储在 class 文件中 , 每一个 class 文件包含一个 Java 类或接口 。 Javaassist 就是一个用来处理 Java 字节码的类库 。
Javassist是一个开源的分析、编辑和创建Java字节码的类库 。
2 Javassist 使用这里主要讲一下主要的几个类:
ClassPoolClassPool:一个基于哈希表(Hashtable)实现的CtClass对象容器 , 其中键名是类名称 , 值是表示该类的CtClass对象(Hashtable和Hashmap类似都是实现map接口 , hashmap可以接收null的值 , 但是Hashtable不行) 。
常用方法:static ClassPool getDefault() 返回默认的类池 。 ClassPath insertClassPath(java.lang.String pathname)在搜索路径的开头插入目录或jar(或zip)文件 。 ClassPath insertClassPath(ClassPath cp)ClassPath在搜索路径的开头插入一个对象 。 java.lang.ClassLoader getClassLoader()获取类加载器toClass() , getAnnotations()在 CtClass等CtClass get(java.lang.String classname)从源中读取类文件 , 并返回对CtClass 表示该类文件的对象的引用 。 ClassPath appendClassPath(ClassPath cp)将ClassPath对象附加到搜索路径的末尾 。 CtClass makeClass(java.lang.String classname) 创建一个新的public类CtClassCtClass表示类 , 一个CtClass(编译时类)对象可以处理一个class文件 , 这些CtClass对象可以从ClassPoold的一些方法获得 。
常用方法:void setSuperclass(CtClass clazz) 更改超类 , 除非此对象表示接口 。 java.lang.Class toClass(java.lang.invoke.MethodHandles.Lookup lookup)将此类转换为java.lang.Class对象 。 byte[] toBytecode()将该类转换为类文件 。 void writeFile()将由此CtClass 对象表示的类文件写入当前目录 。 void writeFile(java.lang.String directoryName)将由此CtClass 对象表示的类文件写入本地磁盘 。 CtConstructor makeClassInitializer()制作一个空的类初始化程序(静态构造函数) 。 CtMethodCtMethod:表示类中的方法 。
CtConstructorCtConstructor的实例表示一个构造函数 。 它可能代表一个静态构造函数(类初始化器) 。
常用方法void setBody(java.lang.String src)设置构造函数主体 。 void setBody(CtConstructor src, ClassMap map)从另一个构造函数复制一个构造函数主体 。 CtMethod toMethod(java.lang.String name, CtClass declaring)复制此构造函数并将其转换为方法 。 ClassClassPath该类作用是用于通过 getResourceAsStream() 在 java.lang.Class 中获取类文件的搜索路径 。
构造方法:
ClassClassPath(java.lang.Class c)创建一个搜索路径 。 常见方法:java.net.URL find (java.lang.String classname)获取指定类文件的URL 。 java.io.InputStream openClassfile(java.lang.String classname)通过获取类文getResourceAsStream() 。 代码实例:ClassPool pool = ClassPool.getDefault();在默认系统搜索路径获取ClassPool对象 。
如果需要修改类搜索的路径需要使用insertClassPath方法进行修改 。
pool.insertClassPath(new ClassClassPath(this.getClass()));将本类所在的路径插入到搜索路径中
toBytecodepackage com.demo;import javassist.*;import java.io.IOException;import java.util.Arrays;public class testssit {public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException {ClassPool pool = ClassPool.getDefault();pool.insertClassPath(new ClassClassPath(demo.class.getClass()));CtClass ctClass = pool.get("com.demo.test");ctClass.setSuperclass(pool.get("com.demo.test"));//System.out.println(ctClass);byte[] bytes = ctClass.toBytecode();String s = Arrays.toString(bytes);System.out.println(s);


推荐阅读