如何在 FernFlower 中使用自定义重命名器?

ber*_*kiv 3 java decompiling

我目前有一个 FernFlower 的工作设置,就像这样;

我有fernflower.jar一个fern.bat文件,其内容是:

title FernFlower
java -jar fernflower.jar -dgs=1 -ren=1 C:\Users\bernhardkiv\Desktop\test\test-obf.jar C:\Users\bernhardkiv\Desktop\test\src
Run Code Online (Sandbox Code Playgroud)

并且该参数-ren 1使得名称少于 3 个字符(或类似名称)的任何方法和字段都重命名为func_blahor field_blah(相应地,方法获取func_名称,字段获取field_名称。

在 fernflower 的自述文件中有这一节:

 5. Renaming identifiers

Some obfuscators give classes and their member elements short, meaningless and above all 
ambiguous names. Recompiling of such code leads to a great number of conflicts. Therefore it is
advisable to let the decompiler rename elements in its turn, ensuring uniqueness of each identifier.

Option 'ren' (i.e. -ren=1) activates renaming functionality. Default renaming strategy goes as follows:
 - rename an element if its name is a reserved word or is shorter than 3 characters
 - new names are built according to a simple pattern: (class|method|field)_<consecutive unique number>  
 You can overwrite this rules by providing your own implementation of the 4 key methods invoked by the decompiler while renaming. Simply pass a class that implements de.fernflower.main.extern.IIdentifierRenamer in the option 'urc' (e.g. -urc=com.mypackage.MyRenamer) to Fernflower.
 The class must be available on the application classpath.
Run Code Online (Sandbox Code Playgroud)

通过它,我已经通读并了解它是如何工作的,但是我在添加自己的重命名函数实现时遇到了麻烦。

我创建了一个类,实现了IIdentifierRenamer,内容如下;

public class MyRenamer implements IIdentifierRenamer {

@Override
public String getNextClassname(String arg0, String arg1) {
    return "_" + arg0 + "_" + arg1;
}

@Override
public String getNextFieldname(String arg0, String arg1, String arg2) {
    return "_" + arg0 + "_" + arg1 + "_" + arg2;
}

@Override
public String getNextMethodname(String arg0, String arg1, String arg2) {
    return "_" + arg0 + "_" + arg1 + "_" + arg2;
}

@Override
public boolean toBeRenamed(int arg0, String arg1, String arg2, String arg3) {

    System.out.println(arg0 + ", " + arg1 + ", " + arg2 + ", arg3");
    return true;
}

}
Run Code Online (Sandbox Code Playgroud)

首先,在您质疑为什么我返回 nextMethod/Class/Field 方法的所有参数之前,我可以探索并查看这些参数实际上是什么,因为绝对没有 AFAIK 文档。

我将这个类编译成一个名为 的 jar,custre.jar并将它放在与我的fern.bat.

我现在不确定该怎么做才能继续,如果您对 FernFlower 有所了解,并且可以帮助我,请回复。

小智 5

好吧,花了一些时间才弄明白这一点。首先,请注意 fernflower 源中有一个实现默认重命名的类:

src/org/jetbrains/java/decompiler/modules/renamer/ConverterHelper.java
Run Code Online (Sandbox Code Playgroud)

将此文件作为模板复制到您自己的位置,根据您的需要进行调整。我将包更改为:

package jimm3rs.renamer;
Run Code Online (Sandbox Code Playgroud)

并将调试消息输出添加到toBeRenamed方法中:

System.out.println("Custom Renamer: processing [" + classname + "]");
Run Code Online (Sandbox Code Playgroud)

然后编译:

javac -cp ~/fernflower/trunk/fernflower.jar ConverterHelper.java
Run Code Online (Sandbox Code Playgroud)

接下来是指示 fernflower 使用这个自定义重命名器:

java -classpath fernflower.jar:/home/martin/mycode/ org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -dgs=1 -ren=1 -urc=jimm3rs.renamer.ConverterHelper /home/martin/Downloads/idea-IC-141.1532.4/lib/boot.jar .
Run Code Online (Sandbox Code Playgroud)

请注意,在上面的代码目录中/home/martin/mycode/包含一个名为的子目录jimm3rs,该子目录又包含名为renamer存储我们自定义重命名器类的目录。如果您希望有一个额外的步骤,可以将其更改为使用罐子。

调试类加载时的一个有用技巧是为 java.lang.Object 指定-Dsun.misc.URLClassPath.debug=true选项。

最后,我想说使用 -jar 语法来运行 fernflower.jar 没有解决问题:通过指定的自定义类-classpath对 fernflower 不可见。