Java tutorial
package the.bytecode.club.bytecodeviewer.decompilers; import org.apache.commons.io.FileUtils; import org.benf.cfr.reader.bytecode.analysis.types.JavaTypeInstance; import org.benf.cfr.reader.entities.ClassFile; import org.benf.cfr.reader.entities.Method; import org.benf.cfr.reader.relationship.MemberNameResolver; import org.benf.cfr.reader.state.ClassFileSourceImpl; import org.benf.cfr.reader.state.DCCommonState; import org.benf.cfr.reader.state.TypeUsageCollector; import org.benf.cfr.reader.util.CannotLoadClassException; import org.benf.cfr.reader.util.Functional; import org.benf.cfr.reader.util.ListFactory; import org.benf.cfr.reader.util.Predicate; import org.benf.cfr.reader.util.bytestream.BaseByteData; import org.benf.cfr.reader.util.getopt.GetOptParser; import org.benf.cfr.reader.util.getopt.Options; import org.benf.cfr.reader.util.getopt.OptionsImpl; import org.benf.cfr.reader.util.output.Dumper; import org.benf.cfr.reader.util.output.FileDumper; import org.benf.cfr.reader.util.output.IllegalIdentifierDump; import org.benf.cfr.reader.util.output.NopSummaryDumper; import org.benf.cfr.reader.util.output.SummaryDumper; import org.benf.cfr.reader.util.output.ToStringDumper; import org.objectweb.asm.tree.ClassNode; import org.zeroturnaround.zip.ZipUtil; import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.DecompilerSettings; import the.bytecode.club.bytecodeviewer.JarUtils; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; /*************************************************************************** * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite * * Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ /** * CFR Java Wrapper * * @author Konloch */ public class CFRDecompiler extends Decompiler { public CFRDecompiler() { for (Settings setting : Settings.values()) { settings.registerSetting(setting); } } @Override public DecompilerSettings getSettings() { return settings; } @Override public String getName() { return "CFR"; } @Override public String decompileClassNode(ClassNode cn, byte[] b) { try { Options options = new GetOptParser().parse(generateMainMethod(), OptionsImpl.getFactory()); ClassFileSourceImpl classFileSource = new ClassFileSourceImpl(options); DCCommonState dcCommonState = new DCCommonState(options, classFileSource); return doClass(dcCommonState, b); } catch (Exception e) { return parseException(e); } } @Override public void decompileToZip(String zipName) { try { Path outputDir = Files.createTempDirectory("cfr_output"); Path tempJar = Files.createTempFile("cfr_input", ".jar"); File output = new File(zipName); try { JarUtils.saveAsJar(BytecodeViewer.getLoadedBytes(), tempJar.toAbsolutePath().toString()); Options options = new GetOptParser().parse(generateMainMethod(), OptionsImpl.getFactory()); ClassFileSourceImpl classFileSource = new ClassFileSourceImpl(options); DCCommonState dcCommonState = new DCCommonState(options, classFileSource); doJar(dcCommonState, tempJar.toAbsolutePath(), outputDir.toAbsolutePath()); ZipUtil.pack(outputDir.toFile(), output); } catch (Exception e) { handleException(e); } finally { try { FileUtils.deleteDirectory(outputDir.toFile()); } catch (IOException e) { handleException(e); } try { Files.delete(tempJar); } catch (IOException e) { handleException(e); } } } catch (Exception e) { handleException(e); } } public String[] generateMainMethod() { String[] result = new String[getSettings().size() * 2 + 1]; result[0] = "bytecodeviewer"; int index = 1; for (Settings setting : Settings.values()) { result[index++] = "--" + setting.getParam(); result[index++] = String.valueOf(getSettings().isSelected(setting)); } return result; } public static String doClass(DCCommonState dcCommonState, byte[] content1) throws Exception { Options options = dcCommonState.getOptions(); Dumper d = new ToStringDumper(); BaseByteData data = new BaseByteData(content1); ClassFile var24 = new ClassFile(data, "", dcCommonState); dcCommonState.configureWith(var24); try { var24 = dcCommonState.getClassFile(var24.getClassType()); } catch (CannotLoadClassException var18) { } if (options.getOption(OptionsImpl.DECOMPILE_INNER_CLASSES)) { var24.loadInnerClasses(dcCommonState); } if (options.getOption(OptionsImpl.RENAME_MEMBERS)) { MemberNameResolver.resolveNames(dcCommonState, ListFactory.newList(dcCommonState.getClassCache().getLoadedTypes())); } var24.analyseTop(dcCommonState); TypeUsageCollector var25 = new TypeUsageCollector(var24); var24.collectTypeUsages(var25); String var26 = options.getOption(OptionsImpl.METHODNAME); if (var26 == null) { var24.dump(d); } else { try { for (Method method : var24.getMethodByName(var26)) { method.dump(d, true); } } catch (NoSuchMethodException var19) { throw new IllegalArgumentException("No such method \'" + var26 + "\'."); } } d.print(""); return d.toString(); } public static void doJar(DCCommonState dcCommonState, Path input, Path output) throws Exception { SummaryDumper summaryDumper = new NopSummaryDumper(); Dumper d = new ToStringDumper(); Options options = dcCommonState.getOptions(); IllegalIdentifierDump illegalIdentifierDump = IllegalIdentifierDump.Factory.get(options); final Predicate e = org.benf.cfr.reader.util.MiscUtils .mkRegexFilter(options.getOption(OptionsImpl.JAR_FILTER), true); List<JavaTypeInstance> err1 = dcCommonState.explicitlyLoadJar(input.toAbsolutePath().toString()); err1 = Functional.filter(err1, new Predicate<JavaTypeInstance>() { public boolean test(JavaTypeInstance in) { return e.test(in.getRawName()); } }); if (options.getOption(OptionsImpl.RENAME_MEMBERS)) { MemberNameResolver.resolveNames(dcCommonState, err1); } for (JavaTypeInstance type : err1) { try { ClassFile e1 = dcCommonState.getClassFile(type); if (e1.isInnerClass()) { d = null; } else { if (options.getOption(OptionsImpl.DECOMPILE_INNER_CLASSES).booleanValue()) { e1.loadInnerClasses(dcCommonState); } e1.analyseTop(dcCommonState); TypeUsageCollector collectingDumper = new TypeUsageCollector(e1); e1.collectTypeUsages(collectingDumper); d = new FileDumper(output.toAbsolutePath().toString(), e1.getClassType(), summaryDumper, collectingDumper.getTypeUsageInformation(), options, illegalIdentifierDump); e1.dump(d); d.print("\n"); d.print("\n"); } } catch (Dumper.CannotCreate var25) { throw var25; } catch (RuntimeException var26) { d.print(var26.toString()).print("\n").print("\n").print("\n"); } finally { if (d != null) { d.close(); } } } } public enum Settings implements DecompilerSettings.Setting { DECODE_ENUM_SWITCH("decodeenumswitch", "Decode Enum Switch", true), SUGAR_ENUMS("sugarenums", "SugarEnums", true), DECODE_STRING_SWITCH("decodestringswitch", "Decode String Switch", true), ARRAYITER( "arrayiter", "Arrayiter", true), COLLECTIONITER("collectioniter", "Collectioniter", true), INNER_CLASSES("innerclasses", "Inner Classes", true), REMOVE_BOILER_PLATE( "removeboilerplate", "Remove Boiler Plate", true), REMOVE_INNER_CLASS_SYNTHETICS("removeinnerclasssynthetics", "Remove Inner Class Synthetics", true), DECODE_LAMBDAS("decodelambdas", "Decode Lambdas", true), HIDE_BRIDGE_METHODS("hidebridgemethods", "Hide Bridge Methods", true), LIFT_CONSTRUCTOR_INIT("liftconstructorinit", "Lift Constructor Init", true), REMOVE_DEAD_METHODS( "removedeadmethods", "Remove Dead Methods", true), REMOVE_BAD_GENERICS( "removebadgenerics", "Remove Bad Generics", true), SUGAR_ASSERTS( "sugarasserts", "Sugar Asserts", true), SUGAR_BOXING( "sugarboxing", "Sugar Boxing", true), SHOW_VERSION( "showversion", "Show Version", true), DECODE_FINALLY( "decodefinally", "Decode Finally", true), TIDY_MONITORS( "tidymonitors", "Tidy Monitors", true), LENIENT( "lenient", "Lenient"), DUMP_CLASS_PATH( "dumpclasspath", "Dump Classpath"), COMMENTS( "comments", "Comments", true), FORCE_TOP_SORT( "forcetopsort", "Force Top Sort", true), FORCE_TOP_SORT_AGGRESSIVE( "forcetopsortaggress", "Force Top Sort Aggressive", true), STRINGBUFFER( "stringbuffer", "StringBuffer"), STRINGBUILDER( "stringbuilder", "StringBuilder", true), SILENT( "silent", "Silent", true), RECOVER( "recover", "Recover", true), ECLIPSE( "eclipse", "Eclipse", true), OVERRIDE( "override", "Override", true), SHOW_INFERRABLE( "showinferrable", "Show Inferrable", true), FORCE_AGGRESSIVE_EXCEPTION_AGG( "aexagg", "Force Aggressive Exception Aggregation", true), FORCE_COND_PROPAGATE( "forcecondpropagate", "Force Conditional Propogation", true), HIDE_UTF( "hideutf", "Hide UTF", true), HIDE_LONG_STRINGS( "hidelongstrings", "Hide Long Strings"), COMMENT_MONITORS( "commentmonitors", "Comment Monitors"), ALLOW_CORRECTING( "allowcorrecting", "Allow Correcting", true), LABELLED_BLOCKS( "labelledblocks", "Labelled Blocks", true), J14_CLASS_OBJ( "j14classobj", "Java 1.4 Class Objects"), HIDE_LANG_IMPORTS( "hidelangimports", "Hide Lang Imports", true), RECOVER_TYPE_CLASH( "recovertypeclash", "Recover Type Clash", true), RECOVER_TYPE_HINTS( "recovertypehints", "Recover Type Hints", true), FORCE_RETURNING_IFS( "forcereturningifs", "Force Returning Ifs", true), FOR_LOOP_AGG_CAPTURE( "forloopaggcapture", "For Loop Aggressive Capture", true); private String name; private String param; private boolean on; Settings(String param, String name) { this(param, name, false); } Settings(String param, String name, boolean on) { this.name = name; this.param = param; this.on = on; } public String getText() { return name; } public boolean isDefaultOn() { return on; } public String getParam() { return param; } } }