Java安全之Javassist动态编程( 二 )
文章插图
toClassHello类:public class Hello {public void say() {System.out.println("Hello");}}Test 类public class Test {public static void main(String[] args) throws Exception {ClassPool cp = ClassPool.getDefault();//在默认系统搜索路径获取ClassPool对象 。CtClass cc = cp.get("com.demo.Hello");//获取hello类的CtMethod m = cc.getDeclaredMethod("say"); //获取hello类的say方法m.insertBefore("{ System.out.println(\"Hello.say():\"); }");//在正文的开头插入字节码Class c = cc.toClass();//将此类转换为java.lang.Class对象Hello h = (Hello)c.newInstance(); //反射创建对象并进行强转h.say();调用方法say}}
文章插图
3 一些小想法按照我的理解来说就是可以去将类和字节码进行互相转换 。 那么按照这个思路来延申的话 , 我们可以做到什么呢?我首先想到的可能就是webshell的一些免杀 , 例如说Jsp的最常见的一些webshell , 都是采用Runtime , ProcessBuilder这两个类去进行构造 , 执行命令 。 按照WAF的惯性这些设备肯定是把这些常见的执行命令函数给拉入黑名单里面去 。 那么如果说可以转换成字节码的话呢?字节码肯定是不会被杀的 。 如果说这时候将Runtime这个类转换成字节码 , 内嵌在Jsp中 , 后面再使用Javassist来将字节码还原成类的话 , 如果转换的几个方法没被杀的话 , 是可以实现过WAF的 。 当然这些也只是我的一些臆想,因为Javassist并不是JDK中自带的 , 实现的话后面可以再研究一下 。 但是类加载器肯定是可以去加载字节码 , 然后实现执行命令的 。 这里只是抛砖引玉 , 更多的就不细说了 。 如果有更好的想法也可以提出来一起去交流 。
4 想法实现这里可以来思考一个问题 , 该怎么样才能动态传入参数去执行呢?那能想到的肯定是反射 。 如果我们用上面的思路 , 把全部代码都转换成字节码的话 , 其实就没有多大意义了 。 因为全是固定死的东西 , 他也只会执行并且得到同一个执行结果 。
我在这里能想到的就是将部分在代码里面固定死的代码给转换成字节码 , 然后再使用反射的方式去调用 。
public class test {public static void main(String[] args) {String string ="java.lang.Runtime";byte[] bytes1 = string.getBytes();System.out.println(Arrays.toString(bytes1));}}
获取结果:
[106,97,118,97,46,108,97,110,103,46,80,114,111,99,101,115,115,73,109,112,108]
现在已经是把结果给获取到了 , 但是我们需要知道字节码怎么样还原为String类型 。
在后面翻阅资料的时候 , 发现String的构造方法就直接能执行 , 来看看他的官方文档 。
文章插图
使用bytes去构造一个新的String
代码:
public class test {public static void main(String[] args) {byte[] bytes = new byte[]{106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101};String s = new String(bytes);System.out.println(s);}}
文章插图
public class test {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {byte[] b1 = new byte[]{106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101};String run = new String(b1);String command = "ipconfig";Class aClass = Class.forName(run);Constructor declaredConstructor = aClass.getDeclaredConstructor();declaredConstructor.setAccessible(true);Object o = declaredConstructor.newInstance();Method exec = aClass.getMethod("exec", String.class);Process process = (Process) exec.invoke(o,command);InputStream inputStream = process.getInputStream();//获取输出的数据String ipconfig = IOUtils.toString(inputStream,"gbk"); //字节输出流转换为字符System.out.println(ipconfig);
推荐阅读
- 计算机专业大一下学期,该选择学习Java还是Python
- 未来想进入AI领域,该学习Python还是Java大数据开发
- 气动 安全性均提升 Lazer推出新款Sphere头盔
- 谷歌发布一月安全补丁 修复Pixel音频、应用重启等问题
- 学习大数据是否需要学习JavaEE
- 年底网络安全盛会线上召开,行业专家共话七大议题
- Edge浏览器酝酿用户账户安全追踪功能 必要时可提醒修改密码
- 从事Java开发时发现基础差,是否应该选择辞职自学一段时间
- 扫码枪将钱扫走,却不需要密码,安全吗?
- 2021年Java和Python的应用趋势会有什么变化?