Example #1
0
 // not used anymore.
 private void notTestGetInner() throws Exception {
   ClassPool pool = ClassPool.getDefault();
   CtClass c = pool.get("javassist.CtMethod.ConstParameter");
   CtClass d = pool.get("javassist.CtMethod.ConstParameter");
   CtClass e = pool.get("javassist.CtMethod$ConstParameter");
   assertSame(c, d);
   assertSame(c, e);
   try {
     c = pool.get("test2.Inner.Fake");
     fail("found not-existing class");
   } catch (NotFoundException ex) {
   }
 }
Example #2
0
  public void not_testURLClassPath() throws Exception {
    String host = "www.csg.is.titech.ac.jp";
    String path = "/~chiba/tmp/";
    String url;

    ClassPool cp = new ClassPool(null);
    cp.insertClassPath(new URLClassPath(host, 80, path, "test"));

    url = cp.find("test.TestClassPath").toString();
    System.out.println(url);
    assertEquals("http://" + host + ":80" + path + "test/TestClassPath.class", url);

    assertNull(cp.find("test.No"));
  }
Example #3
0
  public void testInheritance() throws Exception {
    ClassPool pool = ClassPool.getDefault();
    String classname = "test2.Inherit";
    CtClass target = pool.get(classname);
    String src =
        "public void sampleMethod() {"
            + "  test2.Inherit i = new test2.Inherit();"
            + "  test2.Inherit2 i2 = i;"
            + "  test2.Inherit3 i3 = i;"
            + "  i3.foo2(); i3.foo2(); i2.foo1(); }";

    CtMethod newmethod = CtNewMethod.make(src, target);
    target.addMethod(newmethod);
    target.writeFile();
  }
  /**
   * Writes the given word to the given writer, after having adapted it, based on the renamed class
   * names.
   */
  private void writeUpdatedWord(Writer writer, String word) throws IOException {
    if (word.length() > 0) {
      String newWord = word;

      boolean containsDots = word.indexOf('.') >= 0;

      // Replace dots by forward slashes.
      String className =
          containsDots ? word.replace('.', ClassConstants.INTERNAL_PACKAGE_SEPARATOR) : word;

      // Find the class corrsponding to the word.
      Clazz clazz = classPool.getClass(className);
      if (clazz != null) {
        // Update the word if necessary.
        String newClassName = clazz.getName();
        if (!className.equals(newClassName)) {
          // Replace forward slashes by dots.
          newWord =
              containsDots
                  ? newClassName.replace(ClassConstants.INTERNAL_PACKAGE_SEPARATOR, '.')
                  : newClassName;
        }
      }

      writer.write(newWord);
    }
  }
Example #5
0
  public void testInner() throws Exception {
    ClassPool pool = ClassPool.getDefault();
    String classname = "test2.Inner";
    CtClass target = pool.get(classname);
    String src =
        "public void sampleMethod() throws Exception {"
            + "java.util.Properties props = new java.util.Properties();"
            + "java.rmi.activation.ActivationGroupDesc.CommandEnvironment ace "
            + " = null;"
            + "java.rmi.activation.ActivationGroupDesc agd "
            + " = new java.rmi.activation.ActivationGroupDesc(props,ace);}";
    CtMethod newmethod = CtNewMethod.make(src, target);
    target.addMethod(newmethod);

    String src2 =
        "public java.lang.Character.Subset sampleMethod2() {"
            + "  java.lang.Character.Subset s "
            + "    = Character.UnicodeBlock.HIRAGANA; "
            + "  return s; }";
    CtMethod newmethod2 = CtNewMethod.make(src2, target);
    target.addMethod(newmethod2);

    target.writeFile();
  }
Example #6
0
  /**
   * Finds the specified class using <code>ClassPath</code>. If the source throws an exception, this
   * returns null.
   *
   * <p>This method can be overridden by a subclass of <code>Loader</code>. Note that the overridden
   * method must not throw an exception when it just fails to find a class file.
   *
   * @return null if the specified class could not be found.
   * @throws ClassNotFoundException if an exception is thrown while obtaining a class file.
   */
  protected Class findClass(String name) throws ClassNotFoundException {
    byte[] classfile;
    try {
      if (source != null) {
        if (translator != null) translator.onLoad(source, name);

        try {
          classfile = source.get(name).toBytecode();
        } catch (NotFoundException e) {
          return null;
        }
      } else {
        String jarname = "/" + name.replace('.', '/') + ".class";
        InputStream in = this.getClass().getResourceAsStream(jarname);
        if (in == null) return null;

        classfile = ClassPoolTail.readStream(in);
      }
    } catch (Exception e) {
      throw new ClassNotFoundException(
          "caught an exception while obtaining a class file for " + name, e);
    }

    int i = name.lastIndexOf('.');
    if (i != -1) {
      String pname = name.substring(0, i);
      if (getPackage(pname) == null)
        try {
          definePackage(pname, null, null, null, null, null, null, null);
        } catch (IllegalArgumentException e) {
          // ignore.  maybe the package object for the same
          // name has been created just right away.
        }
    }

    if (domain == null) return defineClass(name, classfile, 0, classfile.length);
    else return defineClass(name, classfile, 0, classfile.length, domain);
  }
  /** Performs obfuscation of the given program class pool. */
  public void execute(ClassPool programClassPool, ClassPool libraryClassPool) throws IOException {
    // Check if we have at least some keep commands.
    if (configuration.keep == null
        && configuration.applyMapping == null
        && configuration.printMapping == null) {
      throw new IOException("You have to specify '-keep' options for the obfuscation step.");
    }

    // Clean up any old visitor info.
    programClassPool.classesAccept(new ClassCleaner());
    libraryClassPool.classesAccept(new ClassCleaner());

    // If the class member names have to correspond globally,
    // link all class members in all classes, otherwise
    // link all non-private methods in all class hierarchies.
    ClassVisitor memberInfoLinker =
        configuration.useUniqueClassMemberNames
            ? (ClassVisitor) new AllMemberVisitor(new MethodLinker())
            : (ClassVisitor) new BottomClassFilter(new MethodLinker());

    programClassPool.classesAccept(memberInfoLinker);
    libraryClassPool.classesAccept(memberInfoLinker);

    // Create a visitor for marking the seeds.
    NameMarker nameMarker = new NameMarker();
    ClassPoolVisitor classPoolvisitor =
        ClassSpecificationVisitorFactory.createClassPoolVisitor(
            configuration.keep, nameMarker, nameMarker, false, false, true);
    // Mark the seeds.
    programClassPool.accept(classPoolvisitor);
    libraryClassPool.accept(classPoolvisitor);

    // All library classes and library class members keep their names.
    libraryClassPool.classesAccept(nameMarker);
    libraryClassPool.classesAccept(new AllMemberVisitor(nameMarker));

    // Mark attributes that have to be kept.
    AttributeUsageMarker requiredAttributeUsageMarker = new AttributeUsageMarker();

    AttributeVisitor optionalAttributeUsageMarker =
        configuration.keepAttributes == null
            ? null
            : new AttributeNameFilter(
                new ListParser(new NameParser()).parse(configuration.keepAttributes),
                requiredAttributeUsageMarker);

    programClassPool.classesAccept(
        new AllAttributeVisitor(
            true,
            new RequiredAttributeFilter(
                requiredAttributeUsageMarker, optionalAttributeUsageMarker)));

    // Remove the attributes that can be discarded. Note that the attributes
    // may only be discarded after the seeds have been marked, since the
    // configuration may rely on annotations.
    programClassPool.classesAccept(new AttributeShrinker());

    // Apply the mapping, if one has been specified. The mapping can
    // override the names of library classes and of library class members.
    if (configuration.applyMapping != null) {
      WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn);

      MappingReader reader = new MappingReader(configuration.applyMapping);

      MappingProcessor keeper =
          new MultiMappingProcessor(
              new MappingProcessor[] {
                new MappingKeeper(programClassPool, warningPrinter),
                new MappingKeeper(libraryClassPool, null),
              });

      reader.pump(keeper);

      // Print out a summary of the warnings if necessary.
      int mappingWarningCount = warningPrinter.getWarningCount();
      if (mappingWarningCount > 0) {
        System.err.println(
            "Warning: there were "
                + mappingWarningCount
                + " kept classes and class members that were remapped anyway.");
        System.err.println(
            "         You should adapt your configuration or edit the mapping file.");

        if (!configuration.ignoreWarnings) {
          System.err.println("         If you are sure this remapping won't hurt,");
          System.err.println(
              "         you could try your luck using the '-ignorewarnings' option.");
          throw new IOException("Please correct the above warnings first.");
        }
      }
    }

    // Come up with new names for all classes.
    DictionaryNameFactory classNameFactory =
        configuration.classObfuscationDictionary != null
            ? new DictionaryNameFactory(configuration.classObfuscationDictionary, null)
            : null;

    DictionaryNameFactory packageNameFactory =
        configuration.packageObfuscationDictionary != null
            ? new DictionaryNameFactory(configuration.packageObfuscationDictionary, null)
            : null;

    programClassPool.classesAccept(
        new ClassObfuscator(
            programClassPool,
            classNameFactory,
            packageNameFactory,
            configuration.useMixedCaseClassNames,
            configuration.keepPackageNames,
            configuration.flattenPackageHierarchy,
            configuration.repackageClasses,
            configuration.allowAccessModification));

    // Come up with new names for all class members.
    NameFactory nameFactory = new SimpleNameFactory();

    if (configuration.obfuscationDictionary != null) {
      nameFactory = new DictionaryNameFactory(configuration.obfuscationDictionary, nameFactory);
    }

    WarningPrinter warningPrinter = new WarningPrinter(System.err, configuration.warn);

    // Maintain a map of names to avoid [descriptor - new name - old name].
    Map descriptorMap = new HashMap();

    // Do the class member names have to be globally unique?
    if (configuration.useUniqueClassMemberNames) {
      // Collect all member names in all classes.
      programClassPool.classesAccept(
          new AllMemberVisitor(
              new MemberNameCollector(configuration.overloadAggressively, descriptorMap)));

      // Assign new names to all members in all classes.
      programClassPool.classesAccept(
          new AllMemberVisitor(
              new MemberObfuscator(
                  configuration.overloadAggressively, nameFactory, descriptorMap)));
    } else {
      // Come up with new names for all non-private class members.
      programClassPool.classesAccept(
          new MultiClassVisitor(
              new ClassVisitor[] {
                // Collect all private member names in this class and down
                // the hierarchy.
                new ClassHierarchyTraveler(
                    true,
                    false,
                    false,
                    true,
                    new AllMemberVisitor(
                        new MemberAccessFilter(
                            ClassConstants.INTERNAL_ACC_PRIVATE,
                            0,
                            new MemberNameCollector(
                                configuration.overloadAggressively, descriptorMap)))),

                // Collect all non-private member names anywhere in the hierarchy.
                new ClassHierarchyTraveler(
                    true,
                    true,
                    true,
                    true,
                    new AllMemberVisitor(
                        new MemberAccessFilter(
                            0,
                            ClassConstants.INTERNAL_ACC_PRIVATE,
                            new MemberNameCollector(
                                configuration.overloadAggressively, descriptorMap)))),

                // Assign new names to all non-private members in this class.
                new AllMemberVisitor(
                    new MemberAccessFilter(
                        0,
                        ClassConstants.INTERNAL_ACC_PRIVATE,
                        new MemberObfuscator(
                            configuration.overloadAggressively, nameFactory, descriptorMap))),

                // Clear the collected names.
                new MapCleaner(descriptorMap)
              }));

      // Come up with new names for all private class members.
      programClassPool.classesAccept(
          new MultiClassVisitor(
              new ClassVisitor[] {
                // Collect all member names in this class.
                new AllMemberVisitor(
                    new MemberNameCollector(configuration.overloadAggressively, descriptorMap)),

                // Collect all non-private member names higher up the hierarchy.
                new ClassHierarchyTraveler(
                    false,
                    true,
                    true,
                    false,
                    new AllMemberVisitor(
                        new MemberAccessFilter(
                            0,
                            ClassConstants.INTERNAL_ACC_PRIVATE,
                            new MemberNameCollector(
                                configuration.overloadAggressively, descriptorMap)))),

                // Assign new names to all private members in this class.
                new AllMemberVisitor(
                    new MemberAccessFilter(
                        ClassConstants.INTERNAL_ACC_PRIVATE,
                        0,
                        new MemberObfuscator(
                            configuration.overloadAggressively, nameFactory, descriptorMap))),

                // Clear the collected names.
                new MapCleaner(descriptorMap)
              }));
    }

    // Some class members may have ended up with conflicting names.
    // Come up with new, globally unique names for them.
    NameFactory specialNameFactory = new SpecialNameFactory(new SimpleNameFactory());

    // Collect a map of special names to avoid
    // [descriptor - new name - old name].
    Map specialDescriptorMap = new HashMap();

    programClassPool.classesAccept(
        new AllMemberVisitor(
            new MemberSpecialNameFilter(
                new MemberNameCollector(
                    configuration.overloadAggressively, specialDescriptorMap))));

    libraryClassPool.classesAccept(
        new AllMemberVisitor(
            new MemberSpecialNameFilter(
                new MemberNameCollector(
                    configuration.overloadAggressively, specialDescriptorMap))));

    // Replace conflicting non-private member names with special names.
    programClassPool.classesAccept(
        new MultiClassVisitor(
            new ClassVisitor[] {
              // Collect all private member names in this class and down
              // the hierarchy.
              new ClassHierarchyTraveler(
                  true,
                  false,
                  false,
                  true,
                  new AllMemberVisitor(
                      new MemberAccessFilter(
                          ClassConstants.INTERNAL_ACC_PRIVATE,
                          0,
                          new MemberNameCollector(
                              configuration.overloadAggressively, descriptorMap)))),

              // Collect all non-private member names in this class and
              // higher up the hierarchy.
              new ClassHierarchyTraveler(
                  true,
                  true,
                  true,
                  false,
                  new AllMemberVisitor(
                      new MemberAccessFilter(
                          0,
                          ClassConstants.INTERNAL_ACC_PRIVATE,
                          new MemberNameCollector(
                              configuration.overloadAggressively, descriptorMap)))),

              // Assign new names to all conflicting non-private members
              // in this class and higher up the hierarchy.
              new ClassHierarchyTraveler(
                  true,
                  true,
                  true,
                  false,
                  new AllMemberVisitor(
                      new MemberAccessFilter(
                          0,
                          ClassConstants.INTERNAL_ACC_PRIVATE,
                          new MemberNameConflictFixer(
                              configuration.overloadAggressively,
                              descriptorMap,
                              warningPrinter,
                              new MemberObfuscator(
                                  configuration.overloadAggressively,
                                  specialNameFactory,
                                  specialDescriptorMap))))),

              // Clear the collected names.
              new MapCleaner(descriptorMap)
            }));

    // Replace conflicting private member names with special names.
    // This is only possible if those names were kept or mapped.
    programClassPool.classesAccept(
        new MultiClassVisitor(
            new ClassVisitor[] {
              // Collect all member names in this class.
              new AllMemberVisitor(
                  new MemberNameCollector(configuration.overloadAggressively, descriptorMap)),

              // Collect all non-private member names higher up the hierarchy.
              new ClassHierarchyTraveler(
                  false,
                  true,
                  true,
                  false,
                  new AllMemberVisitor(
                      new MemberAccessFilter(
                          0,
                          ClassConstants.INTERNAL_ACC_PRIVATE,
                          new MemberNameCollector(
                              configuration.overloadAggressively, descriptorMap)))),

              // Assign new names to all conflicting private members in this
              // class.
              new AllMemberVisitor(
                  new MemberAccessFilter(
                      ClassConstants.INTERNAL_ACC_PRIVATE,
                      0,
                      new MemberNameConflictFixer(
                          configuration.overloadAggressively,
                          descriptorMap,
                          warningPrinter,
                          new MemberObfuscator(
                              configuration.overloadAggressively,
                              specialNameFactory,
                              specialDescriptorMap)))),

              // Clear the collected names.
              new MapCleaner(descriptorMap)
            }));

    // Print out any warnings about member name conflicts.
    int warningCount = warningPrinter.getWarningCount();
    if (warningCount > 0) {
      System.err.println(
          "Warning: there were " + warningCount + " conflicting class member name mappings.");
      System.err.println("         Your configuration may be inconsistent.");

      if (!configuration.ignoreWarnings) {
        System.err.println("         If you are sure the conflicts are harmless,");
        System.err.println("         you could try your luck using the '-ignorewarnings' option.");
        throw new IOException("Please correct the above warnings first.");
      }
    }

    // Print out the mapping, if requested.
    if (configuration.printMapping != null) {
      PrintStream ps =
          isFile(configuration.printMapping)
              ? new PrintStream(
                  new BufferedOutputStream(new FileOutputStream(configuration.printMapping)))
              : System.out;

      // Print out items that will be removed.
      programClassPool.classesAcceptAlphabetically(new MappingPrinter(ps));

      if (ps != System.out) {
        ps.close();
      }
    }

    // Actually apply the new names.
    programClassPool.classesAccept(new ClassRenamer());
    libraryClassPool.classesAccept(new ClassRenamer());

    // Update all references to these new names.
    programClassPool.classesAccept(new ClassReferenceFixer(false));
    libraryClassPool.classesAccept(new ClassReferenceFixer(false));
    programClassPool.classesAccept(new MemberReferenceFixer());

    // Make package visible elements public or protected, if obfuscated
    // classes are being repackaged aggressively.
    if (configuration.repackageClasses != null && configuration.allowAccessModification) {
      programClassPool.classesAccept(new AllConstantVisitor(new AccessFixer()));
    }

    // Rename the source file attributes, if requested.
    if (configuration.newSourceFileAttribute != null) {
      programClassPool.classesAccept(new SourceFileRenamer(configuration.newSourceFileAttribute));
    }

    // Mark NameAndType constant pool entries that have to be kept
    // and remove the other ones.
    programClassPool.classesAccept(new NameAndTypeUsageMarker());
    programClassPool.classesAccept(new NameAndTypeShrinker());

    // Mark Utf8 constant pool entries that have to be kept
    // and remove the other ones.
    programClassPool.classesAccept(new Utf8UsageMarker());
    programClassPool.classesAccept(new Utf8Shrinker());
  }
Example #8
0
 public void testToClass() throws Exception {
   ClassPool cp = ClassPool.getDefault();
   CtClass cc = cp.makeClass("test2.ToClassTest");
   Class c = cc.toClass();
   assertEquals(getClass().getClassLoader(), c.getClassLoader());
 }
Example #9
0
  public void testURL() throws Exception {
    String url;

    ClassPool cp = new ClassPool(null);
    cp.appendSystemPath();

    url = cp.find("java.lang.Object").toString();
    System.out.println(url);
    assertTrue(url.startsWith("jar:file:"));
    assertTrue(url.endsWith(".jar!/java/lang/Object.class"));

    assertNull(cp.find("class.not.Exist"));

    cp = new ClassPool(null);
    cp.insertClassPath(".");

    url = cp.find("test2.Inner").toString();
    System.out.println(url);
    assertTrue(url.startsWith("file:/"));
    assertTrue(url.endsWith("/test2/Inner.class"));

    assertNull(cp.find("test2.TestURL"));

    cp = new ClassPool(null);
    cp.insertClassPath(JAR_PATH + "javassist.jar");

    url = cp.find("javassist.CtClass").toString();
    System.out.println(url);
    assertTrue(url.startsWith("jar:file:"));
    assertTrue(url.endsWith("javassist.jar!/javassist/CtClass.class"));

    assertNull(cp.find("javassist.TestURL"));

    cp = new ClassPool(null);
    cp.insertClassPath(new LoaderClassPath(cloader));

    url = cp.find("javassist.CtMethod").toString();
    System.out.println(url);
    // assertTrue(url.startsWith("jar:file:"));
    // assertTrue(url.endsWith("javassist.jar!/javassist/CtMethod.class"));

    assertNull(cp.find("javassist.TestURL"));

    cp = new ClassPool(null);
    cp.insertClassPath(new ByteArrayClassPath("test2.ByteArray", null));

    url = cp.find("test2.ByteArray").toString();
    System.out.println(url);
    assertTrue(url.equals("file:/ByteArrayClassPath/test2/ByteArray.class"));

    assertNull(cp.find("test2.TestURL"));
  }
 private void createClass(String classname) throws CannotCompileException, IOException {
   ClassPool pool = ClassPool.getDefault();
   CtClass foobarClass = pool.makeClass(classname);
   foobarClass.writeFile(newDir.getAbsolutePath());
 }