From 6c4440ac1133bfaa7871d1049d174528a289ef30 Mon Sep 17 00:00:00 2001 From: hg Date: Sun, 17 Aug 2014 10:56:17 -0400 Subject: added support for automatic reconstruction of inner and anonymous classes also added class to restore bridge method flags taken out by the obfuscator --- src/cuchaz/enigma/analysis/BridgeFixer.java | 91 +++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/cuchaz/enigma/analysis/BridgeFixer.java (limited to 'src/cuchaz/enigma/analysis/BridgeFixer.java') diff --git a/src/cuchaz/enigma/analysis/BridgeFixer.java b/src/cuchaz/enigma/analysis/BridgeFixer.java new file mode 100644 index 0000000..db441d2 --- /dev/null +++ b/src/cuchaz/enigma/analysis/BridgeFixer.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma.analysis; + +import java.util.List; + +import javassist.CannotCompileException; +import javassist.CtClass; +import javassist.CtMethod; +import javassist.NotFoundException; +import javassist.bytecode.AccessFlag; +import javassist.expr.ExprEditor; +import javassist.expr.MethodCall; + +import com.beust.jcommander.internal.Lists; + +public class BridgeFixer +{ + public void fixBridges( CtClass c ) + { + // bridge methods are scrubbed and marked as synthetic methods by the obfuscator + // need to figure out which synthetics are bridge methods and restore them + for( CtMethod method : c.getDeclaredMethods() ) + { + // skip non-synthetic methods + if( ( method.getModifiers() & AccessFlag.SYNTHETIC ) == 0 ) + { + continue; + } + + CtMethod bridgedMethod = getBridgedMethod( method ); + if( bridgedMethod != null ) + { + bridgedMethod.setName( method.getName() ); + method.setModifiers( method.getModifiers() | AccessFlag.BRIDGE ); + } + } + } + + private CtMethod getBridgedMethod( CtMethod method ) + { + // bridge methods just call another method, cast it to the return type, and return the result + // let's see if we can detect this scenario + + // get all the called methods + final List methodCalls = Lists.newArrayList(); + try + { + method.instrument( new ExprEditor( ) + { + @Override + public void edit( MethodCall call ) + { + methodCalls.add( call ); + } + } ); + } + catch( CannotCompileException ex ) + { + // this is stupid... we're not even compiling anything + throw new Error( ex ); + } + + // is there just one? + if( methodCalls.size() != 1 ) + { + return null; + } + MethodCall call = methodCalls.get( 0 ); + + try + { + // we have a bridge method! + return call.getMethod(); + } + catch( NotFoundException ex ) + { + // can't find the type? not a bridge method + ex.printStackTrace( System.err ); + return null; + } + } +} -- cgit v1.2.3