前言
IAST JAVA agent方法调用链,污点值传播等信息的采集功能的实现很大程度上依赖着AOP,IAST JAVA agent是怎么实现AOP的呢,请继续往下看。
源码分析
首先我们来看一下 ENGINEENTRYPOINTCLASS
即 com.secnium.iast.core.AgentEngine
这个类。

install
方法通过反射被调用,入参里的Instrumentation inst
对AOP功能的实现十分重要,我们继续跟着inst
看下去。agentEngine.init(mode, propertiesFilePath, inst);
方法分别调用了各个引擎的init
方法,其中的TransformEngine
明显和AOP有关。

inst
通过init
方法传给了TransformEngine
类的成员变量,在调用start
方法时又传给了IastClassFileTransformer.init
这个静态方法。

如图添加了iastClassFileTransformer
到inst
中,用它来执行字节码转换。类的字节码在载入JVM之前会调用ClassFileTransformer
的transform
方法。
而IastClassFileTransformer
实现了ClassFileTransformer
接口。这块代码很多,重点在下图。

ClassVisitor
和ClassWriter
是ASM框架中常用的类。这里先是创建了ClassWriter,之后通过PLUGINS.initial
方法返回合适的ClassVisitor,cr.accept
修改字节码。

随意查看一个继承自ClassVisitor
的类。这里重写了visitMethod
方法,添加了判断的逻辑,这个方法在访问类里的每个方法时都会被调用,在适当的时候会返回ServletDispatcherAdviceAdapter
的实例。而这个类正是实现AOP的关键。

由图可见,ServletDispatcherAdviceAdapter
继承了AbstractAdviceAdapter
。而AbstractAdviceAdapter
最终继承了MethodVistor
,同时实现AsmTypes
和 AsmMethods
这两个接口。搞清楚继承关系后,我们继续看ServletDispatcherAdviceAdapter
的源码。

ServletDispatcherAdviceAdapter
重写了AbstractAdviceAdapter
的before
和after
方法,将代码插入到方法前后。这里调用了ASM框架的API给方法添加了try-catch结构并插入AsmMethods
里的方法以实现污点值传播的追踪。为什么重写这两个方法能实现插入代码呢。继续看AbstractAdviceAdapter
。

这里用abstract
关键字修饰了这两个方法,然后onMethodEnter
和onMethodExit
分别又调用了这两个方法。

这几个类都重写了这两个方法,可见后续如果要适配新的web框架,只需要添加一个继承自AbstractAdviceAdapter
同时重写这两个方法的类就行了。继续看它的父类。

这个类由ASM提供,方便我们插入代码。实际上这个类也是重写了MethodVisitor
的visitCode
等方法,最终实现了AOP。
总结
通过 -javaagent
参数指定IAST JAVA agent来启动Instrumentation
,并加载IastClassFileTransformer
利用ASM实现修改类文件的功能。同时也实现了插件化,方便后续开发。
本文迁移自知识星球“火线Zone”