2011-09-22 10:55:30 +08:00
/ *
2014-03-12 05:15:43 +08:00
Copyright ( C ) 2011 - 2014 de4dot @gmail . com
2011-09-22 10:55:30 +08:00
This file is part of de4dot .
de4dot 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 .
de4dot 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 de4dot . If not , see < http : //www.gnu.org/licenses/>.
* /
using System ;
using System.Collections.Generic ;
2012-12-20 09:06:09 +08:00
using dnlib.DotNet ;
using dnlib.DotNet.Emit ;
2011-09-22 10:55:30 +08:00
using de4dot.blocks ;
2011-12-09 16:02:06 +08:00
namespace de4dot.code.deobfuscators {
2012-05-29 17:13:39 +08:00
abstract class ProxyCallFixerBase {
2012-11-01 21:39:39 +08:00
protected ModuleDefMD module ;
protected List < MethodDef > delegateCreatorMethods = new List < MethodDef > ( ) ;
protected Dictionary < TypeDef , bool > delegateTypesDict = new Dictionary < TypeDef , bool > ( ) ;
2012-05-29 17:13:39 +08:00
protected int errors = 0 ;
2011-11-28 18:45:48 +08:00
public int Errors {
get { return errors ; }
}
2011-09-22 10:55:30 +08:00
2011-12-28 20:33:10 +08:00
protected class DelegateInfo {
2012-11-01 21:39:39 +08:00
public IMethod methodRef ; // Method we should call
public FieldDef field ; // Field holding the Delegate instance
2011-10-23 19:43:32 +08:00
public OpCode callOpcode ;
2012-11-01 21:39:39 +08:00
public DelegateInfo ( FieldDef field , IMethod methodRef , OpCode callOpcode ) {
2011-09-22 10:55:30 +08:00
this . field = field ;
this . methodRef = methodRef ;
2011-10-23 19:43:32 +08:00
this . callOpcode = callOpcode ;
2011-09-22 10:55:30 +08:00
}
}
public int RemovedDelegateCreatorCalls { get ; set ; }
2011-10-23 19:43:32 +08:00
2012-11-01 21:39:39 +08:00
public IEnumerable < TypeDef > DelegateTypes {
2011-09-22 10:55:30 +08:00
get { return delegateTypesDict . Keys ; }
}
2011-10-23 19:43:32 +08:00
2012-11-01 21:39:39 +08:00
public IEnumerable < TypeDef > DelegateCreatorTypes {
2011-10-23 19:43:32 +08:00
get {
foreach ( var method in delegateCreatorMethods )
yield return method . DeclaringType ;
}
2011-09-22 10:55:30 +08:00
}
2012-11-01 21:39:39 +08:00
public virtual IEnumerable < Tuple < MethodDef , string > > OtherMethods {
get { return new List < Tuple < MethodDef , string > > ( ) ; }
2012-07-27 14:02:27 +08:00
}
2011-09-22 10:55:30 +08:00
public bool Detected {
2011-10-23 19:43:32 +08:00
get { return delegateCreatorMethods . Count ! = 0 ; }
2011-09-22 10:55:30 +08:00
}
2012-11-01 21:39:39 +08:00
protected ProxyCallFixerBase ( ModuleDefMD module ) {
2011-09-22 10:55:30 +08:00
this . module = module ;
}
2012-11-01 21:39:39 +08:00
protected ProxyCallFixerBase ( ModuleDefMD module , ProxyCallFixerBase oldOne ) {
2012-02-07 11:45:04 +08:00
this . module = module ;
foreach ( var method in oldOne . delegateCreatorMethods )
2013-01-19 20:03:57 +08:00
delegateCreatorMethods . Add ( Lookup ( method , "Could not find delegate creator method" ) ) ;
2012-02-07 11:45:04 +08:00
foreach ( var kv in oldOne . delegateTypesDict )
2013-01-19 20:03:57 +08:00
delegateTypesDict [ Lookup ( kv . Key , "Could not find delegate type" ) ] = kv . Value ;
2012-02-07 11:45:04 +08:00
}
2013-01-19 20:03:57 +08:00
protected DelegateInfo Copy ( DelegateInfo di ) {
var method = Lookup ( di . methodRef , "Could not find method ref" ) ;
var field = Lookup ( di . field , "Could not find delegate field" ) ;
2012-02-07 11:45:04 +08:00
return new DelegateInfo ( field , method , di . callOpcode ) ;
}
2013-01-19 20:03:57 +08:00
protected T Lookup < T > ( T def , string errorMessage ) where T : class , ICodedToken {
return DeobUtils . Lookup ( module , def , errorMessage ) ;
2012-02-07 11:45:04 +08:00
}
2013-01-19 20:03:57 +08:00
protected void SetDelegateCreatorMethod ( MethodDef delegateCreatorMethod ) {
2011-10-23 19:43:32 +08:00
if ( delegateCreatorMethod = = null )
return ;
delegateCreatorMethods . Add ( delegateCreatorMethod ) ;
}
2013-01-19 20:03:57 +08:00
protected bool IsDelegateCreatorMethod ( MethodDef method ) {
2011-10-23 19:43:32 +08:00
foreach ( var m in delegateCreatorMethods ) {
if ( m = = method )
return true ;
}
return false ;
2011-09-22 10:55:30 +08:00
}
2013-01-19 20:03:57 +08:00
protected virtual IEnumerable < TypeDef > GetDelegateTypes ( ) {
2012-02-07 09:02:49 +08:00
foreach ( var type in module . Types ) {
if ( type . BaseType = = null | | type . BaseType . FullName ! = "System.MulticastDelegate" )
continue ;
yield return type ;
}
}
2012-05-29 17:13:39 +08:00
protected class BlockInstr {
public Block Block { get ; set ; }
public int Index { get ; set ; }
}
protected class RemoveInfo {
public int Index { get ; set ; }
public DelegateInfo DelegateInfo { get ; set ; }
public bool IsCall {
get { return DelegateInfo ! = null ; }
}
}
protected virtual bool ProxyCallIsObfuscated {
get { return false ; }
}
2013-01-19 20:03:57 +08:00
public void Deobfuscate ( Blocks blocks ) {
2012-05-29 17:13:39 +08:00
if ( blocks . Method . DeclaringType ! = null & & delegateTypesDict . ContainsKey ( blocks . Method . DeclaringType ) )
return ;
2013-01-19 20:03:57 +08:00
var allBlocks = blocks . MethodBlocks . GetAllBlocks ( ) ;
2012-05-29 17:13:39 +08:00
int loops = ProxyCallIsObfuscated ? 50 : 1 ;
for ( int i = 0 ; i < loops ; i + + ) {
2013-01-19 20:03:57 +08:00
if ( ! Deobfuscate ( blocks , allBlocks ) )
2012-05-29 17:13:39 +08:00
break ;
}
2013-01-19 20:03:57 +08:00
DeobfuscateEnd ( blocks , allBlocks ) ;
2012-05-29 17:13:39 +08:00
}
2013-01-19 20:03:57 +08:00
protected abstract bool Deobfuscate ( Blocks blocks , IList < Block > allBlocks ) ;
2012-05-29 17:13:39 +08:00
2013-01-19 20:03:57 +08:00
protected virtual void DeobfuscateEnd ( Blocks blocks , IList < Block > allBlocks ) {
2012-05-29 17:13:39 +08:00
}
2013-01-19 20:03:57 +08:00
protected static void Add ( Dictionary < Block , List < RemoveInfo > > removeInfos , Block block , int index , DelegateInfo di ) {
2012-05-29 17:13:39 +08:00
List < RemoveInfo > list ;
if ( ! removeInfos . TryGetValue ( block , out list ) )
removeInfos [ block ] = list = new List < RemoveInfo > ( ) ;
list . Add ( new RemoveInfo {
Index = index ,
DelegateInfo = di ,
} ) ;
}
2014-05-10 15:00:43 +08:00
protected bool FixProxyCalls ( MethodDef method , Dictionary < Block , List < RemoveInfo > > removeInfos ) {
var gpContext = GenericParamContext . Create ( method ) ;
2012-05-29 17:13:39 +08:00
foreach ( var block in removeInfos . Keys ) {
var list = removeInfos [ block ] ;
var removeIndexes = new List < int > ( list . Count ) ;
foreach ( var info in list ) {
if ( info . IsCall ) {
var opcode = info . DelegateInfo . callOpcode ;
2014-05-10 15:00:43 +08:00
var newInstr = Instruction . Create ( opcode , ReResolve ( info . DelegateInfo . methodRef , gpContext ) ) ;
2013-01-19 20:03:57 +08:00
block . Replace ( info . Index , 1 , newInstr ) ;
2012-05-29 17:13:39 +08:00
}
else
removeIndexes . Add ( info . Index ) ;
}
2012-11-18 10:02:12 +08:00
if ( removeIndexes . Count > 0 )
2013-01-19 20:03:57 +08:00
block . Remove ( removeIndexes ) ;
2012-05-29 17:13:39 +08:00
}
return removeInfos . Count > 0 ;
}
2014-05-10 15:00:43 +08:00
IMethod ReResolve ( IMethod method , GenericParamContext gpContext ) {
if ( method . IsMethodSpec | | method . IsMemberRef )
method = module . ResolveToken ( method . MDToken . Raw , gpContext ) as IMethod ? ? method ;
return method ;
}
2012-05-29 17:13:39 +08:00
}
// Fixes proxy calls that call the delegate inline in the code, eg.:
// ldsfld delegate_instance
// ...push args...
// call Invoke
abstract class ProxyCallFixer1 : ProxyCallFixerBase {
2012-11-22 16:14:51 +08:00
FieldDefAndDeclaringTypeDict < DelegateInfo > fieldToDelegateInfo = new FieldDefAndDeclaringTypeDict < DelegateInfo > ( ) ;
2012-05-29 17:13:39 +08:00
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer1 ( ModuleDefMD module )
2012-05-29 17:13:39 +08:00
: base ( module ) {
}
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer1 ( ModuleDefMD module , ProxyCallFixer1 oldOne )
2012-05-29 17:13:39 +08:00
: base ( module , oldOne ) {
2013-01-19 20:03:57 +08:00
foreach ( var key in oldOne . fieldToDelegateInfo . GetKeys ( ) )
fieldToDelegateInfo . Add ( Lookup ( key , "Could not find field" ) , Copy ( oldOne . fieldToDelegateInfo . Find ( key ) ) ) ;
2012-05-29 17:13:39 +08:00
}
2013-01-19 20:03:57 +08:00
protected void AddDelegateInfo ( DelegateInfo di ) {
fieldToDelegateInfo . Add ( di . field , di ) ;
2012-05-29 17:13:39 +08:00
}
2013-01-19 20:03:57 +08:00
protected DelegateInfo GetDelegateInfo ( IField field ) {
2012-05-29 17:13:39 +08:00
if ( field = = null )
return null ;
2013-01-19 20:03:57 +08:00
return fieldToDelegateInfo . Find ( field ) ;
2012-05-29 17:13:39 +08:00
}
2013-01-19 20:03:57 +08:00
public void Find ( ) {
2011-10-23 19:43:32 +08:00
if ( delegateCreatorMethods . Count = = 0 )
2011-09-22 10:55:30 +08:00
return ;
2012-11-11 12:31:11 +08:00
Logger . v ( "Finding all proxy delegates" ) ;
2013-01-19 20:03:57 +08:00
foreach ( var tmp in GetDelegateTypes ( ) ) {
2012-07-07 06:58:18 +08:00
var type = tmp ;
2012-11-17 06:50:52 +08:00
var cctor = type . FindStaticConstructor ( ) ;
2012-11-06 22:58:55 +08:00
if ( cctor = = null | | ! cctor . HasBody )
2011-09-22 10:55:30 +08:00
continue ;
if ( ! type . HasFields )
continue ;
2013-01-19 20:03:57 +08:00
object context = CheckCctor ( ref type , cctor ) ;
2011-10-23 19:43:32 +08:00
if ( context = = null )
2011-09-22 10:55:30 +08:00
continue ;
2013-01-19 20:03:57 +08:00
Logger . v ( "Found proxy delegate: {0} ({1:X8})" , Utils . RemoveNewlines ( type ) , type . MDToken . ToUInt32 ( ) ) ;
2011-09-22 10:55:30 +08:00
RemovedDelegateCreatorCalls + + ;
2011-10-23 19:43:32 +08:00
2013-01-19 20:03:57 +08:00
Logger . Instance . Indent ( ) ;
2011-09-22 10:55:30 +08:00
foreach ( var field in type . Fields ) {
2012-01-04 02:22:45 +08:00
if ( ! field . IsStatic )
2011-09-22 10:55:30 +08:00
continue ;
2012-11-01 21:39:39 +08:00
IMethod calledMethod ;
2011-10-23 19:43:32 +08:00
OpCode callOpcode ;
2013-01-19 20:03:57 +08:00
GetCallInfo ( context , field , out calledMethod , out callOpcode ) ;
2011-10-23 19:43:32 +08:00
if ( calledMethod = = null )
2012-01-04 02:22:45 +08:00
continue ;
2013-01-19 20:03:57 +08:00
AddDelegateInfo ( new DelegateInfo ( field , calledMethod , callOpcode ) ) ;
2012-11-11 12:31:11 +08:00
Logger . v ( "Field: {0}, Opcode: {1}, Method: {2} ({3:X8})" ,
2013-01-19 20:03:57 +08:00
Utils . RemoveNewlines ( field . Name ) ,
2012-01-04 02:52:40 +08:00
callOpcode ,
2013-01-19 20:03:57 +08:00
Utils . RemoveNewlines ( calledMethod ) ,
2012-11-01 21:39:39 +08:00
calledMethod . MDToken . Raw ) ;
2011-09-22 10:55:30 +08:00
}
2013-01-19 20:03:57 +08:00
Logger . Instance . DeIndent ( ) ;
2011-09-22 10:55:30 +08:00
delegateTypesDict [ type ] = true ;
}
}
2013-01-19 20:03:57 +08:00
protected abstract object CheckCctor ( ref TypeDef type , MethodDef cctor ) ;
protected abstract void GetCallInfo ( object context , FieldDef field , out IMethod calledMethod , out OpCode callOpcode ) ;
2011-10-23 19:43:32 +08:00
2013-01-19 20:03:57 +08:00
protected override bool Deobfuscate ( Blocks blocks , IList < Block > allBlocks ) {
2011-09-22 10:55:30 +08:00
var removeInfos = new Dictionary < Block , List < RemoveInfo > > ( ) ;
foreach ( var block in allBlocks ) {
var instrs = block . Instructions ;
for ( int i = 0 ; i < instrs . Count ; i + + ) {
2011-10-23 19:43:32 +08:00
var instr = instrs [ i ] ;
2012-05-29 17:13:39 +08:00
if ( instr . OpCode ! = OpCodes . Ldsfld )
continue ;
2013-01-19 20:03:57 +08:00
var di = GetDelegateInfo ( instr . Operand as IField ) ;
2012-05-29 17:13:39 +08:00
if ( di = = null )
continue ;
2013-01-19 20:03:57 +08:00
var callInfo = FindProxyCall ( di , block , i ) ;
2012-05-29 17:13:39 +08:00
if ( callInfo ! = null ) {
2013-01-19 20:03:57 +08:00
Add ( removeInfos , block , i , null ) ;
Add ( removeInfos , callInfo . Block , callInfo . Index , di ) ;
2011-09-22 10:55:30 +08:00
}
2012-05-29 17:13:39 +08:00
else {
errors + + ;
2012-11-11 12:31:11 +08:00
Logger . w ( "Could not fix proxy call. Method: {0} ({1:X8}), Proxy type: {2} ({3:X8})" ,
2013-01-19 20:03:57 +08:00
Utils . RemoveNewlines ( blocks . Method ) ,
2012-11-01 21:39:39 +08:00
blocks . Method . MDToken . ToInt32 ( ) ,
2013-01-19 20:03:57 +08:00
Utils . RemoveNewlines ( di . field . DeclaringType ) ,
2012-11-01 21:39:39 +08:00
di . field . DeclaringType . MDToken . ToInt32 ( ) ) ;
2011-09-22 10:55:30 +08:00
}
}
}
2014-05-10 15:00:43 +08:00
return FixProxyCalls ( blocks . Method , removeInfos ) ;
2011-09-22 10:55:30 +08:00
}
2013-01-19 20:03:57 +08:00
protected virtual BlockInstr FindProxyCall ( DelegateInfo di , Block block , int index ) {
return FindProxyCall ( di , block , index , new Dictionary < Block , bool > ( ) , 1 ) ;
2012-05-30 01:13:43 +08:00
}
2013-01-19 20:03:57 +08:00
BlockInstr FindProxyCall ( DelegateInfo di , Block block , int index , Dictionary < Block , bool > visited , int stack ) {
2011-09-22 10:55:30 +08:00
if ( visited . ContainsKey ( block ) )
return null ;
if ( index < = 0 )
visited [ block ] = true ;
var instrs = block . Instructions ;
for ( int i = index + 1 ; i < instrs . Count ; i + + ) {
if ( stack < = 0 )
return null ;
var instr = instrs [ i ] ;
2012-11-01 21:39:39 +08:00
instr . Instruction . UpdateStack ( ref stack , false ) ;
2011-09-22 10:55:30 +08:00
if ( stack < 0 )
return null ;
2012-02-07 09:02:49 +08:00
if ( instr . OpCode ! = OpCodes . Call & & instr . OpCode ! = OpCodes . Callvirt ) {
if ( stack < = 0 )
return null ;
2011-09-22 10:55:30 +08:00
continue ;
2012-02-07 09:02:49 +08:00
}
2012-11-01 21:39:39 +08:00
var calledMethod = instr . Operand as IMethod ;
2012-02-07 09:02:49 +08:00
if ( calledMethod = = null )
return null ;
2013-01-19 20:03:57 +08:00
if ( stack ! = ( DotNetUtils . HasReturnValue ( calledMethod ) ? 1 : 0 ) )
2011-09-22 10:55:30 +08:00
continue ;
2012-02-07 09:02:49 +08:00
if ( calledMethod . Name ! = "Invoke" )
return null ;
2011-09-22 10:55:30 +08:00
return new BlockInstr {
Block = block ,
Index = i ,
} ;
}
if ( stack < = 0 )
return null ;
2013-01-19 20:03:57 +08:00
foreach ( var target in block . GetTargets ( ) ) {
var info = FindProxyCall ( di , target , - 1 , visited , stack ) ;
2011-09-22 10:55:30 +08:00
if ( info ! = null )
return info ;
}
return null ;
}
2013-01-19 20:03:57 +08:00
protected override void DeobfuscateEnd ( Blocks blocks , IList < Block > allBlocks ) {
FixBrokenCalls ( blocks . Method , allBlocks ) ;
2012-05-29 17:13:39 +08:00
}
2011-09-22 10:55:30 +08:00
// The obfuscator could be buggy and call a proxy delegate without pushing the
// instance field. SA has done it, so let's fix it.
2013-01-19 20:03:57 +08:00
void FixBrokenCalls ( MethodDef obfuscatedMethod , IList < Block > allBlocks ) {
2011-09-22 10:55:30 +08:00
foreach ( var block in allBlocks ) {
var instrs = block . Instructions ;
for ( int i = 0 ; i < instrs . Count ; i + + ) {
var call = instrs [ i ] ;
if ( call . OpCode ! = OpCodes . Call & & call . OpCode ! = OpCodes . Callvirt )
continue ;
2012-11-01 21:39:39 +08:00
var methodRef = call . Operand as IMethod ;
2012-07-22 05:13:34 +08:00
if ( methodRef = = null | | methodRef . Name ! = "Invoke" )
2011-09-22 10:55:30 +08:00
continue ;
2013-01-19 20:03:57 +08:00
MethodDef method = DotNetUtils . GetMethod2 ( module , methodRef ) ;
2012-11-01 21:39:39 +08:00
if ( method = = null | | method . DeclaringType = = null )
2011-09-22 10:55:30 +08:00
continue ;
2012-11-01 21:39:39 +08:00
if ( ! delegateTypesDict . ContainsKey ( method . DeclaringType ) )
2011-09-22 10:55:30 +08:00
continue ;
// Oooops!!! The obfuscator is buggy. Well, let's hope it is, or it's my code. ;)
2012-11-11 12:31:11 +08:00
Logger . w ( "Holy obfuscator bugs, Batman! Found a proxy delegate call with no instance push in {0:X8}. Replacing it with a throw..." , obfuscatedMethod . MDToken . ToInt32 ( ) ) ;
2013-01-19 20:03:57 +08:00
block . Insert ( i , OpCodes . Ldnull . ToInstruction ( ) ) ;
block . Replace ( i + 1 , 1 , OpCodes . Throw . ToInstruction ( ) ) ;
2011-09-22 10:55:30 +08:00
i + + ;
}
}
}
}
2012-05-29 17:13:39 +08:00
// Fixes proxy calls that call a static method which then calls
// Invoke() on a delegate instance, eg.:
// ...push args...
// call static method
abstract class ProxyCallFixer2 : ProxyCallFixerBase {
2012-11-22 16:14:51 +08:00
MethodDefAndDeclaringTypeDict < DelegateInfo > proxyMethodToDelegateInfo = new MethodDefAndDeclaringTypeDict < DelegateInfo > ( ) ;
2012-05-29 17:13:39 +08:00
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer2 ( ModuleDefMD module )
2012-05-29 17:13:39 +08:00
: base ( module ) {
}
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer2 ( ModuleDefMD module , ProxyCallFixer2 oldOne )
2012-05-29 17:13:39 +08:00
: base ( module , oldOne ) {
2013-01-19 20:03:57 +08:00
foreach ( var oldMethod in oldOne . proxyMethodToDelegateInfo . GetKeys ( ) ) {
var oldDi = oldOne . proxyMethodToDelegateInfo . Find ( oldMethod ) ;
var method = Lookup ( oldMethod , "Could not find proxy method" ) ;
proxyMethodToDelegateInfo . Add ( method , Copy ( oldDi ) ) ;
2012-05-29 17:13:39 +08:00
}
}
2013-01-19 20:03:57 +08:00
public void Find ( ) {
2012-05-29 17:13:39 +08:00
if ( delegateCreatorMethods . Count = = 0 )
return ;
2012-11-11 12:31:11 +08:00
Logger . v ( "Finding all proxy delegates" ) ;
2013-01-19 20:03:57 +08:00
Find2 ( ) ;
2012-07-31 13:13:07 +08:00
}
2013-01-19 20:03:57 +08:00
protected void Find2 ( ) {
foreach ( var type in GetDelegateTypes ( ) ) {
2012-11-17 06:50:52 +08:00
var cctor = type . FindStaticConstructor ( ) ;
2012-11-06 22:58:55 +08:00
if ( cctor = = null | | ! cctor . HasBody )
2012-05-29 17:13:39 +08:00
continue ;
if ( ! type . HasFields )
continue ;
2013-01-19 20:03:57 +08:00
object context = CheckCctor ( type , cctor ) ;
2012-05-29 17:13:39 +08:00
if ( context = = null )
continue ;
2013-01-19 20:03:57 +08:00
Logger . v ( "Found proxy delegate: {0} ({1:X8})" , Utils . RemoveNewlines ( type ) , type . MDToken . ToUInt32 ( ) ) ;
2012-05-29 17:13:39 +08:00
RemovedDelegateCreatorCalls + + ;
2013-01-19 20:03:57 +08:00
var fieldToMethod = GetFieldToMethodDictionary ( type ) ;
2012-05-29 17:13:39 +08:00
2013-01-19 20:03:57 +08:00
Logger . Instance . Indent ( ) ;
2012-05-29 17:13:39 +08:00
foreach ( var field in type . Fields ) {
2012-11-01 21:39:39 +08:00
MethodDef proxyMethod ;
2012-05-29 17:13:39 +08:00
if ( ! fieldToMethod . TryGetValue ( field , out proxyMethod ) )
continue ;
2012-11-01 21:39:39 +08:00
IMethod calledMethod ;
2012-05-29 17:13:39 +08:00
OpCode callOpcode ;
2013-01-19 20:03:57 +08:00
GetCallInfo ( context , field , out calledMethod , out callOpcode ) ;
2012-05-29 17:13:39 +08:00
if ( calledMethod = = null )
continue ;
2013-01-19 20:03:57 +08:00
Add ( proxyMethod , new DelegateInfo ( field , calledMethod , callOpcode ) ) ;
2012-11-11 12:31:11 +08:00
Logger . v ( "Field: {0}, Opcode: {1}, Method: {2} ({3:X8})" ,
2013-01-19 20:03:57 +08:00
Utils . RemoveNewlines ( field . Name ) ,
2012-05-29 17:13:39 +08:00
callOpcode ,
2013-01-19 20:03:57 +08:00
Utils . RemoveNewlines ( calledMethod ) ,
2012-11-01 21:39:39 +08:00
calledMethod . MDToken . ToUInt32 ( ) ) ;
2012-05-29 17:13:39 +08:00
}
2013-01-19 20:03:57 +08:00
Logger . Instance . DeIndent ( ) ;
2012-05-29 17:13:39 +08:00
delegateTypesDict [ type ] = true ;
}
}
2013-01-19 20:03:57 +08:00
protected void Add ( MethodDef method , DelegateInfo di ) {
proxyMethodToDelegateInfo . Add ( method , di ) ;
2012-05-29 17:13:39 +08:00
}
2013-01-19 20:03:57 +08:00
protected abstract object CheckCctor ( TypeDef type , MethodDef cctor ) ;
protected abstract void GetCallInfo ( object context , FieldDef field , out IMethod calledMethod , out OpCode callOpcode ) ;
2012-05-29 17:13:39 +08:00
2013-01-19 20:03:57 +08:00
Dictionary < FieldDef , MethodDef > GetFieldToMethodDictionary ( TypeDef type ) {
2012-11-01 21:39:39 +08:00
var dict = new Dictionary < FieldDef , MethodDef > ( ) ;
2012-07-27 13:57:13 +08:00
foreach ( var method in type . Methods ) {
2012-11-06 22:58:55 +08:00
if ( ! method . IsStatic | | ! method . HasBody | | method . Name = = ".cctor" )
2012-07-27 13:57:13 +08:00
continue ;
2012-11-06 22:58:55 +08:00
var instructions = method . Body . Instructions ;
2012-07-27 13:57:13 +08:00
for ( int i = 0 ; i < instructions . Count ; i + + ) {
var instr = instructions [ i ] ;
if ( instr . OpCode . Code ! = Code . Ldsfld )
continue ;
2012-11-01 21:39:39 +08:00
var field = instr . Operand as FieldDef ;
2012-07-27 13:57:13 +08:00
if ( field = = null )
continue ;
dict [ field ] = method ;
break ;
}
}
return dict ;
}
2013-01-19 20:03:57 +08:00
protected override bool Deobfuscate ( Blocks blocks , IList < Block > allBlocks ) {
2012-05-29 17:13:39 +08:00
var removeInfos = new Dictionary < Block , List < RemoveInfo > > ( ) ;
foreach ( var block in allBlocks ) {
var instrs = block . Instructions ;
for ( int i = 0 ; i < instrs . Count ; i + + ) {
var instr = instrs [ i ] ;
if ( instr . OpCode ! = OpCodes . Call )
continue ;
2012-11-01 21:39:39 +08:00
var method = instr . Operand as IMethod ;
2012-05-29 17:13:39 +08:00
if ( method = = null )
continue ;
2013-01-19 20:03:57 +08:00
var di = proxyMethodToDelegateInfo . Find ( method ) ;
2012-05-29 17:13:39 +08:00
if ( di = = null )
continue ;
2013-01-19 20:03:57 +08:00
Add ( removeInfos , block , i , di ) ;
2012-05-29 17:13:39 +08:00
}
}
2014-05-10 15:00:43 +08:00
return FixProxyCalls ( blocks . Method , removeInfos ) ;
2012-05-29 17:13:39 +08:00
}
}
2012-05-30 01:13:43 +08:00
// Fixes proxy calls that call a static method with the instance of
2012-07-07 06:58:18 +08:00
// a delegate as the last arg, which then calls the Invoke method.
2012-05-30 01:13:43 +08:00
// ...push args...
// ldsfld delegate instance
// call static method
abstract class ProxyCallFixer3 : ProxyCallFixer1 {
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer3 ( ModuleDefMD module )
2012-05-30 01:13:43 +08:00
: base ( module ) {
}
2012-11-01 21:39:39 +08:00
protected ProxyCallFixer3 ( ModuleDefMD module , ProxyCallFixer3 oldOne )
2012-05-30 01:13:43 +08:00
: base ( module , oldOne ) {
}
2013-01-19 20:03:57 +08:00
protected override BlockInstr FindProxyCall ( DelegateInfo di , Block block , int index ) {
2012-05-30 01:13:43 +08:00
index + + ;
if ( index > = block . Instructions . Count )
return null ;
2013-01-19 20:03:57 +08:00
var calledMethod = GetCalledMethod ( block . Instructions [ index ] ) ;
2012-05-30 01:13:43 +08:00
if ( calledMethod = = null )
return null ;
return new BlockInstr {
Block = block ,
Index = index ,
} ;
}
2013-01-19 20:03:57 +08:00
static IMethod GetCalledMethod ( Instr instr ) {
2012-05-30 01:13:43 +08:00
if ( instr . OpCode . Code ! = Code . Call )
return null ;
2012-11-01 21:39:39 +08:00
return instr . Operand as IMethod ;
2012-05-30 01:13:43 +08:00
}
}
2011-09-22 10:55:30 +08:00
}