Java安全之动态加载字节码( 三 )

但它是一个private方法 , 还是不能直接调用,继续往上看到getTransletInstance(),
private Translet getTransletInstance()        throws TransformerConfigurationException {        try {            if (_name == null) return null;            if (_class == null) defineTransletClasses();//此处调用defineTransletClasses方法            // The translet needs to keep a reference to all its auxiliary class to prevent the GC from collecting them            AbstractTranslet translet = (AbstractTranslet)                    _class[_transletIndex].getConstructor().newInstance();            translet.postInitialization();            translet.setTemplates(this);            translet.setOverrideDefaultParser(_overrideDefaultParser);            translet.setAllowedProtocols(_accessExternalStylesheet);            if (_auxClasses != null) {                translet.setAuxiliaryClasses(_auxClasses);            }            return translet;        }        catch (InstantiationException | IllegalAccessException |                NoSuchMethodException | InvocationTargetException e) {            ErrorMsg err = new ErrorMsg(ErrorMsg.TRANSLET_OBJECT_ERR, _name);            throw new TransformerConfigurationException(err.toString(), e);        }    }还是private方法,继续找到newTransformer()方法
public synchronized Transformer newTransformer()        throws TransformerConfigurationException    {        TransformerImpl transformer;        transformer = new TransformerImpl(getTransletInstance(), _outputProperties,            _indentNumber, _tfactory);//调用了getTransletInstance方法        if (_uriResolver != null) {            transformer.setURIResolver(_uriResolver);        }        if (_tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) {            transformer.setSecureProcessing(true);        }        return transformer;    }是public方法了,可以直接调用,所以一条调用链就出来了
首先得设置TemplatesImpl对象的三个私有属性 , 这里我们用反射设置就行,三个属性:_bytecodes、 _name 和 _tfactory

  • _name:为任意字符串,只要不是null才可以进入defineTransletClasses()
    Java安全之动态加载字节码

    文章插图
  • _bytecodes:由字节码组成的数组,用来存放恶意代码,其值不能为null
  • _tfactory 需要是一个 TransformerFactoryImpl 对象,因为TemplatesImpl#defineTransletClasses() 方法里有调用_tfactory.getExternalExtensionsMap() ,如果是null会出错
另外TemplatesImpl 中对加载的字节码是有一定要求的:这个字节码对应的类必须是com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet 的子类所以,我们需要构造一个特殊的类:
package org.gk0d;import com.sun.org.apache.xalan.internal.xsltc.DOM;import com.sun.org.apache.xalan.internal.xsltc.TransletException;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;import com.sun.org.apache.xml.internal.serializer.SerializationHandler;public class HelloTemplatesImpl extends AbstractTranslet {    public void transform(DOM document, SerializationHandler[] handlers)            throws TransletException {}    public void transform(DOM document, DTMAxisIterator iterator,                          SerializationHandler handler) throws TransletException {}    public HelloTemplatesImpl() {        super();        System.out.println("Hello TemplatesImpl");    }}

推荐阅读