Guest User

FPE sniffer

a guest
Jun 18th, 2012
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.30 KB | None | 0 0
  1. package paci.samples.bce;
  2.  
  3. import static org.objectweb.asm.Opcodes.DADD;
  4. import static org.objectweb.asm.Opcodes.DDIV;
  5. import static org.objectweb.asm.Opcodes.DMUL;
  6. import static org.objectweb.asm.Opcodes.DSUB;
  7. import static org.objectweb.asm.Opcodes.IFEQ;
  8. import static org.objectweb.asm.Opcodes.INVOKESTATIC;
  9.  
  10. import java.lang.instrument.ClassFileTransformer;
  11. import java.lang.instrument.IllegalClassFormatException;
  12. import java.lang.instrument.Instrumentation;
  13. import java.security.ProtectionDomain;
  14. import java.util.HashSet;
  15. import java.util.Set;
  16. import java.util.logging.Logger;
  17. import java.util.regex.Matcher;
  18. import java.util.regex.Pattern;
  19.  
  20. import org.objectweb.asm.ClassAdapter;
  21. import org.objectweb.asm.ClassReader;
  22. import org.objectweb.asm.ClassWriter;
  23. import org.objectweb.asm.Label;
  24. import org.objectweb.asm.MethodVisitor;
  25. import org.objectweb.asm.commons.GeneratorAdapter;
  26.  
  27. /*  
  28.  * @author [email protected]
  29.  */
  30. public class Agent {
  31.     public static void premain( String agentArgs,Instrumentation instr ) throws Exception {    
  32.         String targets = "paci.*";
  33.        
  34.         if( agentArgs != null )
  35.             targets = agentArgs;
  36.  
  37.         Set<String> targetSet = new HashSet<String>( );
  38.         for( String str : targets.split( ":" ) )
  39.             targetSet.add( str );
  40.         instr.addTransformer( new TransformerImpl( targetSet ) );
  41.     }
  42. }
  43.  
  44. class TransformerImpl implements ClassFileTransformer {
  45.     private static final Logger LOGGER = Logger.getLogger(
  46.         TransformerImpl.class.getPackage( ).getName( ) );
  47.     private final Set<Pattern> _targets;
  48.  
  49.     TransformerImpl( Set<String> targets ) {
  50.         _targets = new HashSet<Pattern>( );
  51.         for( String target : targets )
  52.             _targets.add( Pattern.compile( target ) );
  53.     }
  54.  
  55.     public byte[ ] transform( ClassLoader loader,
  56.                   final String className,
  57.                   Class<?> classBeingRedefined,
  58.                   ProtectionDomain protectionDomain,
  59.                   byte[ ] classfileBuffer )
  60.         throws IllegalClassFormatException {
  61.         boolean match = false;
  62.        
  63.         if( className.startsWith( "java/lang" ) || className.startsWith( "java/util" ) )
  64.             return null;
  65.        
  66.         if( _targets.size( ) > 0 )
  67.         {
  68.             for( Pattern target : _targets )
  69.             {
  70.                 Matcher matcher = target.matcher( className );
  71.                 if( matcher.matches( ) )
  72.                 {
  73.                     match = true;
  74.                     break;
  75.                 }
  76.             }
  77.         }
  78.         else
  79.             match = true;
  80.        
  81.         if( ! match )
  82.             return null;
  83.  
  84.         try {
  85.             ClassReader cr = new ClassReader( classfileBuffer );
  86.             ClassWriter cw = new ClassWriter( 0 );
  87.             cr.accept(
  88.                     new ClassAdapter( cw ) {
  89.                         public MethodVisitor visitMethod( int access,String name,String desc,String signature,String[ ] exceptions ) {
  90.                             MethodVisitor mv = super.visitMethod( access,name,desc,signature,exceptions );                         
  91.                             return new BytecodeModifier( access,name,desc,mv );
  92.                         }
  93.                     },ClassReader.EXPAND_FRAMES );
  94.    
  95.             return cw.toByteArray( );
  96.         }
  97.         catch( Exception e ) {
  98.             // If anything goes wrong, return the class as is and log this fact
  99.             LOGGER.severe( "Instrumentation of class " + className +
  100.                     " failed. Message is " + e.getMessage( ) + "." );
  101.            
  102.             return null;
  103.         }
  104.     }
  105. }
  106.  
  107. class BytecodeModifier extends GeneratorAdapter {
  108.     public BytecodeModifier( int access,String name,String desc,MethodVisitor mv ) {
  109.         super( mv,access,name,desc );
  110.     }
  111.  
  112.     private void generateChecks( String operation ) {
  113.         dup2( );
  114.         // Is it NaN?
  115.         mv.visitMethodInsn( INVOKESTATIC,"java/lang/Double","isNaN","(D)Z" );
  116.         Label label1 = new Label( );
  117.         mv.visitJumpInsn( IFEQ,label1 );
  118.         mv.visitLdcInsn( operation );
  119.         mv.visitMethodInsn(INVOKESTATIC, "paci/samples/bce/FPEListener", "resultIsNan", "(Ljava/lang/String;)V");
  120.         mv.visitLabel( label1 );
  121.  
  122.         dup2( );
  123.         // Is it infinite?
  124.         mv.visitMethodInsn( INVOKESTATIC,"java/lang/Double","isInfinite","(D)Z" );
  125.         Label label2 = new Label( );
  126.         mv.visitJumpInsn( IFEQ,label2 );
  127.         mv.visitLdcInsn( operation );
  128.         mv.visitMethodInsn(INVOKESTATIC, "paci/samples/bce/FPEListener", "resultIsInfinite", "(Ljava/lang/String;)V");
  129.         mv.visitLabel( label2 );
  130.     }
  131.    
  132.     @Override
  133.     public void visitInsn( int opcode ) {
  134.         mv.visitInsn( opcode );
  135.         switch( opcode ) {
  136.             case DDIV :
  137.                 generateChecks( "DIVIDE" );
  138.                 break;
  139.             case DMUL :
  140.                 generateChecks( "MULTIPLY" );
  141.                 break;
  142.             case DADD :
  143.                 generateChecks( "ADD" );
  144.                 break;
  145.             case DSUB :
  146.                 generateChecks( "SUBSTRACT" );
  147.                 break;
  148.         }
  149.     }
  150.  
  151.     @Override
  152.     public void visitMethodInsn( int opcode,String owner,String name,String desc ) {
  153.         // Slot is an allocation unit on the stack. One slot equals a word (32 bit).
  154.         // An object reference and 32-bit (or shorter) primitives take one slot,
  155.         // 64-bit primitives like long and double take two slots.
  156.  
  157.         super.visitMethodInsn( opcode,owner,name,desc );
  158.         // Intercept all java.lang.Math calls which are static, take one
  159.         // double as an argument and return double
  160.         if( opcode == INVOKESTATIC && owner.equals( "java/lang/Math" ) && desc.equals( "(D)D" ) ) {
  161.             String operation = name.toUpperCase( );
  162.             generateChecks( operation );
  163.         }
  164.     }
  165.    
  166.     /**
  167.      * Reports the maximum consumption of stack and local variables in slots.
  168.      */
  169.     @Override
  170.     public void visitMaxs( int maxStack,int maxLocals ) {
  171.         // Parameters are given in slots, not in bytes
  172.         // Our manipulation logic added 2 slots and no local variables
  173.         super.visitMaxs( maxStack + 2,maxLocals );
  174.     }
  175. }
Advertisement
Add Comment
Please, Sign In to add comment