Port the remaining classes in blocks
This commit is contained in:
parent
301a2fab97
commit
8022a445a9
|
@ -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(),
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
public class FilterHandlerBlock : ScopeBlock {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) { }.
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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 new SigComparer().Equals(origType, newByRef.Next);
|
||||
}
|
||||
|
||||
protected static bool isValueType(IType type) {
|
||||
if (type == null)
|
||||
return false;
|
||||
//TODO:
|
||||
return false;
|
||||
return MemberReferenceHelper.compareTypes(origType, newByRef.ElementType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
2
dot10
|
@ -1 +1 @@
|
|||
Subproject commit 526604c81df777accde4e45327cffcba954c356c
|
||||
Subproject commit e543043aff5f9f14484038d0d7bb3850b8d1d2c9
|
Loading…
Reference in New Issue
Block a user