2017-08-08 18:27:21 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
using de4dot.blocks;
|
|
|
|
|
using de4dot.blocks.cflow;
|
|
|
|
|
using dnlib.DotNet;
|
|
|
|
|
using dnlib.DotNet.Emit;
|
|
|
|
|
|
|
|
|
|
namespace de4dot.code.deobfuscators.ConfuserEx
|
|
|
|
|
{
|
2017-08-08 18:27:21 +08:00
|
|
|
|
internal class ConstantsInliner : IBlocksDeobfuscator
|
2017-02-13 17:14:22 +08:00
|
|
|
|
{
|
2017-08-08 18:27:21 +08:00
|
|
|
|
private readonly ArrayValueInliner _arrayValueInliner;
|
|
|
|
|
private readonly ByteValueInliner _byteValueInliner;
|
|
|
|
|
private readonly DoubleValueInliner _doubleValueInliner;
|
|
|
|
|
private readonly Int16ValueInliner _int16ValueInliner;
|
|
|
|
|
private readonly Int32ValueInliner _int32ValueInliner;
|
|
|
|
|
private readonly Int64ValueInliner _int64ValueInliner;
|
|
|
|
|
private readonly SByteValueInliner _sbyteValueInliner;
|
|
|
|
|
private readonly SingleValueInliner _singleValueInliner;
|
|
|
|
|
private readonly UInt16ValueInliner _uint16ValueInliner;
|
|
|
|
|
private readonly UInt32ValueInliner _uint32ValueInliner;
|
|
|
|
|
private readonly UInt64ValueInliner _uint64ValueInliner;
|
|
|
|
|
private Blocks _blocks;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
|
|
|
|
|
public ConstantsInliner(SByteValueInliner sbyteValueInliner, ByteValueInliner byteValueInliner,
|
2017-08-08 18:27:21 +08:00
|
|
|
|
Int16ValueInliner int16ValueInliner, UInt16ValueInliner uint16ValueInliner,
|
|
|
|
|
Int32ValueInliner int32ValueInliner,
|
|
|
|
|
UInt32ValueInliner uint32ValueInliner, Int64ValueInliner int64ValueInliner,
|
|
|
|
|
UInt64ValueInliner uint64ValueInliner,
|
|
|
|
|
SingleValueInliner singleValueInliner, DoubleValueInliner doubleValueInliner,
|
|
|
|
|
ArrayValueInliner arrayValueInliner)
|
2017-02-13 17:14:22 +08:00
|
|
|
|
{
|
2017-08-08 18:27:21 +08:00
|
|
|
|
_sbyteValueInliner = sbyteValueInliner;
|
|
|
|
|
_byteValueInliner = byteValueInliner;
|
|
|
|
|
_int16ValueInliner = int16ValueInliner;
|
|
|
|
|
_uint16ValueInliner = uint16ValueInliner;
|
|
|
|
|
_int32ValueInliner = int32ValueInliner;
|
|
|
|
|
_uint32ValueInliner = uint32ValueInliner;
|
|
|
|
|
_int64ValueInliner = int64ValueInliner;
|
|
|
|
|
_uint64ValueInliner = uint64ValueInliner;
|
|
|
|
|
_singleValueInliner = singleValueInliner;
|
|
|
|
|
_doubleValueInliner = doubleValueInliner;
|
|
|
|
|
_arrayValueInliner = arrayValueInliner;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-08 18:27:21 +08:00
|
|
|
|
public bool ExecuteIfNotModified { get; set; }
|
|
|
|
|
|
2017-02-13 17:14:22 +08:00
|
|
|
|
public void DeobfuscateBegin(Blocks blocks)
|
|
|
|
|
{
|
2017-08-08 18:27:21 +08:00
|
|
|
|
_blocks = blocks;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Deobfuscate(List<Block> allBlocks)
|
|
|
|
|
{
|
2017-08-08 18:27:21 +08:00
|
|
|
|
var modified = false;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
foreach (var block in allBlocks)
|
|
|
|
|
{
|
2017-08-08 18:27:21 +08:00
|
|
|
|
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;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
}
|
|
|
|
|
return modified;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-08 18:27:21 +08:00
|
|
|
|
|
2017-02-13 17:14:22 +08:00
|
|
|
|
public class SByteValueInliner : ValueInlinerBase<sbyte>
|
|
|
|
|
{
|
|
|
|
|
protected override void InlineReturnValues(IList<CallResult> callResults)
|
|
|
|
|
{
|
|
|
|
|
foreach (var callResult in callResults)
|
|
|
|
|
{
|
|
|
|
|
var block = callResult.block;
|
2017-08-08 18:27:21 +08:00
|
|
|
|
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
|
2017-08-08 18:27:21 +08:00
|
|
|
|
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int) callResult.returnValue));
|
2017-02-13 17:14:22 +08:00
|
|
|
|
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.SByte");
|
|
|
|
|
Logger.v("Decrypted sbyte: {0}", callResult.returnValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-08 18:27:21 +08:00
|
|
|
|
|
2017-02-13 17:14:22 +08:00
|
|
|
|
public class ByteValueInliner : ValueInlinerBase<byte>
|
|
|
|
|
{
|
|
|
|
|
protected override void InlineReturnValues(IList<CallResult> callResults)
|
|
|
|
|
{
|
|
|
|
|
foreach (var callResult in callResults)
|
|
|
|
|
{
|
|
|
|
|
var block = callResult.block;
|
2017-08-08 18:27:21 +08:00
|
|
|
|
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
|
2017-08-08 18:27:21 +08:00
|
|
|
|
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int) callResult.returnValue));
|
2017-02-13 17:14:22 +08:00
|
|
|
|
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.Byte");
|
|
|
|
|
Logger.v("Decrypted byte: {0}", callResult.returnValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-08 18:27:21 +08:00
|
|
|
|
|
2017-02-13 17:14:22 +08:00
|
|
|
|
public class Int16ValueInliner : ValueInlinerBase<short>
|
|
|
|
|
{
|
|
|
|
|
protected override void InlineReturnValues(IList<CallResult> callResults)
|
|
|
|
|
{
|
|
|
|
|
foreach (var callResult in callResults)
|
|
|
|
|
{
|
|
|
|
|
var block = callResult.block;
|
2017-08-08 18:27:21 +08:00
|
|
|
|
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
|
2017-08-08 18:27:21 +08:00
|
|
|
|
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int) callResult.returnValue));
|
2017-02-13 17:14:22 +08:00
|
|
|
|
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.Int16");
|
|
|
|
|
Logger.v("Decrypted int16: {0}", callResult.returnValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-08 18:27:21 +08:00
|
|
|
|
|
2017-02-13 17:14:22 +08:00
|
|
|
|
public class UInt16ValueInliner : ValueInlinerBase<ushort>
|
|
|
|
|
{
|
|
|
|
|
protected override void InlineReturnValues(IList<CallResult> callResults)
|
|
|
|
|
{
|
|
|
|
|
foreach (var callResult in callResults)
|
|
|
|
|
{
|
|
|
|
|
var block = callResult.block;
|
2017-08-08 18:27:21 +08:00
|
|
|
|
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
|
2017-08-08 18:27:21 +08:00
|
|
|
|
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int) callResult.returnValue));
|
2017-02-13 17:14:22 +08:00
|
|
|
|
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.UInt16");
|
|
|
|
|
Logger.v("Decrypted uint16: {0}", callResult.returnValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-08 18:27:21 +08:00
|
|
|
|
|
2017-02-13 17:14:22 +08:00
|
|
|
|
public class UInt32ValueInliner : ValueInlinerBase<uint>
|
|
|
|
|
{
|
|
|
|
|
protected override void InlineReturnValues(IList<CallResult> callResults)
|
|
|
|
|
{
|
|
|
|
|
foreach (var callResult in callResults)
|
|
|
|
|
{
|
|
|
|
|
var block = callResult.block;
|
2017-08-08 18:27:21 +08:00
|
|
|
|
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
|
2017-08-08 18:27:21 +08:00
|
|
|
|
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int) callResult.returnValue));
|
2017-02-13 17:14:22 +08:00
|
|
|
|
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.UInt32");
|
|
|
|
|
Logger.v("Decrypted uint32: {0}", callResult.returnValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-08 18:27:21 +08:00
|
|
|
|
|
2017-02-13 17:14:22 +08:00
|
|
|
|
public class UInt64ValueInliner : ValueInlinerBase<ulong>
|
|
|
|
|
{
|
|
|
|
|
protected override void InlineReturnValues(IList<CallResult> callResults)
|
|
|
|
|
{
|
|
|
|
|
foreach (var callResult in callResults)
|
|
|
|
|
{
|
|
|
|
|
var block = callResult.block;
|
2017-08-08 18:27:21 +08:00
|
|
|
|
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
|
2017-08-08 18:27:21 +08:00
|
|
|
|
block.Replace(callResult.callStartIndex, num,
|
|
|
|
|
OpCodes.Ldc_I8.ToInstruction((long) callResult.returnValue));
|
2017-02-13 17:14:22 +08:00
|
|
|
|
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, "System.UInt64");
|
|
|
|
|
Logger.v("Decrypted uint64: {0}", callResult.returnValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-08 18:27:21 +08:00
|
|
|
|
|
2017-02-13 17:14:22 +08:00
|
|
|
|
public class ArrayValueInliner : ValueInlinerBase<Array>
|
|
|
|
|
{
|
2017-08-08 18:27:21 +08:00
|
|
|
|
private readonly InitializedDataCreator _initializedDataCreator;
|
|
|
|
|
|
|
|
|
|
public ArrayValueInliner(InitializedDataCreator initializedDataCreator)
|
|
|
|
|
{
|
|
|
|
|
_initializedDataCreator = initializedDataCreator;
|
|
|
|
|
}
|
2017-02-13 17:14:22 +08:00
|
|
|
|
|
|
|
|
|
protected override void InlineReturnValues(IList<CallResult> callResults)
|
|
|
|
|
{
|
|
|
|
|
foreach (var callResult in callResults)
|
|
|
|
|
{
|
|
|
|
|
var block = callResult.block;
|
2017-08-08 18:27:21 +08:00
|
|
|
|
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
2017-02-13 17:14:22 +08:00
|
|
|
|
|
2017-08-08 18:27:21 +08:00
|
|
|
|
var generic = ((MethodSpec) callResult.GetMethodRef()).GenericInstMethodSig.GenericArguments;
|
|
|
|
|
var sig = generic[0].Next.ToTypeDefOrRef();
|
2017-02-13 17:14:22 +08:00
|
|
|
|
|
2017-08-08 18:27:21 +08:00
|
|
|
|
_initializedDataCreator.AddInitializeArrayCode(block, callResult.callStartIndex, num, sig,
|
|
|
|
|
callResult.returnValue as byte[]);
|
2017-02-13 17:14:22 +08:00
|
|
|
|
RemoveUnboxInstruction(block, callResult.callStartIndex + 1, sig.ToString()); //TODO: sig.ToString() ??
|
|
|
|
|
Logger.v("Decrypted array <{1}>: {0}", callResult.returnValue, sig.ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|