de4dot-cex/de4dot.code/deobfuscators/ConfuserEx/ConstantInliner.cs
ViR Dash 23477ccb5f Implemented ConfuserEx deobfuscator
x86 cflow and x86 constant decryption
Backport of LINQ (LinqBridge)
Shift left/right emulation fixes in de4dot core
Block class extended to hold additional information
2017-02-13 11:14:22 +02:00

181 lines
8.4 KiB
C#

using System.Collections.Generic;
using de4dot.blocks;
using de4dot.blocks.cflow;
using System;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
namespace de4dot.code.deobfuscators.ConfuserEx
{
class ConstantsInliner : IBlocksDeobfuscator
{
Blocks blocks;
SByteValueInliner sbyteValueInliner;
ByteValueInliner byteValueInliner;
Int16ValueInliner int16ValueInliner;
UInt16ValueInliner uint16ValueInliner;
Int32ValueInliner int32ValueInliner;
UInt32ValueInliner uint32ValueInliner;
Int64ValueInliner int64ValueInliner;
UInt64ValueInliner uint64ValueInliner;
SingleValueInliner singleValueInliner;
DoubleValueInliner doubleValueInliner;
ArrayValueInliner arrayValueInliner;
public bool ExecuteIfNotModified { get; set; }
public ConstantsInliner(SByteValueInliner sbyteValueInliner, ByteValueInliner byteValueInliner,
Int16ValueInliner int16ValueInliner, UInt16ValueInliner uint16ValueInliner, Int32ValueInliner int32ValueInliner,
UInt32ValueInliner uint32ValueInliner, Int64ValueInliner int64ValueInliner, UInt64ValueInliner uint64ValueInliner,
SingleValueInliner singleValueInliner, DoubleValueInliner doubleValueInliner, ArrayValueInliner arrayValueInliner)
{
this.sbyteValueInliner = sbyteValueInliner;
this.byteValueInliner = byteValueInliner;
this.int16ValueInliner = int16ValueInliner;
this.uint16ValueInliner = uint16ValueInliner;
this.int32ValueInliner = int32ValueInliner;
this.uint32ValueInliner = uint32ValueInliner;
this.int64ValueInliner = int64ValueInliner;
this.uint64ValueInliner = uint64ValueInliner;
this.singleValueInliner = singleValueInliner;
this.doubleValueInliner = doubleValueInliner;
this.arrayValueInliner = arrayValueInliner;
}
public void DeobfuscateBegin(Blocks blocks)
{
this.blocks = blocks;
}
public bool Deobfuscate(List<Block> allBlocks)
{
bool modified = false;
foreach (var block in allBlocks)
{
modified |= sbyteValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= byteValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= int16ValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= uint16ValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= int32ValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= uint32ValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= int64ValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= uint64ValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= singleValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= doubleValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
modified |= arrayValueInliner.Decrypt(blocks.Method, allBlocks) != 0;
}
return modified;
}
}
public class SByteValueInliner : ValueInlinerBase<sbyte>
{
protected override void InlineReturnValues(IList<CallResult> callResults)
{
foreach (var callResult in callResults)
{
var block = callResult.block;
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int)callResult.returnValue));
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.SByte");
Logger.v("Decrypted sbyte: {0}", callResult.returnValue);
}
}
}
public class ByteValueInliner : ValueInlinerBase<byte>
{
protected override void InlineReturnValues(IList<CallResult> callResults)
{
foreach (var callResult in callResults)
{
var block = callResult.block;
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int)callResult.returnValue));
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.Byte");
Logger.v("Decrypted byte: {0}", callResult.returnValue);
}
}
}
public class Int16ValueInliner : ValueInlinerBase<short>
{
protected override void InlineReturnValues(IList<CallResult> callResults)
{
foreach (var callResult in callResults)
{
var block = callResult.block;
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int)callResult.returnValue));
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.Int16");
Logger.v("Decrypted int16: {0}", callResult.returnValue);
}
}
}
public class UInt16ValueInliner : ValueInlinerBase<ushort>
{
protected override void InlineReturnValues(IList<CallResult> callResults)
{
foreach (var callResult in callResults)
{
var block = callResult.block;
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int)callResult.returnValue));
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.UInt16");
Logger.v("Decrypted uint16: {0}", callResult.returnValue);
}
}
}
public class UInt32ValueInliner : ValueInlinerBase<uint>
{
protected override void InlineReturnValues(IList<CallResult> callResults)
{
foreach (var callResult in callResults)
{
var block = callResult.block;
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int)callResult.returnValue));
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.UInt32");
Logger.v("Decrypted uint32: {0}", callResult.returnValue);
}
}
}
public class UInt64ValueInliner : ValueInlinerBase<ulong>
{
protected override void InlineReturnValues(IList<CallResult> callResults)
{
foreach (var callResult in callResults)
{
var block = callResult.block;
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
block.Replace(callResult.callStartIndex, num, OpCodes.Ldc_I8.ToInstruction((long)callResult.returnValue));
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.UInt64");
Logger.v("Decrypted uint64: {0}", callResult.returnValue);
}
}
}
public class ArrayValueInliner : ValueInlinerBase<Array>
{
InitializedDataCreator initializedDataCreator;
public ArrayValueInliner(InitializedDataCreator initializedDataCreator) { this.initializedDataCreator = initializedDataCreator; }
protected override void InlineReturnValues(IList<CallResult> callResults)
{
foreach (var callResult in callResults)
{
var block = callResult.block;
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
var generic = (callResult.GetMethodRef() as MethodSpec).GenericInstMethodSig.GenericArguments;
ITypeDefOrRef sig = generic[0].Next.ToTypeDefOrRef();
initializedDataCreator.AddInitializeArrayCode(block, callResult.callStartIndex, num, sig, callResult.returnValue as byte[]);
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, sig.ToString()); //TODO: sig.ToString() ??
Logger.v("Decrypted array <{1}>: {0}", callResult.returnValue, sig.ToString());
}
}
}
}