Port the remaining classes in blocks

This commit is contained in:
de4dot 2012-10-31 18:52:50 +01:00
parent 301a2fab97
commit 8022a445a9
20 changed files with 181 additions and 119 deletions

View File

@ -23,6 +23,10 @@ using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Metadata;
//TODO: Remove these
using DN = dot10.DotNet;
using DNE = dot10.DotNet.Emit;
namespace de4dot.blocks {
public enum FrameworkType {
Unknown,
@ -635,6 +639,11 @@ namespace de4dot.blocks {
return newMethod;
}
// Copies most things but not everything
public static DN.MethodDef clone(DN.MethodDef method) {
return null; //TODO:
}
public static Instruction clone(Instruction instr) {
return new Instruction {
Offset = instr.Offset,
@ -707,6 +716,22 @@ namespace de4dot.blocks {
bodyExceptionHandlers.Add(eh);
}
public static void restoreBody(DN.MethodDef method, IEnumerable<DNE.Instruction> instructions, IEnumerable<DNE.ExceptionHandler> exceptionHandlers) {
if (method == null || method.CilBody == null)
return;
var bodyInstrs = method.CilBody.Instructions;
bodyInstrs.Clear();
foreach (var instr in instructions)
bodyInstrs.Add(instr);
var bodyExceptionHandlers = method.CilBody.ExceptionHandlers;
bodyExceptionHandlers.Clear();
foreach (var eh in exceptionHandlers)
bodyExceptionHandlers.Add(eh);
}
public static void copyBodyFromTo(MethodDefinition fromMethod, MethodDefinition toMethod) {
if (fromMethod == toMethod)
return;
@ -1035,6 +1060,16 @@ namespace de4dot.blocks {
return args;
}
public static List<DN.IType> getArgs(DN.IMethod method) {
var sig = method.MethodSig;
var args = new List<DN.IType>(sig.Params.Count + 1);
if (sig.HasThis && !sig.ExplicitThis)
args.Add(method.DeclaringType);
foreach (var arg in sig.Params)
args.Add(arg);
return args;
}
public static TypeReference getArgType(MethodReference method, Instruction instr) {
return getArgType(getArgs(method), instr);
}
@ -1056,6 +1091,16 @@ namespace de4dot.blocks {
return count;
}
public static int getArgsCount(DN.IMethod method) {
var sig = method.MethodSig;
if (sig == null)
return 0;
int count = sig.Params.Count;
if (sig.HasThis && !sig.ExplicitThis)
count++;
return count;
}
public static Instruction createLdci4(int value) {
if (value == -1) return Instruction.Create(OpCodes.Ldc_I4_M1);
if (value == 0) return Instruction.Create(OpCodes.Ldc_I4_0);
@ -1113,6 +1158,25 @@ namespace de4dot.blocks {
return null;
}
public static DNE.Instruction getInstruction(IList<DNE.Instruction> instructions, ref int index) {
for (int i = 0; i < 10; i++) {
if (index < 0 || index >= instructions.Count)
return null;
var instr = instructions[index++];
if (instr.OpCode.Code == DNE.Code.Nop)
continue;
if (instr.OpCode.OpCodeType == DNE.OpCodeType.Prefix)
continue;
if (instr == null || (instr.OpCode.Code != DNE.Code.Br && instr.OpCode.Code != DNE.Code.Br_S))
return instr;
instr = instr.Operand as DNE.Instruction;
if (instr == null)
return null;
index = instructions.IndexOf(instr);
}
return null;
}
public static PropertyDefinition createPropertyDefinition(string name, TypeReference propType, MethodDefinition getter, MethodDefinition setter) {
return new PropertyDefinition(name, PropertyAttributes.None, propType) {
MetadataToken = nextPropertyToken(),

View File

@ -18,8 +18,6 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace de4dot.blocks {
public class FilterHandlerBlock : ScopeBlock {

View File

@ -19,8 +19,6 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace de4dot.blocks {
// This class makes sure that each block that is entered with a non-empty stack has at

View File

@ -18,8 +18,6 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace de4dot.blocks {
// This is the block inside catch(xxx) { }.

View File

@ -38,26 +38,26 @@
<Compile Include="Block.cs" />
<Compile Include="Blocks.cs" />
<Compile Include="BlocksSorter.cs" />
<None Include="cflow\BlockCflowDeobfuscator.cs" />
<None Include="cflow\BlockDeobfuscator.cs" />
<None Include="cflow\BlocksCflowDeobfuscator.cs" />
<None Include="cflow\BranchEmulator.cs" />
<None Include="cflow\CachedCflowDeobfuscator.cs" />
<None Include="cflow\CflowDeobfuscator.cs" />
<None Include="cflow\CflowUtils.cs" />
<None Include="cflow\ConstantsFolder.cs" />
<None Include="cflow\DeadCodeRemover.cs" />
<None Include="cflow\DeadStoreRemover.cs" />
<None Include="cflow\IBlocksDeobfuscator.cs" />
<None Include="cflow\ICflowDeobfuscator.cs" />
<Compile Include="cflow\BlockCflowDeobfuscator.cs" />
<Compile Include="cflow\BlockDeobfuscator.cs" />
<Compile Include="cflow\BlocksCflowDeobfuscator.cs" />
<Compile Include="cflow\BranchEmulator.cs" />
<Compile Include="cflow\CachedCflowDeobfuscator.cs" />
<Compile Include="cflow\CflowDeobfuscator.cs" />
<Compile Include="cflow\CflowUtils.cs" />
<Compile Include="cflow\ConstantsFolder.cs" />
<Compile Include="cflow\DeadCodeRemover.cs" />
<Compile Include="cflow\DeadStoreRemover.cs" />
<Compile Include="cflow\IBlocksDeobfuscator.cs" />
<Compile Include="cflow\ICflowDeobfuscator.cs" />
<Compile Include="cflow\InstructionEmulator.cs" />
<Compile Include="cflow\Int32Value.cs" />
<Compile Include="cflow\Int64Value.cs" />
<None Include="cflow\MethodCallInliner.cs" />
<None Include="cflow\MethodCallInlinerBase.cs" />
<Compile Include="cflow\MethodCallInliner.cs" />
<Compile Include="cflow\MethodCallInlinerBase.cs" />
<Compile Include="cflow\Real8Value.cs" />
<None Include="cflow\StLdlocFixer.cs" />
<None Include="cflow\SwitchCflowDeobfuscator.cs" />
<Compile Include="cflow\StLdlocFixer.cs" />
<Compile Include="cflow\SwitchCflowDeobfuscator.cs" />
<Compile Include="cflow\Value.cs" />
<Compile Include="cflow\ValueStack.cs" />
<Compile Include="CodeGenerator.cs" />

View File

@ -18,7 +18,7 @@
*/
using System;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
class BlockCflowDeobfuscator : BlockDeobfuscator, IBranchHandler {
@ -33,7 +33,7 @@ namespace de4dot.blocks.cflow {
protected override bool deobfuscate(Block block) {
this.block = block;
if (!DotNetUtils.isConditionalBranch(block.LastInstr.OpCode.Code) && block.LastInstr.OpCode.Code != Code.Switch)
if (!block.LastInstr.isConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch)
return false;
instructionEmulator.init(blocks);

View File

@ -18,8 +18,7 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
public class BlocksCflowDeobfuscator {

View File

@ -17,7 +17,7 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
public interface IBranchHandler {

View File

@ -18,14 +18,14 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
// Only deobfuscates a method once. A copy of the method (now deobfuscated) is returned.
public class CachedCflowDeobfuscator {
BlocksCflowDeobfuscator cflowDeobfuscator = new BlocksCflowDeobfuscator();
Dictionary<MethodDefinition, MethodDefinition> deobfuscated = new Dictionary<MethodDefinition, MethodDefinition>();
Dictionary<MethodDef, MethodDef> deobfuscated = new Dictionary<MethodDef, MethodDef>();
public CachedCflowDeobfuscator() {
}
@ -43,12 +43,12 @@ namespace de4dot.blocks.cflow {
cflowDeobfuscator.add(blocksDeobfuscator);
}
public MethodDefinition deobfuscate(MethodDefinition method) {
MethodDefinition deobfuscatedMethod;
public MethodDef deobfuscate(MethodDef method) {
MethodDef deobfuscatedMethod;
if (deobfuscated.TryGetValue(method, out deobfuscatedMethod))
return deobfuscatedMethod;
if (method.Body == null || method.Body.Instructions.Count == 0) {
if (method.CilBody == null || method.CilBody.Instructions.Count == 0) {
deobfuscated[method] = method;
return method;
}

View File

@ -18,8 +18,8 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
public class CflowDeobfuscator : ICflowDeobfuscator {
@ -32,18 +32,18 @@ namespace de4dot.blocks.cflow {
cflowDeobfuscator.add(blocksDeobfuscator);
}
public void deobfuscate(MethodDefinition method) {
public void deobfuscate(MethodDef method) {
deobfuscate(method, (blocks) => {
cflowDeobfuscator.init(blocks);
cflowDeobfuscator.deobfuscate();
});
}
static bool hasNonEmptyBody(MethodDefinition method) {
return method.Body != null && method.Body.Instructions.Count > 0;
static bool hasNonEmptyBody(MethodDef method) {
return method.CilBody != null && method.CilBody.Instructions.Count > 0;
}
void deobfuscate(MethodDefinition method, Action<Blocks> handler) {
void deobfuscate(MethodDef method, Action<Blocks> handler) {
if (hasNonEmptyBody(method)) {
var blocks = new Blocks(method);

View File

@ -19,19 +19,19 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
using de4dot.blocks;
namespace de4dot.blocks.cflow {
// Very simple constants folder which is all that's needed at the moment
class ConstantsFolder : BlockDeobfuscator {
InstructionEmulator instructionEmulator = new InstructionEmulator();
List<ParameterDefinition> args;
IList<Parameter> args;
protected override void init(List<Block> allBlocks) {
base.init(allBlocks);
args = DotNetUtils.getParameters(blocks.Method);
args = blocks.Method.Parameters;
}
protected override bool deobfuscate(Block block) {
@ -49,7 +49,7 @@ namespace de4dot.blocks.cflow {
case Code.Ldarg_2:
case Code.Ldarg_3:
case Code.Ldarg_S:
changed |= fixLoadInstruction(block, i, instructionEmulator.getArg(DotNetUtils.getParameter(args, instr.Instruction)));
changed |= fixLoadInstruction(block, i, instructionEmulator.getArg(instr.Instruction.GetParameter(args)));
break;
case Code.Ldloc:
@ -58,17 +58,17 @@ namespace de4dot.blocks.cflow {
case Code.Ldloc_2:
case Code.Ldloc_3:
case Code.Ldloc_S:
changed |= fixLoadInstruction(block, i, instructionEmulator.getLocal(DotNetUtils.getLocalVar(blocks.Locals, instr.Instruction)));
changed |= fixLoadInstruction(block, i, instructionEmulator.getLocal(instr.Instruction.GetLocal(blocks.Locals)));
break;
case Code.Ldarga:
case Code.Ldarga_S:
instructionEmulator.makeArgUnknown((ParameterDefinition)instr.Operand);
instructionEmulator.makeArgUnknown((Parameter)instr.Operand);
break;
case Code.Ldloca:
case Code.Ldloca_S:
instructionEmulator.makeLocalUnknown((VariableDefinition)instr.Operand);
instructionEmulator.makeLocalUnknown((Local)instr.Operand);
break;
}
@ -89,7 +89,7 @@ namespace de4dot.blocks.cflow {
var intValue = (Int32Value)value;
if (!intValue.allBitsValid())
return false;
block.Instructions[index] = new Instr(DotNetUtils.createLdci4(intValue.value));
block.Instructions[index] = new Instr(Instruction.CreateLdcI4(intValue.value));
return true;
}
else if (value.isInt64()) {

View File

@ -18,7 +18,7 @@
*/
using System.Collections.Generic;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
// Removes dead code that is the result of one of our optimizations, or created by the
@ -185,7 +185,7 @@ namespace de4dot.blocks.cflow {
case Code.Ldc_I8:
case Code.Ldc_R4:
case Code.Ldc_R8:
case Code.Ldelem_Any:
case Code.Ldelem:
case Code.Ldelem_I:
case Code.Ldelem_I1:
case Code.Ldelem_I2:
@ -237,7 +237,6 @@ namespace de4dot.blocks.cflow {
case Code.Mul_Ovf_Un:
case Code.Neg:
case Code.Newarr:
case Code.No:
case Code.Nop:
case Code.Not:
case Code.Or:
@ -257,7 +256,7 @@ namespace de4dot.blocks.cflow {
case Code.Sub_Ovf:
case Code.Sub_Ovf_Un:
case Code.Switch:
case Code.Tail:
case Code.Tailcall:
case Code.Throw:
case Code.Unaligned:
case Code.Unbox:
@ -276,7 +275,7 @@ namespace de4dot.blocks.cflow {
case Code.Newobj:
case Code.Starg:
case Code.Starg_S:
case Code.Stelem_Any:
case Code.Stelem:
case Code.Stelem_I:
case Code.Stelem_I1:
case Code.Stelem_I2:
@ -380,7 +379,7 @@ namespace de4dot.blocks.cflow {
}
static void calculateStackUsage(Instruction instr, bool methodHasReturnValue, out int pushes, out int pops) {
DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops);
instr.CalculateStackUsage(false, out pushes, out pops);
}
}
}

View File

@ -19,7 +19,7 @@
using System;
using System.Collections.Generic;
using Mono.Cecil.Cil;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
// Removes dead stores by replacing the stloc with a pop. Other optimizations will notice it's
@ -80,7 +80,7 @@ namespace de4dot.blocks.cflow {
void findLoadStores() {
foreach (var block in allBlocks) {
foreach (var instr in block.Instructions) {
VariableDefinition local;
Local local;
AccessFlags flags;
switch (instr.OpCode.Code) {
case Code.Ldloc:
@ -105,7 +105,7 @@ namespace de4dot.blocks.cflow {
case Code.Ldloca_S:
case Code.Ldloca:
local = instr.Operand as VariableDefinition;
local = instr.Operand as Local;
flags = AccessFlags.Read | AccessFlags.Write;
break;
@ -128,7 +128,7 @@ namespace de4dot.blocks.cflow {
var instructions = block.Instructions;
for (int i = 0; i < instructions.Count; i++) {
var instr = instructions[i];
VariableDefinition local;
Local local;
switch (instr.OpCode.Code) {
case Code.Stloc:
case Code.Stloc_S:

View File

@ -17,10 +17,10 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using Mono.Cecil;
using dot10.DotNet;
namespace de4dot.blocks.cflow {
public interface ICflowDeobfuscator {
void deobfuscate(MethodDefinition method);
void deobfuscate(MethodDef method);
}
}

View File

@ -42,11 +42,9 @@ namespace de4dot.blocks.cflow {
init(method);
}
#if PORT
public void init(Blocks blocks) {
init(blocks.Method);
}
#endif
public void init(MethodDef method) {
this.parameterDefs = method.Parameters;
@ -234,7 +232,6 @@ namespace de4dot.blocks.cflow {
return valueStack.peek();
}
#if PORT
public void emulate(IEnumerable<Instr> instructions) {
foreach (var instr in instructions)
emulate(instr.Instruction);
@ -244,7 +241,6 @@ namespace de4dot.blocks.cflow {
for (int i = start; i < end; i++)
emulate(instructions[i].Instruction);
}
#endif
public void emulate(Instruction instr) {
switch (instr.OpCode.Code) {

View File

@ -18,8 +18,8 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
public class MethodCallInliner : MethodCallInlinerBase {
@ -40,12 +40,12 @@ namespace de4dot.blocks.cflow {
return changed;
}
protected virtual bool canInline(MethodDefinition method) {
if (method.GenericParameters.Count > 0)
protected virtual bool canInline(MethodDef method) {
if (method.GenericParams.Count > 0)
return false;
if (method == blocks.Method)
return false;
if (!MemberReferenceHelper.compareTypes(method.DeclaringType, blocks.Method.DeclaringType))
if (!new SigComparer().Equals(method.DeclaringType, blocks.Method.DeclaringType))
return false;
if (method.IsStatic)
@ -56,13 +56,13 @@ namespace de4dot.blocks.cflow {
}
bool inlineMethod(Instruction callInstr, int instrIndex) {
var methodToInline = callInstr.Operand as MethodDefinition;
var methodToInline = callInstr.Operand as MethodDef;
if (methodToInline == null)
return false;
if (!canInline(methodToInline))
return false;
var body = methodToInline.Body;
var body = methodToInline.CilBody;
if (body == null)
return false;
@ -113,10 +113,10 @@ namespace de4dot.blocks.cflow {
}
}
protected override bool isCompatibleType(int paramIndex, TypeReference origType, TypeReference newType) {
if (MemberReferenceHelper.compareTypes(origType, newType))
protected override bool isCompatibleType(int paramIndex, IType origType, IType newType) {
if (new SigComparer().Equals(origType, newType))
return true;
if (newType.IsValueType || origType.IsValueType)
if (isValueType(newType) || isValueType(origType))
return false;
return newType.FullName == "System.Object";
}

View File

@ -18,8 +18,8 @@
*/
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
public abstract class MethodCallInlinerBase : IBlocksDeobfuscator {
@ -60,7 +60,7 @@ namespace de4dot.blocks.cflow {
this.patchIndex = patchIndex;
this.afterIndex = afterIndex;
this.lastInstr = lastInstr;
this.clonedInstr = new Instr(DotNetUtils.clone(lastInstr));
this.clonedInstr = new Instr(lastInstr.Clone());
}
public void patch(Block block) {
@ -68,7 +68,7 @@ namespace de4dot.blocks.cflow {
}
}
protected bool inlineLoadMethod(int patchIndex, MethodDefinition methodToInline, Instruction loadInstr, int instrIndex) {
protected bool inlineLoadMethod(int patchIndex, MethodDef methodToInline, Instruction loadInstr, int instrIndex) {
if (!isReturn(methodToInline, instrIndex))
return false;
@ -76,19 +76,19 @@ namespace de4dot.blocks.cflow {
for (int i = 0; i < methodArgsCount; i++)
block.insert(patchIndex++, Instruction.Create(OpCodes.Pop));
block.Instructions[patchIndex] = new Instr(DotNetUtils.clone(loadInstr));
block.Instructions[patchIndex] = new Instr(loadInstr.Clone());
return true;
}
protected bool inlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex) {
protected bool inlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) {
return inlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0);
}
protected bool inlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
protected bool inlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
return patchMethod(methodToInline, tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, popLastArgs));
}
protected bool patchMethod(MethodDefinition methodToInline, InstructionPatcher patcher) {
protected bool patchMethod(MethodDef methodToInline, InstructionPatcher patcher) {
if (patcher == null)
return false;
@ -99,11 +99,11 @@ namespace de4dot.blocks.cflow {
return true;
}
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex) {
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex) {
return tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0);
}
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
int loadIndex = 0;
int methodArgsCount = DotNetUtils.getArgsCount(methodToInline);
bool foundLdarga = false;
@ -128,10 +128,10 @@ namespace de4dot.blocks.cflow {
if (!isLdarg)
break;
if (DotNetUtils.getArgIndex(instr) != loadIndex)
if (instr.GetParameterIndex() != loadIndex)
return null;
loadIndex++;
instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
instr = DotNetUtils.getInstruction(methodToInline.CilBody.Instructions, ref instrIndex);
}
if (instr == null || loadIndex != methodArgsCount - popLastArgs)
return null;
@ -140,11 +140,11 @@ namespace de4dot.blocks.cflow {
if (foundLdarga)
return null;
var callInstr = instr;
var calledMethod = callInstr.Operand as MethodReference;
var calledMethod = callInstr.Operand as IMethod;
if (calledMethod == null)
return null;
if (!isCompatibleType(-1, calledMethod.MethodReturnType.ReturnType, methodToInline.MethodReturnType.ReturnType))
if (!isCompatibleType(-1, calledMethod.MethodSig.RetType, methodToInline.MethodSig.RetType))
return null;
if (!checkSameMethods(calledMethod, methodToInline, popLastArgs))
@ -156,19 +156,19 @@ namespace de4dot.blocks.cflow {
if (foundLdarga)
return null;
var newobjInstr = instr;
var ctor = newobjInstr.Operand as MethodReference;
var ctor = newobjInstr.Operand as IMethod;
if (ctor == null)
return null;
if (!isCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodReturnType.ReturnType))
if (!isCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodSig.RetType))
return null;
var methodArgs = DotNetUtils.getArgs(methodToInline);
var methodArgs = methodToInline.Parameters;
var calledMethodArgs = DotNetUtils.getArgs(ctor);
if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count)
if (methodArgs.Length + 1 - popLastArgs != calledMethodArgs.Count)
return null;
for (int i = 1; i < calledMethodArgs.Count; i++) {
if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1]))
if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1].Type))
return null;
}
@ -186,25 +186,26 @@ namespace de4dot.blocks.cflow {
return null;
}
protected virtual bool isReturn(MethodDefinition methodToInline, int instrIndex) {
var instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
protected virtual bool isReturn(MethodDef methodToInline, int instrIndex) {
var instr = DotNetUtils.getInstruction(methodToInline.CilBody.Instructions, ref instrIndex);
return instr != null && instr.OpCode.Code == Code.Ret;
}
protected bool checkSameMethods(MethodReference method, MethodDefinition methodToInline) {
protected bool checkSameMethods(IMethod method, MethodDef methodToInline) {
return checkSameMethods(method, methodToInline, 0);
}
protected bool checkSameMethods(MethodReference method, MethodDefinition methodToInline, int ignoreLastMethodToInlineArgs) {
var methodToInlineArgs = DotNetUtils.getArgs(methodToInline);
protected bool checkSameMethods(IMethod method, MethodDef methodToInline, int ignoreLastMethodToInlineArgs) {
var methodToInlineArgs = methodToInline.Parameters;
var methodArgs = DotNetUtils.getArgs(method);
if (methodToInlineArgs.Count - ignoreLastMethodToInlineArgs != methodArgs.Count)
bool hasImplicitThis = method.MethodSig.HasThis && !method.MethodSig.ExplicitThis;
if (methodToInlineArgs.Length - ignoreLastMethodToInlineArgs != methodArgs.Count)
return false;
for (int i = 0; i < methodArgs.Count; i++) {
var methodArg = methodArgs[i];
var methodToInlineArg = methodToInlineArgs[i];
var methodToInlineArg = methodToInlineArgs[i].Type;
if (!isCompatibleType(i, methodArg, methodToInlineArg)) {
if (i != 0 || !method.HasImplicitThis)
if (i != 0 || !hasImplicitThis)
return false;
if (!isCompatibleValueThisPtr(methodArg, methodToInlineArg))
return false;
@ -214,17 +215,24 @@ namespace de4dot.blocks.cflow {
return true;
}
protected virtual bool isCompatibleType(int paramIndex, TypeReference origType, TypeReference newType) {
return MemberReferenceHelper.compareTypes(origType, newType);
protected virtual bool isCompatibleType(int paramIndex, IType origType, IType newType) {
return new SigComparer().Equals(origType, newType);
}
static bool isCompatibleValueThisPtr(TypeReference origType, TypeReference newType) {
var newByRef = newType as ByReferenceType;
static bool isCompatibleValueThisPtr(IType origType, IType newType) {
var newByRef = newType as ByRefSig;
if (newByRef == null)
return false;
if (!newByRef.ElementType.IsValueType || !origType.IsValueType)
if (!isValueType(newByRef.Next) || !isValueType(origType))
return false;
return MemberReferenceHelper.compareTypes(origType, newByRef.ElementType);
return new SigComparer().Equals(origType, newByRef.Next);
}
protected static bool isValueType(IType type) {
if (type == null)
return false;
//TODO:
return false;
}
}
}

View File

@ -18,12 +18,13 @@
*/
using System.Collections.Generic;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
// Replace stloc + ldloc with dup + stloc
class StLdlocFixer : BlockDeobfuscator {
IList<VariableDefinition> locals;
IList<Local> locals;
protected override void init(List<Block> allBlocks) {
base.init(allBlocks);
@ -49,7 +50,7 @@ namespace de4dot.blocks.cflow {
if (!instructions[i + 1].isLdloc())
break;
var local = Instr.getLocalVar(locals, instr);
if (local.VariableType.FullName != "System.Boolean")
if (local.Type.ElementType != ElementType.Boolean)
continue;
if (local != Instr.getLocalVar(locals, instructions[i + 1]))
break;

View File

@ -19,7 +19,8 @@
using System;
using System.Collections.Generic;
using Mono.Cecil.Cil;
using dot10.DotNet;
using dot10.DotNet.Emit;
namespace de4dot.blocks.cflow {
class SwitchCflowDeobfuscator : BlockDeobfuscator {
@ -64,7 +65,7 @@ namespace de4dot.blocks.cflow {
}
bool isSwitchType2(Block switchBlock) {
VariableDefinition local = null;
Local local = null;
foreach (var instr in switchBlock.Instructions) {
if (!instr.isLdloc())
continue;
@ -178,7 +179,7 @@ namespace de4dot.blocks.cflow {
// swblk:
// ldloc N
// switch (......)
bool deobfuscateLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block, VariableDefinition switchVariable) {
bool deobfuscateLdloc(IList<Block> switchTargets, Block switchFallThrough, Block block, Local switchVariable) {
bool changed = false;
foreach (var source in new List<Block>(block.Sources)) {
if (isBranchBlock(source)) {
@ -366,18 +367,18 @@ namespace de4dot.blocks.cflow {
return changed;
}
static Block createBlock(Dictionary<VariableDefinition, int> consts, Block fallThrough) {
static Block createBlock(Dictionary<Local, int> consts, Block fallThrough) {
var block = new Block();
foreach (var kv in consts) {
block.Instructions.Add(new Instr(DotNetUtils.createLdci4(kv.Value)));
block.Instructions.Add(new Instr(Instruction.CreateLdcI4(kv.Value)));
block.Instructions.Add(new Instr(Instruction.Create(OpCodes.Stloc, kv.Key)));
}
fallThrough.Parent.add(block);
return block;
}
Dictionary<VariableDefinition, int> getBccLocalConstants(Block block) {
var dict = new Dictionary<VariableDefinition, int>();
Dictionary<Local, int> getBccLocalConstants(Block block) {
var dict = new Dictionary<Local, int>();
var instrs = block.Instructions;
for (int i = 0; i < instrs.Count; i++) {
var instr = instrs[i];
@ -397,7 +398,7 @@ namespace de4dot.blocks.cflow {
dict.Remove(local);
}
else if (instr.OpCode.Code == Code.Ldloca || instr.OpCode.Code == Code.Ldloca_S) {
var local = instr.Operand as VariableDefinition;
var local = instr.Operand as Local;
if (local != null)
dict.Remove(local);
}

2
dot10

@ -1 +1 @@
Subproject commit 526604c81df777accde4e45327cffcba954c356c
Subproject commit e543043aff5f9f14484038d0d7bb3850b8d1d2c9