Java
  • About This Book
  • 🍖Prerequisites
    • 反射
      • 反射基本使用
      • 高版本JDK反射绕过
      • 反射调用命令执行
      • 反射构造HashMap
      • 方法句柄
    • 类加载
      • 动态加载字节码
      • 双亲委派模型
      • BCEL
      • SPI
    • RMI & JNDI
      • RPC Intro
      • RMI
      • JEP 290
      • JNDI
    • Misc
      • Unsafe
      • 代理模式
      • JMX
      • JDWP
      • JPDA
      • JVMTI
      • JNA
      • Java Security Manager
  • 👻Serial Journey
    • URLDNS
    • SerialVersionUID
    • Commons Collection 🥏
      • CC1-TransformedMap
      • CC1-LazyMap
      • CC6
      • CC3
      • CC2
    • FastJson 🪁
      • FastJson-Basic Usage
      • FastJson-TemplatesImpl
      • FastJson-JdbcRowSetImpl
      • FastJson-BasicDataSource
      • FastJson-ByPass
      • FastJson与原生反序列化(一)
      • FastJson与原生反序列化(二)
      • Jackson的原生反序列化利用
    • Other Components
      • SnakeYaml
      • C3P0
      • AspectJWeaver
      • Rome
      • Spring
      • Hessian
      • Hessian_Only_JDK
      • Kryo
      • Dubbo
  • 🌵RASP
    • JavaAgent
    • JVM
    • ByteCode
    • JNI
    • ASM 🪡
      • ASM Intro
      • Class Generation
      • Class Transformation
    • Rasp防御命令执行
    • OpenRASP
  • 🐎Memory Shell
    • Tomcat-Architecture
    • Servlet API
      • Listener
      • Filter
      • Servlet
    • Tomcat-Middlewares
      • Tomcat-Valve
      • Tomcat-Executor
      • Tomcat-Upgrade
    • Agent MemShell
    • WebSocket
    • 内存马查杀
    • IDEA本地调试Tomcat
  • ✂️JDBC Attack
    • MySQL JDBC Attack
    • H2 JDBC Attack
  • 🎨Templates
    • FreeMarker
    • Thymeleaf
    • Enjoy
  • 🎏MessageQueue
    • ActiveMQ CNVD-2023-69477
    • AMQP CVE-2023-34050
    • Spring-Kafka CVE-2023-34040
    • RocketMQ CVE-2023-33246
  • 🛡️Shiro
    • Shiro Intro
    • Request URI ByPass
    • Context Path ByPass
    • Remember Me反序列化 CC-Shiro
    • CB1与无CC依赖的反序列化链
  • 🍺Others
    • Deserialization Twice
    • A New Blazer 4 getter RCE
    • Apache Commons Jxpath
    • El Attack
    • Spel Attack
    • C3P0原生反序列化的JNDI打法
    • Log4j
    • Echo Tech
      • SpringBoot Under Tomcat
    • CTF 🚩
      • 长城杯-b4bycoffee (ROME反序列化)
      • MTCTF2022(CB+Shiro绕过)
      • CISCN 2023 西南赛区半决赛 (Hessian原生JDK+Kryo反序列化)
      • CISCN 2023 初赛 (高版本Commons Collections下其他依赖的利用)
      • CISCN 2021 总决赛 ezj4va (AspectJWeaver写字节码文件到classpath)
      • D^3CTF2023 (新的getter+高版本JNDI不出网+Hessian异常toString)
      • WMCTF2023(CC链花式玩法+盲读文件)
      • 第六届安洵杯网络安全挑战赛(CB PriorityQueue替代+Postgresql JDBC Attack+FreeMarker)
  • 🔍Code Inspector
    • CodeQL 🧶
      • Tutorial
        • Intro
        • Module
        • Predicate
        • Query
        • Type
      • CodeQL 4 Java
        • Basics
        • DFA
        • Example
    • SootUp ✨
      • Intro
      • Jimple
      • DFA
      • CG
    • Tabby 🔦
      • install
    • Theory
      • Static Analysis
        • Intro
        • IR & CFG
        • DFA
        • DFA-Foundation
        • Interprocedural Analysis
        • Pointer Analysis
        • Pointer Analysis Foundation
        • PTA-Context Sensitivity
        • Taint Anlysis
        • Datalog
Powered by GitBook
On this page
  • Intro
  • Lookup
  • MethodHandle
  • MethodType
  • QuickStart
  • Runtime#exec

Was this helpful?

  1. 🍖Prerequisites
  2. 反射

方法句柄

Intro

Java通过反射可以在运行时动态获取或修改类型字段、方法等信息,但反射的执行速度也成一大诟病。Java7开始提供另一套API称为方法句柄(Method Handle),其作用与反射类似,但执行效率比反射高,被称为现代化反射。

A method handle is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return values.

方法句柄是一种指向方法的强类型、可执行的引用,它的类型由方法的参数类型和返回值类型组成,而与方法所在类名和方法名无关。 它作为方法的抽象,使方法调用不再受所在类型的约束,能更好的支持动态类型语言特性。

几个关键的类:

  • Lookup:方法句柄的创建工厂类,方法的检查工作是在创建时处理的而非调用时处理

  • MethodType:方法的签名,包括返回值类型和参数类型

  • MethodHandle:方法句柄,用于动态访问类型的信息

Lookup

创建一个提供对公共方法访问的查找:

MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();

lookup方法可访问私有和受保护的方法

MethodHandles.Lookup lookup = MethodHandles.lookup();

Lookup对象提供几种查找对象的方法

  • invokevirtual

对象方法的查找

public MethodHandle findVirtual(Class<?> refc, String name, MethodType type)
  • invokestatic

静态方法查找

public MethodHandle findStatic(Class<?> refc, String name, MethodType type)
  • 查找构造函数

public MethodHandle findConstructor(Class<?> refc, MethodType type)
  • 查找非私有字段

/**
* Produces a method handle giving read access to a non-static field.
* The type of the method handle will have a return type of the field's
* value type.
* The method handle's single argument will be the instance containing
* the field.
*/
public MethodHandle findGetter(Class<?> refc, String name, Class<?> type)
/**
* Produces a method handle giving write access to a non-static field.
* The type of the method handle will have a void return type.
 * The method handle will take two arguments, the instance containing
* the field, and the value to be stored.
*/
public MethodHandle findSetter(Class<?> refc, String name, Class<?> type)

MethodHandle

使用invoke家族来调用

invoke、invokeWithArguments、invokeExact

MethodType

Lookup需要方法的签名才能找到方法句柄

public static MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes)

rtype为返回值类型,ptypes为参数类型

QuickStart

class Horse {
  public void race() {
    System.out.println("Horse.race()"); 
  }
}

class Deer {
  public void race() {
    System.out.println("Deer.race()");
  }
}

class Cobra {
  public void race() {
    System.out.println("How do you turn this on?");
  }
}

如何设计统一的方式调用race方法?

使用反射有性能损耗,抽象出一个包含race方法的接口则增加了接口约束,这时候就可以考虑方法句柄了。将race方法抽象成方法句柄,它们的句柄类型一致,对调用者暴露方法句柄即可。

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class MethodHandleTest {
    public void race(Object obj) throws Throwable {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodHandle race = lookup.findVirtual(obj.getClass(), "race", MethodType.methodType(void.class));
        race.invoke(obj);
    }

    public static void main(String[] args) throws Throwable {
        MethodHandleTest test = new MethodHandleTest();
        test.race(new Horse());
        test.race(new Deer());
    }
}

方法句柄也有权限问题,但与反射在方法调用时检查不同,它是在句柄创建阶段进行检查的,如果多次调用句柄,它比反射可以省下权限重复检查的开销。

但需注意的是,句柄的访问权限不取决于创建句柄的位置,而是 Lookup 对象的位置。

Runtime#exec

MethodHandles.Lookup lookup = MethodHandles.lookup();

MethodType mt1 = MethodType.methodType(Runtime.class);
MethodHandle getRuntime = lookup.findStatic(Runtime.class, "getRuntime", mt1);

MethodType mt2 = MethodType.methodType(Process.class, String.class);
MethodHandle exec = lookup.findVirtual(Runtime.class, "exec", mt2);

Object runTime = getRuntime.invokeWithArguments();
exec.invoke(runTime, "calc");

getRuntime没有参数,对应的MethodType只要传一个Runtime.class即可

Previous反射构造HashMapNext类加载

Last updated 11 months ago

Was this helpful?