Acerca de FernFlower
FernFlower es el primer descompilador analítico que realmente funciona para Java y probablemente para un lenguaje de programación de alto nivel en general. Naturalmente, todavía está en desarrollo. Envíe sus informes de errores y sugerencias de mejora al [rastreador de problemas] (https://youtrack.jetbrains.com/newIssue?project=IDEA&clearDraft=true&c=Subsystem+Java. Decompiler).
Flor de helecho y flor de forja
FernFlower incluye algunos parches de ForgeFlower. Se extiende un sincero agradecimiento a quienes mantienen ForgeFlower por sus valiosas contribuciones y mejoras.
Licencia
FernFlower tiene la licencia Apache versión 2.0.
Ejecutando desde la línea de comando
java -jar fernflower.jar [-<option>=<value>]* [<source>]+ <destination>
* significa 0 o más veces
+ significa 1 o más veces
<fuente>: archivo o directorio con archivos a descompilar. Los directorios se escanean de forma recursiva. Las extensiones de archivo permitidas son class, zip y jar. Las fuentes con el prefijo -e= significan archivos de "biblioteca" que no se descompilarán, pero que se tendrán en cuenta al analizar las relaciones entre clases o métodos. Especialmente el cambio de nombre de identificadores (ver opción 'ren') puede beneficiarse de la información sobre clases externas.
<destino>: directorio de destino
<opción>, <valor>: una opción de línea de comandos con el valor correspondiente (consulte "Opciones de línea de comandos" a continuación).
Ejemplos:
java -jar fernflower.jar -hes=0 -hdc=0 c:Tempbinary -e=c:Javart.jar c:Tempsource
java -jar fernflower.jar -dgs=1 c:Tempbinarylibrary.jar c:TempbinaryBoot.class c:Tempsource
Opciones de línea de comando
Con la excepción de mpm y urc, el valor 1 significa que la opción está activada y 0, desactivada. El valor predeterminado, si lo hay, se proporciona entre paréntesis.
Normalmente, el usuario cambiará las siguientes opciones, si las hay: hes, hdc, dgs, mpm, ren, urc. El resto de opciones se pueden dejar como están: están dirigidas a ingenieros inversos profesionales.
- rbr (1): ocultar métodos de puente
- rsy (0): ocultar miembros de clase sintéticos
- din (1): descompilar clases internas
- dc4 (1): colapsar referencias de clase 1.4
- das (1): descompilar afirmaciones
- hes (1): ocultar superinvocación vacía
- hdc (1): ocultar constructor predeterminado vacío
- dgs (0): descompila firmas genéricas
- ner (1): asume que el retorno no arroja excepciones
- guarida (1): descompilar enumeraciones
- rgn (1): elimina la invocación getClass(), cuando es parte de una nueva declaración calificada
- iluminado (0): genera literales numéricos "tal cual"
- asc (0): codifica caracteres no ASCII en cadenas y caracteres literales como escapes Unicode
- bto (1): interpreta int 1 como booleano verdadero (solución alternativa a un error del compilador)
- nns (0): permite el atributo sintético no establecido (solución alternativa a un error del compilador)
- uto (1): considere los tipos sin nombre como java.lang.Object (solución alternativa a un defecto de la arquitectura del compilador)
- udv (1): reconstruye nombres de variables a partir de información de depuración, si está presente
- ump (1): reconstruye los nombres de los parámetros a partir de los atributos correspondientes, si están presentes
- rer (1): eliminar rangos de excepción vacíos
- ied (1): estructuras finalmente desalineadas
- mpm (0): tiempo máximo de procesamiento permitido por método descompilado, en segundos. 0 significa que no hay límite superior
- ren (0): cambia el nombre de clases y elementos de clase ambiguos (o ofuscados)
- urc (-): nombre completo de una clase proporcionada por el usuario que implementa la interfaz IIdentifierRenamer. Se utiliza para determinar qué identificadores de clase deben cambiarse de nombre y proporciona nuevos nombres de identificadores (consulte "Cambiar el nombre de identificadores")
- posada (1): verifique la anotación @NotNull específica de IntelliJ IDEA y elimine el código insertado si lo encuentra
- lac (0): descompila expresiones lambda en clases anónimas
- nls (0): define el carácter de nueva línea que se utilizará para la salida. 0 - 'rn' (Windows), 1 - 'n' (Unix), el valor predeterminado depende del sistema operativo
- ind: cadena de sangría (el valor predeterminado es 3 espacios)
- crp (0): utilice patrones de registro cuando sea posible
- cps (0): use el interruptor con patrones donde sea posible
- log (INFO): un nivel de registro, los valores posibles son TRACE, INFO, WARN, ERROR
- IEC (0): incluye la ruta de clase completa en contexto al descompilar
- isl (1): expresiones lambda simples en línea
- ucrc (1): oculta constructores y captadores de registros innecesarios
- cci (1): compruebe si el recurso en try-with-resources realmente implementa la interfaz
AutoCloseable
- jvn (0): sobrescribe cualquier nombre de variable local con nombres de estilo JAD
- jpr (0): incluye nombres de parámetros en la denominación JAD
Cambiar el nombre de los identificadores
Algunos ofuscadores dan a las clases y a sus elementos miembros nombres cortos, sin sentido y sobre todo ambiguos. La recompilación de dicho código genera una gran cantidad de conflictos. Por lo tanto, es aconsejable dejar que el descompilador cambie el nombre de los elementos a su vez, asegurando la unicidad de cada identificador.
La opción 'ren' (es decir, -ren=1) activa la función de cambio de nombre. La estrategia de cambio de nombre predeterminada es la siguiente:
- cambiar el nombre de un elemento si su nombre es una palabra reservada o tiene menos de 3 caracteres
- Los nuevos nombres se construyen según un patrón simple: (clase|método|campo)_<número único consecutivo>
Puede sobrescribir estas reglas proporcionando su propia implementación de los 4 métodos clave invocados por el descompilador al cambiar el nombre. Simplemente pase una clase que implemente org.jetbrains.java.decompiler.main.extern.IIdentifierRenamer en la opción 'urc' (por ejemplo, -urc=com.example.MyRenamer) a FernFlower. La clase debe estar disponible en el classpath de la aplicación.
El significado de cada método debe quedar claro al nombrar: toBeRenamed determina si se cambiará el nombre del elemento, mientras que los otros tres proporcionan nuevos nombres para clases, métodos y campos respectivamente.