ConfuserEx deobfuscator code clean-up and refactor
This commit is contained in:
parent
e0a2e805d4
commit
3e4170deb6
|
@ -6,3 +6,4 @@
|
|||
*.suo
|
||||
/Debug/
|
||||
/Release/
|
||||
.idea/
|
||||
|
|
|
@ -1,19 +1,26 @@
|
|||
using de4dot.blocks;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.code.deobfuscators.ConfuserEx
|
||||
{
|
||||
public class ConstantDecrypterBase
|
||||
{
|
||||
private X86Method _nativeMethod;
|
||||
private readonly InstructionEmulator _instructionEmulator = new InstructionEmulator();
|
||||
private X86Method _nativeMethod;
|
||||
|
||||
public MethodDef Method { get; set; }
|
||||
public MethodDef NativeMethod { get; set; }
|
||||
public byte[] Decrypted { get; set; }
|
||||
public uint Magic1 { get; set; }
|
||||
public uint Magic2 { get; set; }
|
||||
public bool CanRemove { get; set; } = true;
|
||||
|
||||
private int? CalculateKey()
|
||||
{
|
||||
|
@ -23,99 +30,93 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return null;
|
||||
|
||||
_instructionEmulator.Pop();
|
||||
int result = _nativeMethod.Execute(((Int32Value)popValue).Value);
|
||||
var result = _nativeMethod.Execute(((Int32Value) popValue).Value);
|
||||
return result;
|
||||
}
|
||||
|
||||
public MethodDef Method { get; set; }
|
||||
public MethodDef NativeMethod { get; set; }
|
||||
public byte[] Decrypted { get; set; }
|
||||
public uint Magic1 { get; set; }
|
||||
public uint Magic2 { get; set; }
|
||||
public bool CanRemove { get; set; } = true;
|
||||
|
||||
private uint CalculateMagic(uint index)
|
||||
{
|
||||
_instructionEmulator.Push(new Int32Value((int)index));
|
||||
_instructionEmulator.Push(new Int32Value((int) index));
|
||||
_nativeMethod = new X86Method(NativeMethod, Method.Module as ModuleDefMD); //TODO: Possible null
|
||||
int? key = CalculateKey();
|
||||
var key = CalculateKey();
|
||||
|
||||
uint uint_0 = (uint) key.Value;
|
||||
var uint_0 = (uint) key.Value;
|
||||
uint_0 &= 0x3fffffff;
|
||||
uint_0 <<= 2;
|
||||
return uint_0;
|
||||
}
|
||||
|
||||
public string DecryptString(uint index)
|
||||
{
|
||||
index = CalculateMagic(index);
|
||||
int count = BitConverter.ToInt32(Decrypted, (int)index);
|
||||
return string.Intern(Encoding.UTF8.GetString(Decrypted, (int)index + 4, count));
|
||||
var count = BitConverter.ToInt32(Decrypted, (int) index);
|
||||
return string.Intern(Encoding.UTF8.GetString(Decrypted, (int) index + 4, count));
|
||||
}
|
||||
|
||||
public T DecryptConstant<T>(uint index)
|
||||
{
|
||||
index = CalculateMagic(index);
|
||||
T[] array = new T[1];
|
||||
Buffer.BlockCopy(Decrypted, (int)index, array, 0, Marshal.SizeOf(typeof(T)));
|
||||
var array = new T[1];
|
||||
Buffer.BlockCopy(Decrypted, (int) index, array, 0, Marshal.SizeOf(typeof(T)));
|
||||
return array[0];
|
||||
}
|
||||
|
||||
public byte[] DecryptArray(uint index)
|
||||
{
|
||||
index = CalculateMagic(index);
|
||||
int count = BitConverter.ToInt32(Decrypted, (int)index);
|
||||
var count = BitConverter.ToInt32(Decrypted, (int) index);
|
||||
//int lengt = BitConverter.ToInt32(Decrypted, (int)index+4); we actualy dont need that
|
||||
byte[] buffer = new byte[count - 4];
|
||||
Buffer.BlockCopy(Decrypted, (int)index + 8, buffer, 0, count - 4);
|
||||
var buffer = new byte[count - 4];
|
||||
Buffer.BlockCopy(Decrypted, (int) index + 8, buffer, 0, count - 4);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstantsDecrypter
|
||||
{
|
||||
TypeDef arrayType;
|
||||
MethodDef constantsDecInitMethod;
|
||||
FieldDef decryptedField, arrayField;
|
||||
List<ConstantDecrypterBase> constantDecrpers = new List<ConstantDecrypterBase>();
|
||||
byte[] decryptedBytes;
|
||||
bool canRemoveLzma = true;
|
||||
private readonly ISimpleDeobfuscator _deobfuscator;
|
||||
private readonly MethodDef _lzmaMethod;
|
||||
|
||||
public bool CanRemoveLzma
|
||||
{
|
||||
get { return canRemoveLzma; }
|
||||
}
|
||||
public TypeDef Type
|
||||
{
|
||||
get { return arrayType; }
|
||||
}
|
||||
public MethodDef Method
|
||||
{
|
||||
get { return constantsDecInitMethod; }
|
||||
}
|
||||
public List<FieldDef> Fields
|
||||
{
|
||||
get { return new List<FieldDef>() { decryptedField, arrayField }; }
|
||||
}
|
||||
public List<ConstantDecrypterBase> Decrypters
|
||||
{
|
||||
get { return constantDecrpers; }
|
||||
}
|
||||
public bool Detected
|
||||
{
|
||||
get { return constantsDecInitMethod != null && decryptedBytes != null && constantDecrpers.Count != 0 && decryptedField != null && arrayField != null; }
|
||||
}
|
||||
private readonly ModuleDef _module;
|
||||
|
||||
private readonly string[] _strDecryptCalledMethods =
|
||||
{
|
||||
"System.Text.Encoding System.Text.Encoding::get_UTF8()",
|
||||
"System.String System.Text.Encoding::GetString(System.Byte[],System.Int32,System.Int32)",
|
||||
"System.Array System.Array::CreateInstance(System.Type,System.Int32)",
|
||||
"System.String System.String::Intern(System.String)",
|
||||
"System.Void System.Buffer::BlockCopy(System.Array,System.Int32,System.Array,System.Int32,System.Int32)",
|
||||
"System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)",
|
||||
"System.Type System.Type::GetElementType()"
|
||||
};
|
||||
|
||||
private byte[] _decryptedBytes;
|
||||
private FieldDef _decryptedField, _arrayField;
|
||||
internal TypeDef ArrayType;
|
||||
|
||||
ModuleDef module;
|
||||
MethodDef lzmaMethod;
|
||||
ISimpleDeobfuscator deobfuscator;
|
||||
public ConstantsDecrypter(ModuleDef module, MethodDef lzmaMethod, ISimpleDeobfuscator deobfsucator)
|
||||
{
|
||||
this.module = module;
|
||||
this.lzmaMethod = lzmaMethod;
|
||||
this.deobfuscator = deobfsucator;
|
||||
_module = module;
|
||||
_lzmaMethod = lzmaMethod;
|
||||
_deobfuscator = deobfsucator;
|
||||
}
|
||||
|
||||
public bool CanRemoveLzma { get; private set; } = true;
|
||||
|
||||
public TypeDef Type => ArrayType;
|
||||
|
||||
public MethodDef Method { get; private set; }
|
||||
|
||||
public List<FieldDef> Fields => new List<FieldDef> {_decryptedField, _arrayField};
|
||||
|
||||
public List<ConstantDecrypterBase> Decrypters { get; } = new List<ConstantDecrypterBase>();
|
||||
|
||||
public bool Detected => Method != null && _decryptedBytes != null && Decrypters.Count != 0 &&
|
||||
_decryptedField != null && _arrayField != null;
|
||||
|
||||
public void Find()
|
||||
{
|
||||
var moduleCctor = DotNetUtils.GetModuleTypeCctor(module);
|
||||
var moduleCctor = DotNetUtils.GetModuleTypeCctor(_module);
|
||||
if (moduleCctor == null)
|
||||
return;
|
||||
foreach (var inst in moduleCctor.Body.Instructions)
|
||||
|
@ -124,20 +125,20 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
continue;
|
||||
if (!(inst.Operand is MethodDef))
|
||||
continue;
|
||||
var method = inst.Operand as MethodDef;
|
||||
var method = (MethodDef) inst.Operand;
|
||||
if (!method.HasBody || !method.IsStatic)
|
||||
continue;
|
||||
if (!DotNetUtils.IsMethod(method, "System.Void", "()"))
|
||||
continue;
|
||||
deobfuscator.Deobfuscate(method, SimpleDeobfuscatorFlags.Force);
|
||||
if (!isStrDecryptInit(method))
|
||||
_deobfuscator.Deobfuscate(method, SimpleDeobfuscatorFlags.Force);
|
||||
if (!IsStringDecrypterInit(method))
|
||||
continue;
|
||||
constantsDecInitMethod = method;
|
||||
Method = method;
|
||||
FindStringDecrypters(moduleCctor.DeclaringType);
|
||||
}
|
||||
}
|
||||
|
||||
bool isStrDecryptInit(MethodDef method)
|
||||
private bool IsStringDecrypterInit(MethodDef method)
|
||||
{
|
||||
var instructions = method.Body.Instructions;
|
||||
|
||||
|
@ -146,7 +147,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
|
||||
if (!instructions[0].IsLdcI4())
|
||||
return false;
|
||||
if (!instructions[1].IsStloc()) //uint num = 96u;
|
||||
if (!instructions[1].IsStloc()) //uint num = 96u;
|
||||
return false;
|
||||
|
||||
if (!instructions[2].IsLdcI4())
|
||||
|
@ -162,17 +163,17 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
if (instructions[5].OpCode != OpCodes.Ldtoken)
|
||||
return false;
|
||||
var aField = instructions[5].Operand as FieldDef;
|
||||
if (aField == null)
|
||||
return false;
|
||||
if (aField.InitialValue == null)
|
||||
if (aField?.InitialValue == null)
|
||||
return false;
|
||||
if (aField.Attributes != (FieldAttributes.Assembly | FieldAttributes.Static | FieldAttributes.HasFieldRVA))
|
||||
return false;
|
||||
if (instructions[6].OpCode != OpCodes.Call)
|
||||
return false;
|
||||
if (instructions[6].Operand.ToString() != "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)")
|
||||
if (instructions[6].Operand.ToString() !=
|
||||
"System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)"
|
||||
)
|
||||
return false;
|
||||
if (!instructions[7].IsStloc()) // uint[] array = new uint[] {.....};
|
||||
if (!instructions[7].IsStloc()) // uint[] array = new uint[] {.....};
|
||||
return false;
|
||||
|
||||
var l = instructions.Count;
|
||||
|
@ -180,9 +181,9 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return false;
|
||||
if (instructions[l - 3].OpCode != OpCodes.Call)
|
||||
return false;
|
||||
if (instructions[l - 3].Operand != lzmaMethod)
|
||||
if (instructions[l - 3].Operand != _lzmaMethod)
|
||||
return false;
|
||||
if (instructions[l - 2].OpCode != OpCodes.Stsfld) //<Module>.byte_0 = <Module>.smethod_0(array4);
|
||||
if (instructions[l - 2].OpCode != OpCodes.Stsfld) //<Module>.byte_0 = <Module>.smethod_0(array4);
|
||||
return false;
|
||||
var dField = instructions[l - 2].Operand as FieldDef;
|
||||
if (dField == null)
|
||||
|
@ -191,53 +192,56 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
{
|
||||
DecryptArray(ConvertArray<uint, byte>(aField.InitialValue));
|
||||
}
|
||||
catch (Exception e) { Console.WriteLine(e.Message); canRemoveLzma = false; return false; }
|
||||
arrayField = aField;
|
||||
arrayType = DotNetUtils.GetType(module, aField.FieldSig.Type);
|
||||
decryptedField = dField;
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
CanRemoveLzma = false;
|
||||
return false;
|
||||
}
|
||||
_arrayField = aField;
|
||||
ArrayType = DotNetUtils.GetType(_module, aField.FieldSig.Type);
|
||||
_decryptedField = dField;
|
||||
return true;
|
||||
}
|
||||
|
||||
private T[] ConvertArray<T, T1>(T1[] array)
|
||||
private static T[] ConvertArray<T, T1>(T1[] array)
|
||||
{
|
||||
int l = Marshal.SizeOf(typeof(T));
|
||||
int l1 = Marshal.SizeOf(typeof(T1));
|
||||
var buffer = new T[(array.Length * l1) / l];
|
||||
var l = Marshal.SizeOf(typeof(T));
|
||||
var l1 = Marshal.SizeOf(typeof(T1));
|
||||
var buffer = new T[array.Length * l1 / l];
|
||||
Buffer.BlockCopy(array, 0, buffer, 0, array.Length * l1);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private void DecryptArray(uint[] array) //TODO: Automatic detection
|
||||
{
|
||||
uint num = 960u; // array size?
|
||||
uint[] array2 = new uint[16];
|
||||
uint num2 = 4136251032u;
|
||||
for (int i = 0; i < 16; i++)
|
||||
var num = 960u; // array size?
|
||||
var array2 = new uint[16];
|
||||
var num2 = 4136251032u;
|
||||
for (var i = 0; i < 16; i++)
|
||||
{
|
||||
num2 ^= num2 >> 12;
|
||||
num2 ^= num2 << 25;
|
||||
num2 ^= num2 >> 27;
|
||||
array2[i] = num2;
|
||||
}
|
||||
int num3 = 0;
|
||||
int num4 = 0;
|
||||
uint[] array3 = new uint[16];
|
||||
byte[] array4 = new byte[num * 4u];
|
||||
while ((long)num3 < (long)((ulong)num))
|
||||
var num3 = 0;
|
||||
var num4 = 0;
|
||||
var array3 = new uint[16];
|
||||
var array4 = new byte[num * 4u];
|
||||
while (num3 < num)
|
||||
{
|
||||
for (int j = 0; j < 16; j++)
|
||||
{
|
||||
for (var j = 0; j < 16; j++)
|
||||
array3[j] = array[num3 + j];
|
||||
}
|
||||
uint num5 = array3[3] * 41u;
|
||||
array3[11] = (array3[11] ^ 3634844963u);
|
||||
uint num6 = array3[3] * 31u;
|
||||
var num5 = array3[3] * 41u;
|
||||
array3[11] = array3[11] ^ 3634844963u;
|
||||
var num6 = array3[3] * 31u;
|
||||
num6 += array3[9] * 47u;
|
||||
num5 += array3[9] * 85u;
|
||||
num5 += array3[10] * 149u;
|
||||
uint num7 = array3[3] << 1;
|
||||
var num7 = array3[3] << 1;
|
||||
num7 += array3[3];
|
||||
uint num8 = array3[3] << 1;
|
||||
var num8 = array3[3] << 1;
|
||||
num8 += array3[3] << 3;
|
||||
num7 += array3[9] << 3;
|
||||
num8 += array3[9] * 13u;
|
||||
|
@ -245,7 +249,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
num6 += array3[10] * 71u;
|
||||
num7 += array3[10] << 1;
|
||||
num6 += array3[1] * 81u;
|
||||
array3[4] = (array3[4] ^ ~array3[6]);
|
||||
array3[4] = array3[4] ^ ~array3[6];
|
||||
num8 += array3[10] << 1;
|
||||
num7 += array3[10] << 4;
|
||||
array3[9] = num6;
|
||||
|
@ -257,11 +261,11 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
num6 = array3[7] * 19u;
|
||||
array3[10] = num7;
|
||||
num6 += array3[8] * 28u;
|
||||
array3[14] = (array3[14] ^ array3[0]);
|
||||
array3[14] = array3[14] ^ array3[0];
|
||||
array3[3] = num8;
|
||||
num6 += array3[12] << 6;
|
||||
array3[1] = num5;
|
||||
array3[2] = (array3[2] ^ array2[2]);
|
||||
array3[2] = array3[2] ^ array2[2];
|
||||
num5 = array3[7] * 28u;
|
||||
num5 += array3[8] << 2;
|
||||
num8 = array3[7] << 1;
|
||||
|
@ -290,53 +294,53 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
num6 = array3[15] >> 22;
|
||||
array3[15] = array3[15] << 10;
|
||||
num8 = array3[1] >> 21;
|
||||
array3[15] = (array3[15] | num6);
|
||||
array3[12] = (array3[12] ^ array2[12]);
|
||||
num6 = (array3[2] & 3262151220u);
|
||||
array3[15] = array3[15] | num6;
|
||||
array3[12] = array3[12] ^ array2[12];
|
||||
num6 = array3[2] & 3262151220u;
|
||||
array3[1] = array3[1] << 11;
|
||||
array3[1] = (array3[1] | num8);
|
||||
array3[1] = array3[1] | num8;
|
||||
array3[7] = array3[7] << 11;
|
||||
array3[0] = array3[0] - array3[14];
|
||||
num7 = array3[13] << 4;
|
||||
num8 = array3[3] * 954284655u;
|
||||
array3[3] = array3[5];
|
||||
array3[5] = num8 * 3102958735u;
|
||||
array3[7] = (array3[7] | num5);
|
||||
array3[7] = array3[7] | num5;
|
||||
num5 = array3[10] << 4;
|
||||
num8 = array3[9] * 2468501497u;
|
||||
array3[2] = (array3[2] & 1032816075u);
|
||||
array3[2] = array3[2] & 1032816075u;
|
||||
array3[13] = array3[13] >> 28;
|
||||
array3[13] = (array3[13] | num7);
|
||||
array3[13] = array3[13] | num7;
|
||||
array3[7] = array3[7] - 888060325u;
|
||||
array3[2] = (array3[2] | (array3[8] & 3262151220u));
|
||||
array3[2] = array3[2] | (array3[8] & 3262151220u);
|
||||
array3[12] = array3[12] * 4056148675u;
|
||||
array3[9] = array3[13];
|
||||
num7 = array3[6] << 5;
|
||||
array3[13] = num8 * 1746582089u;
|
||||
array3[6] = array3[6] >> 27;
|
||||
array3[6] = (array3[6] | num7);
|
||||
array3[8] = (array3[8] & 1032816075u);
|
||||
array3[7] = (array3[7] ^ array2[7]);
|
||||
array3[6] = array3[6] | num7;
|
||||
array3[8] = array3[8] & 1032816075u;
|
||||
array3[7] = array3[7] ^ array2[7];
|
||||
num5 += array3[11] * 46u;
|
||||
num6 *= 869722291u;
|
||||
num8 = array3[10] << 1;
|
||||
num5 += array3[3] * 92u;
|
||||
num5 += array3[5] * 149u;
|
||||
array3[7] = array3[7] - 3922202313u;
|
||||
array3[8] = (array3[8] | num6 * 2576221819u);
|
||||
array3[8] = array3[8] | (num6 * 2576221819u);
|
||||
num8 += array3[11] * 15u;
|
||||
num8 += array3[3] * 37u;
|
||||
num6 = array3[10] * 7u;
|
||||
array3[8] = (array3[8] ^ 1878284212u);
|
||||
array3[8] = array3[8] ^ 1878284212u;
|
||||
num8 += array3[5] * 56u;
|
||||
array3[9] = (array3[9] ^ array2[9]);
|
||||
array3[9] = array3[9] ^ array2[9];
|
||||
num7 = array3[10] << 3;
|
||||
array3[6] = (array3[6] ^ 2841119440u);
|
||||
array3[6] = array3[6] ^ 2841119440u;
|
||||
num6 += array3[11] << 4;
|
||||
array3[2] = (array3[2] ^ 217219923u);
|
||||
array3[2] = array3[2] ^ 217219923u;
|
||||
num7 += array3[10];
|
||||
num6 += array3[3] * 29u;
|
||||
array3[6] = (array3[6] ^ array2[6]);
|
||||
array3[6] = array3[6] ^ array2[6];
|
||||
num7 += array3[11] * 26u;
|
||||
num7 += array3[3] * 52u;
|
||||
num6 += array3[5] * 49u;
|
||||
|
@ -344,24 +348,24 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
array3[3] = num5;
|
||||
array3[10] = num6;
|
||||
num6 = array3[1] * 15u;
|
||||
array3[12] = (array3[12] ^ 1080861703u);
|
||||
array3[12] = array3[12] ^ 1080861703u;
|
||||
array3[5] = num8;
|
||||
num5 = (array3[4] & 3659960635u);
|
||||
num5 = array3[4] & 3659960635u;
|
||||
num6 += array3[12] << 1;
|
||||
array3[4] = (array3[4] & 635006660u);
|
||||
array3[4] = (array3[4] | (array3[9] & 3659960635u));
|
||||
array3[4] = array3[4] & 635006660u;
|
||||
array3[4] = array3[4] | (array3[9] & 3659960635u);
|
||||
num5 *= 1676034815u;
|
||||
array3[11] = num7;
|
||||
num7 = array3[1] * 19u;
|
||||
num6 += array3[12] << 4;
|
||||
array3[9] = (array3[9] & 635006660u);
|
||||
array3[9] = array3[9] & 635006660u;
|
||||
num6 += array3[3] << 6;
|
||||
num7 += array3[12] * 27u;
|
||||
array3[5] = array3[5] - array3[8];
|
||||
array3[9] = (array3[9] | num5 * 1267776767u);
|
||||
array3[9] = array3[9] | (num5 * 1267776767u);
|
||||
num5 = array3[1] << 2;
|
||||
num5 += array3[1];
|
||||
array3[13] = (array3[13] ^ array2[13]);
|
||||
array3[13] = array3[13] ^ array2[13];
|
||||
num8 = array3[1];
|
||||
num6 += array3[3];
|
||||
num5 += array3[12] << 3;
|
||||
|
@ -377,53 +381,53 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
num8 += array3[15] << 1;
|
||||
num8 += array3[15];
|
||||
array3[3] = num6;
|
||||
array3[0] = (array3[0] ^ array3[13]);
|
||||
array3[0] = array3[0] ^ array3[13];
|
||||
array3[14] = array3[14] - array3[15];
|
||||
num7 += array3[15] << 5;
|
||||
array3[13] = (array3[13] ^ ~array3[1]);
|
||||
array3[13] = array3[13] ^ ~array3[1];
|
||||
num6 = array3[10] >> 31;
|
||||
array3[14] = (array3[14] ^ array2[14]);
|
||||
array3[8] = (array3[8] ^ array2[8]);
|
||||
array3[14] = array3[14] ^ array2[14];
|
||||
array3[8] = array3[8] ^ array2[8];
|
||||
array3[12] = num5;
|
||||
array3[1] = num8;
|
||||
array3[5] = (array3[5] ^ array2[5]);
|
||||
array3[11] = (array3[11] ^ array2[11]);
|
||||
num5 = (array3[11] & 2204625944u);
|
||||
array3[1] = (array3[1] ^ array2[1]);
|
||||
array3[4] = (array3[4] ^ array2[4]);
|
||||
array3[11] = (array3[11] & 2090341351u);
|
||||
array3[11] = (array3[11] | (array3[4] & 2204625944u));
|
||||
array3[5] = array3[5] ^ array2[5];
|
||||
array3[11] = array3[11] ^ array2[11];
|
||||
num5 = array3[11] & 2204625944u;
|
||||
array3[1] = array3[1] ^ array2[1];
|
||||
array3[4] = array3[4] ^ array2[4];
|
||||
array3[11] = array3[11] & 2090341351u;
|
||||
array3[11] = array3[11] | (array3[4] & 2204625944u);
|
||||
array3[15] = num7;
|
||||
num8 = (array3[14] & 2496954112u);
|
||||
array3[14] = (array3[14] & 1798013183u);
|
||||
array3[4] = (array3[4] & 2090341351u);
|
||||
array3[15] = (array3[15] ^ array2[15]);
|
||||
num8 = array3[14] & 2496954112u;
|
||||
array3[14] = array3[14] & 1798013183u;
|
||||
array3[4] = array3[4] & 2090341351u;
|
||||
array3[15] = array3[15] ^ array2[15];
|
||||
array3[10] = array3[10] << 1;
|
||||
num5 *= 338764649u;
|
||||
array3[14] = (array3[14] | (array3[9] & 2496954112u));
|
||||
array3[14] = array3[14] | (array3[9] & 2496954112u);
|
||||
array3[15] = array3[15] - array3[0];
|
||||
array3[10] = (array3[10] | num6);
|
||||
array3[10] = (array3[10] ^ array2[10]);
|
||||
array3[3] = (array3[3] ^ array2[3]);
|
||||
array3[10] = array3[10] | num6;
|
||||
array3[10] = array3[10] ^ array2[10];
|
||||
array3[3] = array3[3] ^ array2[3];
|
||||
num8 *= 2292397853u;
|
||||
array3[0] = (array3[0] ^ array2[0]);
|
||||
array3[0] = (array3[0] ^ 2814140307u);
|
||||
array3[2] = (array3[2] ^ ~array3[13]);
|
||||
array3[4] = (array3[4] | num5 * 587046105u);
|
||||
array3[9] = (array3[9] & 1798013183u);
|
||||
array3[9] = (array3[9] | num8 * 1520255797u);
|
||||
for (int k = 0; k < 16; k++)
|
||||
array3[0] = array3[0] ^ array2[0];
|
||||
array3[0] = array3[0] ^ 2814140307u;
|
||||
array3[2] = array3[2] ^ ~array3[13];
|
||||
array3[4] = array3[4] | (num5 * 587046105u);
|
||||
array3[9] = array3[9] & 1798013183u;
|
||||
array3[9] = array3[9] | (num8 * 1520255797u);
|
||||
for (var k = 0; k < 16; k++)
|
||||
{
|
||||
uint num9 = array3[k];
|
||||
array4[num4++] = (byte)num9;
|
||||
array4[num4++] = (byte)(num9 >> 8);
|
||||
array4[num4++] = (byte)(num9 >> 16);
|
||||
array4[num4++] = (byte)(num9 >> 24);
|
||||
var num9 = array3[k];
|
||||
array4[num4++] = (byte) num9;
|
||||
array4[num4++] = (byte) (num9 >> 8);
|
||||
array4[num4++] = (byte) (num9 >> 16);
|
||||
array4[num4++] = (byte) (num9 >> 24);
|
||||
array2[k] ^= num9;
|
||||
}
|
||||
num3 += 16;
|
||||
}
|
||||
decryptedBytes = Lzma.Decompress(array4);
|
||||
_decryptedBytes = Lzma.Decompress(array4);
|
||||
}
|
||||
|
||||
private void FindStringDecrypters(TypeDef type)
|
||||
|
@ -432,12 +436,10 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
{
|
||||
if (!method.HasBody)
|
||||
continue;
|
||||
if (!(method.Signature.ContainsGenericParameter))
|
||||
if (!method.Signature.ContainsGenericParameter)
|
||||
continue;
|
||||
var sig = method.MethodSig;
|
||||
if (sig == null)
|
||||
continue;
|
||||
if (sig.Params.Count != 1)
|
||||
if (sig?.Params.Count != 1)
|
||||
continue;
|
||||
if (sig.Params[0].GetElementType() != ElementType.U4)
|
||||
continue;
|
||||
|
@ -445,28 +447,18 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
continue;
|
||||
if (sig.GenParamCount != 1)
|
||||
continue;
|
||||
deobfuscator.Deobfuscate(method, SimpleDeobfuscatorFlags.Force);
|
||||
_deobfuscator.Deobfuscate(method, SimpleDeobfuscatorFlags.Force);
|
||||
IsStringDecrypter(method);
|
||||
}
|
||||
}
|
||||
|
||||
string[] strDecryptCalledMethods = {
|
||||
"System.Text.Encoding System.Text.Encoding::get_UTF8()",
|
||||
"System.String System.Text.Encoding::GetString(System.Byte[],System.Int32,System.Int32)",
|
||||
"System.Array System.Array::CreateInstance(System.Type,System.Int32)",
|
||||
"System.String System.String::Intern(System.String)",
|
||||
"System.Void System.Buffer::BlockCopy(System.Array,System.Int32,System.Array,System.Int32,System.Int32)",
|
||||
"System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)",
|
||||
"System.Type System.Type::GetElementType()"
|
||||
};
|
||||
|
||||
private void IsStringDecrypter(MethodDef method)
|
||||
{
|
||||
var instr = method.Body.Instructions;
|
||||
if (instr.Count < 25)
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
var i = 0;
|
||||
|
||||
if (!instr[i++].IsLdarg())
|
||||
return;
|
||||
|
@ -481,7 +473,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
if (!DotNetUtils.IsMethod(nativeMethod, "System.Int32", "(System.Int32)"))
|
||||
return;
|
||||
|
||||
if (!instr[i++].IsStarg()) //uint_0 = (uint_0 * 2857448701u ^ 1196001109u);
|
||||
if (!instr[i++].IsStarg()) //uint_0 = (uint_0 * 2857448701u ^ 1196001109u);
|
||||
return;
|
||||
|
||||
if (!instr[i++].IsLdarg())
|
||||
|
@ -504,7 +496,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return;
|
||||
if (instr[i++].OpCode != OpCodes.And)
|
||||
return;
|
||||
if (!instr[i++].IsStarg()) //uint_0 &= 1073741823u;
|
||||
if (!instr[i++].IsStarg()) //uint_0 &= 1073741823u;
|
||||
return;
|
||||
|
||||
if (!instr[i++].IsLdarg())
|
||||
|
@ -513,98 +505,108 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return;
|
||||
if (instr[i++].OpCode != OpCodes.Shl)
|
||||
return;
|
||||
if (!instr[i++].IsStarg()) //uint_0 <<= 2;
|
||||
if (!instr[i++].IsStarg()) //uint_0 <<= 2;
|
||||
return;
|
||||
|
||||
foreach (var mtd in strDecryptCalledMethods)
|
||||
foreach (var mtd in _strDecryptCalledMethods)
|
||||
if (!DotNetUtils.CallsMethod(method, mtd))
|
||||
return;
|
||||
//TODO: Implement
|
||||
//if (!DotNetUtils.LoadsField(method, decryptedField))
|
||||
// return;
|
||||
constantDecrpers.Add(new ConstantDecrypterBase()
|
||||
Decrypters.Add(new ConstantDecrypterBase
|
||||
{
|
||||
Decrypted = decryptedBytes,
|
||||
Decrypted = _decryptedBytes,
|
||||
Method = method,
|
||||
NativeMethod = nativeMethod,
|
||||
NativeMethod = nativeMethod
|
||||
});
|
||||
}
|
||||
|
||||
static bool VerifyGenericArg(MethodSpec gim, ElementType etype)
|
||||
private static bool VerifyGenericArg(MethodSpec gim, ElementType etype)
|
||||
{
|
||||
if (gim == null)
|
||||
return false;
|
||||
var gims = gim.GenericInstMethodSig;
|
||||
var gims = gim?.GenericInstMethodSig;
|
||||
if (gims == null || gims.GenericArguments.Count != 1)
|
||||
return false;
|
||||
return gims.GenericArguments[0].GetElementType() == etype;
|
||||
}
|
||||
|
||||
public string DecryptString(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.String))
|
||||
return null;
|
||||
return info.DecryptString(magic1);
|
||||
}
|
||||
|
||||
public object DecryptSByte(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.I1))
|
||||
return null;
|
||||
return info.DecryptConstant<sbyte>(magic1);
|
||||
}
|
||||
|
||||
public object DecryptByte(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.U1))
|
||||
return null;
|
||||
return info.DecryptConstant<byte>(magic1);
|
||||
}
|
||||
|
||||
public object DecryptInt16(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.I2))
|
||||
return null;
|
||||
return info.DecryptConstant<short>(magic1);
|
||||
}
|
||||
|
||||
public object DecryptUInt16(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.U2))
|
||||
return null;
|
||||
return info.DecryptConstant<ushort>(magic1);
|
||||
}
|
||||
|
||||
public object DecryptInt32(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.I4))
|
||||
return null;
|
||||
return info.DecryptConstant<int>(magic1);
|
||||
}
|
||||
|
||||
public object DecryptUInt32(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.U4))
|
||||
return null;
|
||||
return info.DecryptConstant<uint>(magic1);
|
||||
}
|
||||
|
||||
public object DecryptInt64(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.I8))
|
||||
return null;
|
||||
return info.DecryptConstant<long>(magic1);
|
||||
}
|
||||
|
||||
public object DecryptUInt64(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.U8))
|
||||
return null;
|
||||
return info.DecryptConstant<ulong>(magic1);
|
||||
}
|
||||
|
||||
public object DecryptSingle(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.R4))
|
||||
return null;
|
||||
return info.DecryptConstant<float>(magic1);
|
||||
}
|
||||
|
||||
public object DecryptDouble(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.R8))
|
||||
return null;
|
||||
return info.DecryptConstant<double>(magic1);
|
||||
}
|
||||
|
||||
public object DecryptArray(ConstantDecrypterBase info, MethodSpec gim, uint magic1)
|
||||
{
|
||||
if (!VerifyGenericArg(gim, ElementType.SZArray))
|
||||
|
|
|
@ -1,72 +1,76 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
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
|
||||
internal 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;
|
||||
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;
|
||||
|
||||
public ConstantsInliner(SByteValueInliner sbyteValueInliner, ByteValueInliner byteValueInliner,
|
||||
Int16ValueInliner int16ValueInliner, UInt16ValueInliner uint16ValueInliner,
|
||||
Int32ValueInliner int32ValueInliner,
|
||||
UInt32ValueInliner uint32ValueInliner, Int64ValueInliner int64ValueInliner,
|
||||
UInt64ValueInliner uint64ValueInliner,
|
||||
SingleValueInliner singleValueInliner, DoubleValueInliner doubleValueInliner,
|
||||
ArrayValueInliner arrayValueInliner)
|
||||
{
|
||||
_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;
|
||||
_blocks = blocks;
|
||||
}
|
||||
|
||||
public bool Deobfuscate(List<Block> allBlocks)
|
||||
{
|
||||
bool modified = false;
|
||||
var 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;
|
||||
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)
|
||||
|
@ -74,14 +78,15 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
foreach (var callResult in callResults)
|
||||
{
|
||||
var block = callResult.block;
|
||||
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
|
||||
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int)callResult.returnValue));
|
||||
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)
|
||||
|
@ -89,14 +94,15 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
foreach (var callResult in callResults)
|
||||
{
|
||||
var block = callResult.block;
|
||||
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
|
||||
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int)callResult.returnValue));
|
||||
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)
|
||||
|
@ -104,14 +110,15 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
foreach (var callResult in callResults)
|
||||
{
|
||||
var block = callResult.block;
|
||||
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
|
||||
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int)callResult.returnValue));
|
||||
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)
|
||||
|
@ -119,14 +126,15 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
foreach (var callResult in callResults)
|
||||
{
|
||||
var block = callResult.block;
|
||||
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
|
||||
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int)callResult.returnValue));
|
||||
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)
|
||||
|
@ -134,14 +142,15 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
foreach (var callResult in callResults)
|
||||
{
|
||||
var block = callResult.block;
|
||||
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
|
||||
block.Replace(callResult.callStartIndex, num, Instruction.CreateLdcI4((int)callResult.returnValue));
|
||||
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)
|
||||
|
@ -149,30 +158,37 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
foreach (var callResult in callResults)
|
||||
{
|
||||
var block = callResult.block;
|
||||
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
var num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
|
||||
block.Replace(callResult.callStartIndex, num, OpCodes.Ldc_I8.ToInstruction((long)callResult.returnValue));
|
||||
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;
|
||||
private readonly InitializedDataCreator _initializedDataCreator;
|
||||
|
||||
public ArrayValueInliner(InitializedDataCreator initializedDataCreator)
|
||||
{
|
||||
_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 num = callResult.callEndIndex - callResult.callStartIndex + 1;
|
||||
|
||||
var generic = (callResult.GetMethodRef() as MethodSpec).GenericInstMethodSig.GenericArguments;
|
||||
ITypeDefOrRef sig = generic[0].Next.ToTypeDefOrRef();
|
||||
var generic = ((MethodSpec) callResult.GetMethodRef()).GenericInstMethodSig.GenericArguments;
|
||||
var sig = generic[0].Next.ToTypeDefOrRef();
|
||||
|
||||
initializedDataCreator.AddInitializeArrayCode(block, callResult.callStartIndex, num, sig, callResult.returnValue as byte[]);
|
||||
_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());
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@ using dnlib.DotNet.Emit;
|
|||
|
||||
namespace de4dot.code.deobfuscators.ConfuserEx
|
||||
{
|
||||
class ControlFlowFixer : IBlocksDeobfuscator
|
||||
internal class ControlFlowFixer : IBlocksDeobfuscator
|
||||
{
|
||||
public bool ExecuteIfNotModified { get; }
|
||||
public bool ExecuteIfNotModified { get; } = false;
|
||||
public List<MethodDef> NativeMethods = new List<MethodDef>();
|
||||
|
||||
private readonly InstructionEmulator _instructionEmulator = new InstructionEmulator();
|
||||
|
|
|
@ -17,98 +17,78 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace de4dot.code.deobfuscators.ConfuserEx
|
||||
{
|
||||
|
||||
public class DeobfuscatorInfo : DeobfuscatorInfoBase
|
||||
{
|
||||
public const string THE_NAME = "ConfuserEx";
|
||||
internal const string THE_NAME = "ConfuserEx";
|
||||
public const string THE_TYPE = "cx";
|
||||
const string DEFAULT_REGEX = DeobfuscatorBase.DEFAULT_ASIAN_VALID_NAME_REGEX;
|
||||
private const string DEFAULT_REGEX = DeobfuscatorBase.DEFAULT_ASIAN_VALID_NAME_REGEX;
|
||||
|
||||
public DeobfuscatorInfo()
|
||||
: base(DEFAULT_REGEX)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return THE_NAME; }
|
||||
}
|
||||
|
||||
public override string Type
|
||||
{
|
||||
get { return THE_TYPE; }
|
||||
}
|
||||
public override string Name => THE_NAME;
|
||||
public override string Type => THE_TYPE;
|
||||
|
||||
public override IDeobfuscator CreateDeobfuscator()
|
||||
{
|
||||
return new Deobfuscator(new Deobfuscator.Options
|
||||
{
|
||||
RenameResourcesInCode = false,
|
||||
ValidNameRegex = validNameRegex.Get(),
|
||||
ValidNameRegex = validNameRegex.Get()
|
||||
});
|
||||
}
|
||||
|
||||
class Deobfuscator : DeobfuscatorBase
|
||||
private class Deobfuscator : DeobfuscatorBase
|
||||
{
|
||||
private bool _detectedConfuserExAttribute = false, _deobfuscating = false;
|
||||
private string _version = "";
|
||||
private LzmaFinder _lzmaFinder;
|
||||
private readonly ControlFlowFixer _controlFlowFixer = new ControlFlowFixer();
|
||||
|
||||
private bool _canRemoveLzma = true;
|
||||
private ConstantsDecrypter _constantDecrypter;
|
||||
private ResourceDecrypter _resourceDecrypter;
|
||||
private bool _detectedConfuserExAttribute, _deobfuscating;
|
||||
private LzmaFinder _lzmaFinder;
|
||||
private ProxyCallFixer _proxyCallFixer;
|
||||
private ControlFlowFixer _controlFlowFixer = new ControlFlowFixer();
|
||||
|
||||
#region ConstantInliners
|
||||
|
||||
SByteValueInliner sbyteValueInliner;
|
||||
ByteValueInliner byteValueInliner;
|
||||
Int16ValueInliner int16ValueInliner;
|
||||
UInt16ValueInliner uint16ValueInliner;
|
||||
Int32ValueInliner int32ValueInliner;
|
||||
UInt32ValueInliner uint32ValueInliner;
|
||||
Int64ValueInliner int64ValueInliner;
|
||||
UInt64ValueInliner uint64ValueInliner;
|
||||
SingleValueInliner singleValueInliner;
|
||||
DoubleValueInliner doubleValueInliner;
|
||||
ArrayValueInliner arrayValueInliner;
|
||||
|
||||
#endregion
|
||||
|
||||
internal class Options : OptionsBase
|
||||
{
|
||||
}
|
||||
|
||||
public override string Type
|
||||
{
|
||||
get { return DeobfuscatorInfo.THE_TYPE; }
|
||||
}
|
||||
|
||||
public override string TypeLong
|
||||
{
|
||||
get { return DeobfuscatorInfo.THE_NAME; }
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return $"{TypeLong} {_version}"; }
|
||||
}
|
||||
private ResourceDecrypter _resourceDecrypter;
|
||||
private string _version = "";
|
||||
|
||||
public Deobfuscator(Options options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Type => THE_TYPE;
|
||||
public override string TypeLong => THE_NAME;
|
||||
public override string Name => $"{TypeLong} {_version}";
|
||||
|
||||
public override IEnumerable<IBlocksDeobfuscator> BlocksDeobfuscators
|
||||
{
|
||||
get
|
||||
{
|
||||
var list = new List<IBlocksDeobfuscator>();
|
||||
list.Add(_controlFlowFixer);
|
||||
|
||||
if (_deobfuscating && _int32ValueInliner != null)
|
||||
list.Add(new ConstantsInliner(_sbyteValueInliner, _byteValueInliner, _int16ValueInliner,
|
||||
_uint16ValueInliner,
|
||||
_int32ValueInliner, _uint32ValueInliner, _int64ValueInliner, _uint64ValueInliner,
|
||||
_singleValueInliner, _doubleValueInliner, _arrayValueInliner)
|
||||
{ExecuteIfNotModified = true});
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
protected override int DetectInternal()
|
||||
{
|
||||
int val = 0;
|
||||
var val = 0;
|
||||
if (_detectedConfuserExAttribute) val += 0;
|
||||
if (_lzmaFinder.FoundLzma) val += 10;
|
||||
if (_constantDecrypter.Detected) val += 10;
|
||||
|
@ -137,7 +117,6 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
|
||||
private void DetectConfuserExAttribute()
|
||||
{
|
||||
var versions = new List<string>();
|
||||
foreach (var attribute in module.CustomAttributes)
|
||||
{
|
||||
if (attribute.TypeFullName != "ConfusedByAttribute")
|
||||
|
@ -160,81 +139,64 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
{
|
||||
if (_constantDecrypter.Detected)
|
||||
{
|
||||
Logger.w("Constants encryption detected! Please note that the decryption method has to be set manually!"); //TODO: Remove
|
||||
Logger.w(
|
||||
"Constants encryption detected! Please note that the decryption method has to be set manually!"); //TODO: Remove
|
||||
|
||||
sbyteValueInliner = new SByteValueInliner();
|
||||
byteValueInliner = new ByteValueInliner();
|
||||
int16ValueInliner = new Int16ValueInliner();
|
||||
uint16ValueInliner = new UInt16ValueInliner();
|
||||
int32ValueInliner = new Int32ValueInliner();
|
||||
uint32ValueInliner = new UInt32ValueInliner();
|
||||
int64ValueInliner = new Int64ValueInliner();
|
||||
uint64ValueInliner = new UInt64ValueInliner();
|
||||
singleValueInliner = new SingleValueInliner();
|
||||
doubleValueInliner = new DoubleValueInliner();
|
||||
arrayValueInliner = new ArrayValueInliner(initializedDataCreator);
|
||||
_sbyteValueInliner = new SByteValueInliner();
|
||||
_byteValueInliner = new ByteValueInliner();
|
||||
_int16ValueInliner = new Int16ValueInliner();
|
||||
_uint16ValueInliner = new UInt16ValueInliner();
|
||||
_int32ValueInliner = new Int32ValueInliner();
|
||||
_uint32ValueInliner = new UInt32ValueInliner();
|
||||
_int64ValueInliner = new Int64ValueInliner();
|
||||
_uint64ValueInliner = new UInt64ValueInliner();
|
||||
_singleValueInliner = new SingleValueInliner();
|
||||
_doubleValueInliner = new DoubleValueInliner();
|
||||
_arrayValueInliner = new ArrayValueInliner(initializedDataCreator);
|
||||
foreach (var info in _constantDecrypter.Decrypters)
|
||||
{
|
||||
staticStringInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptString(info, gim, (uint) args[0]));
|
||||
sbyteValueInliner.Add(info.Method,
|
||||
_sbyteValueInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptSByte(info, gim, (uint) args[0]));
|
||||
byteValueInliner.Add(info.Method,
|
||||
_byteValueInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptByte(info, gim, (uint) args[0]));
|
||||
int16ValueInliner.Add(info.Method,
|
||||
_int16ValueInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptInt16(info, gim, (uint) args[0]));
|
||||
uint16ValueInliner.Add(info.Method,
|
||||
_uint16ValueInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptUInt16(info, gim, (uint) args[0]));
|
||||
int32ValueInliner.Add(info.Method,
|
||||
_int32ValueInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptInt32(info, gim, (uint) args[0]));
|
||||
uint32ValueInliner.Add(info.Method,
|
||||
_uint32ValueInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptUInt32(info, gim, (uint) args[0]));
|
||||
int64ValueInliner.Add(info.Method,
|
||||
_int64ValueInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptInt64(info, gim, (uint) args[0]));
|
||||
uint64ValueInliner.Add(info.Method,
|
||||
_uint64ValueInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptUInt64(info, gim, (uint) args[0]));
|
||||
singleValueInliner.Add(info.Method,
|
||||
_singleValueInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptSingle(info, gim, (uint) args[0]));
|
||||
doubleValueInliner.Add(info.Method,
|
||||
_doubleValueInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptDouble(info, gim, (uint) args[0]));
|
||||
arrayValueInliner.Add(info.Method,
|
||||
_arrayValueInliner.Add(info.Method,
|
||||
(method, gim, args) => _constantDecrypter.DecryptArray(info, gim, (uint) args[0]));
|
||||
}
|
||||
_deobfuscating = true;
|
||||
}
|
||||
if (_resourceDecrypter.Detected)
|
||||
{
|
||||
Logger.w("Resource encryption detected! Please note that the decryption method has to be set manually!"); //TODO: Remove
|
||||
Logger.w(
|
||||
"Resource encryption detected! Please note that the decryption method has to be set manually!"); //TODO: Remove
|
||||
_resourceDecrypter.Fix();
|
||||
}
|
||||
|
||||
base.DeobfuscateBegin();
|
||||
}
|
||||
|
||||
public override IEnumerable<IBlocksDeobfuscator> BlocksDeobfuscators
|
||||
{
|
||||
get
|
||||
{
|
||||
var list = new List<IBlocksDeobfuscator>();
|
||||
list.Add(_controlFlowFixer);
|
||||
|
||||
if (_deobfuscating && int32ValueInliner != null)
|
||||
list.Add(new ConstantsInliner(sbyteValueInliner, byteValueInliner, int16ValueInliner,
|
||||
uint16ValueInliner,
|
||||
int32ValueInliner, uint32ValueInliner, int64ValueInliner, uint64ValueInliner,
|
||||
singleValueInliner, doubleValueInliner, arrayValueInliner)
|
||||
{ExecuteIfNotModified = true});
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
bool _canRemoveLzma = true;
|
||||
|
||||
public override void DeobfuscateEnd()
|
||||
{
|
||||
FindAndRemoveInlinedMethods();
|
||||
|
||||
List<MethodDef> toRemoveFromCctor = new List<MethodDef>();
|
||||
var toRemoveFromCctor = new List<MethodDef>();
|
||||
|
||||
if (_constantDecrypter.Detected)
|
||||
if (CanRemoveStringDecrypterType)
|
||||
|
@ -247,7 +209,9 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
AddTypeToBeRemoved(_constantDecrypter.Type, "Array field signature type");
|
||||
}
|
||||
else
|
||||
{
|
||||
_canRemoveLzma = false;
|
||||
}
|
||||
|
||||
if (_resourceDecrypter.Detected && _resourceDecrypter.CanRemoveLzma)
|
||||
{
|
||||
|
@ -275,13 +239,13 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
AddTypesToBeRemoved(_proxyCallFixer.AttributeTypes, "Proxy creator attributes");
|
||||
AddMethodsToBeRemoved(_proxyCallFixer.NativeMethods, "Proxy native methods");
|
||||
}
|
||||
|
||||
|
||||
AddMethodsToBeRemoved(_controlFlowFixer.NativeMethods, "Control flow native methods");
|
||||
|
||||
var moduleCctor = DotNetUtils.GetModuleTypeCctor(module);
|
||||
foreach (var instr in moduleCctor.Body.Instructions)
|
||||
if (instr.OpCode == OpCodes.Call && instr.Operand is MethodDef &&
|
||||
toRemoveFromCctor.Contains(instr.Operand as MethodDef))
|
||||
toRemoveFromCctor.Contains((MethodDef) instr.Operand))
|
||||
instr.OpCode = OpCodes.Nop;
|
||||
|
||||
//No more mixed!
|
||||
|
@ -292,8 +256,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
|
||||
public override IEnumerable<int> GetStringDecrypterMethods()
|
||||
{
|
||||
var list = new List<int>();
|
||||
return list;
|
||||
return new List<int>();
|
||||
}
|
||||
|
||||
public override void DeobfuscateMethodEnd(Blocks blocks)
|
||||
|
@ -301,6 +264,26 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
_proxyCallFixer.Deobfuscate(blocks);
|
||||
base.DeobfuscateMethodEnd(blocks);
|
||||
}
|
||||
|
||||
internal class Options : OptionsBase
|
||||
{
|
||||
}
|
||||
|
||||
#region ConstantInliners
|
||||
|
||||
private SByteValueInliner _sbyteValueInliner;
|
||||
private ByteValueInliner _byteValueInliner;
|
||||
private Int16ValueInliner _int16ValueInliner;
|
||||
private UInt16ValueInliner _uint16ValueInliner;
|
||||
private Int32ValueInliner _int32ValueInliner;
|
||||
private UInt32ValueInliner _uint32ValueInliner;
|
||||
private Int64ValueInliner _int64ValueInliner;
|
||||
private UInt64ValueInliner _uint64ValueInliner;
|
||||
private SingleValueInliner _singleValueInliner;
|
||||
private DoubleValueInliner _doubleValueInliner;
|
||||
private ArrayValueInliner _arrayValueInliner;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +1,32 @@
|
|||
using de4dot.blocks;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using de4dot.blocks;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace de4dot.code.deobfuscators.ConfuserEx
|
||||
{
|
||||
public class LzmaFinder
|
||||
{
|
||||
MethodDef decompressMethod;
|
||||
List<TypeDef> types = new List<TypeDef>();
|
||||
private readonly ISimpleDeobfuscator _deobfuscator;
|
||||
|
||||
public MethodDef Method
|
||||
{
|
||||
get { return decompressMethod; }
|
||||
}
|
||||
public List<TypeDef> Types
|
||||
{
|
||||
get { return types; }
|
||||
}
|
||||
public bool FoundLzma
|
||||
{
|
||||
get { return decompressMethod != null && types.Count != 0; }
|
||||
}
|
||||
private readonly ModuleDef _module;
|
||||
|
||||
ModuleDef module;
|
||||
ISimpleDeobfuscator deobfuscator;
|
||||
public LzmaFinder(ModuleDef module, ISimpleDeobfuscator deobfuscator)
|
||||
{
|
||||
this.module = module;
|
||||
this.deobfuscator = deobfuscator;
|
||||
this._module = module;
|
||||
this._deobfuscator = deobfuscator;
|
||||
}
|
||||
|
||||
public MethodDef Method { get; private set; }
|
||||
|
||||
public List<TypeDef> Types { get; } = new List<TypeDef>();
|
||||
|
||||
public bool FoundLzma => Method != null && Types.Count != 0;
|
||||
|
||||
public void Find()
|
||||
{
|
||||
var moduleType = DotNetUtils.GetModuleType(module);
|
||||
var moduleType = DotNetUtils.GetModuleType(_module);
|
||||
if (moduleType == null)
|
||||
return;
|
||||
foreach (var method in moduleType.Methods)
|
||||
|
@ -45,11 +35,11 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
continue;
|
||||
if (!DotNetUtils.IsMethod(method, "System.Byte[]", "(System.Byte[])"))
|
||||
continue;
|
||||
deobfuscator.Deobfuscate(method, SimpleDeobfuscatorFlags.Force);
|
||||
_deobfuscator.Deobfuscate(method, SimpleDeobfuscatorFlags.Force);
|
||||
if (!IsLzmaMethod(method))
|
||||
continue;
|
||||
decompressMethod = method;
|
||||
var type = ((MethodDef)method.Body.Instructions[3].Operand).DeclaringType;
|
||||
Method = method;
|
||||
var type = ((MethodDef) method.Body.Instructions[3].Operand).DeclaringType;
|
||||
ExtractNestedTypes(type);
|
||||
}
|
||||
}
|
||||
|
@ -62,14 +52,14 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return false;
|
||||
|
||||
var firstInstruction = instructions.FirstOrDefault(
|
||||
instr =>
|
||||
instr.OpCode == OpCodes.Newobj &&
|
||||
instr.Operand.ToString() == "System.Void System.IO.MemoryStream::.ctor(System.Byte[])");
|
||||
instr =>
|
||||
instr.OpCode == OpCodes.Newobj &&
|
||||
instr.Operand.ToString() == "System.Void System.IO.MemoryStream::.ctor(System.Byte[])");
|
||||
|
||||
if (firstInstruction == null)
|
||||
return false;
|
||||
|
||||
int i = instructions.IndexOf(firstInstruction) + 1;
|
||||
var i = instructions.IndexOf(firstInstruction) + 1;
|
||||
|
||||
if (!instructions[i++].IsStloc())
|
||||
return false;
|
||||
|
@ -82,7 +72,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return false;
|
||||
if (instructions[i++].OpCode != OpCodes.Newarr)
|
||||
return false;
|
||||
if (!instructions[i++].IsStloc()) //byte[] buffer = new byte[5];
|
||||
if (!instructions[i++].IsStloc()) //byte[] buffer = new byte[5];
|
||||
return false;
|
||||
|
||||
if (!instructions[i++].IsLdloc())
|
||||
|
@ -93,16 +83,17 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return false;
|
||||
if (!instructions[i].IsLdcI4() || instructions[i++].GetLdcI4Value() != 5)
|
||||
return false;
|
||||
if (instructions[i].OpCode != OpCodes.Callvirt || instructions[i++].Operand.ToString() != "System.Int32 System.IO.Stream::Read(System.Byte[],System.Int32,System.Int32)")
|
||||
if (instructions[i].OpCode != OpCodes.Callvirt || instructions[i++].Operand.ToString() !=
|
||||
"System.Int32 System.IO.Stream::Read(System.Byte[],System.Int32,System.Int32)")
|
||||
return false;
|
||||
if (instructions[i++].OpCode != OpCodes.Pop) //memoryStream.Read(buffer, 0, 5);
|
||||
if (instructions[i++].OpCode != OpCodes.Pop) //memoryStream.Read(buffer, 0, 5);
|
||||
return false;
|
||||
|
||||
if (!instructions[i++].IsLdloc())
|
||||
return false;
|
||||
if (!instructions[i++].IsLdloc())
|
||||
return false;
|
||||
if (instructions[i++].OpCode != OpCodes.Callvirt) //@class.method_5(buffer);
|
||||
if (instructions[i++].OpCode != OpCodes.Callvirt) //@class.method_5(buffer);
|
||||
return false;
|
||||
|
||||
firstInstruction =
|
||||
|
@ -118,7 +109,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
|
||||
i = instructions.IndexOf(firstInstruction) + 1;
|
||||
|
||||
if (!instructions[i++].IsStloc()) //int num2 = memoryStream.ReadByte();
|
||||
if (!instructions[i++].IsStloc()) //int num2 = memoryStream.ReadByte();
|
||||
return false;
|
||||
|
||||
if (!instructions[i++].IsLdloc())
|
||||
|
@ -143,14 +134,15 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return false;
|
||||
if (instructions[i++].OpCode != OpCodes.Or)
|
||||
return false;
|
||||
if (!instructions[i++].IsStloc()) //num |= (long)((long)((ulong)((byte)num2)) << 8 * i);
|
||||
if (!instructions[i++].IsStloc()) //num |= (long)((long)((ulong)((byte)num2)) << 8 * i);
|
||||
return false;
|
||||
|
||||
firstInstruction =
|
||||
instructions.FirstOrDefault(
|
||||
instr =>
|
||||
instr.OpCode == OpCodes.Newobj &&
|
||||
instr.Operand.ToString() == "System.Void System.IO.MemoryStream::.ctor(System.Byte[],System.Boolean)");
|
||||
instr.Operand.ToString() ==
|
||||
"System.Void System.IO.MemoryStream::.ctor(System.Byte[],System.Boolean)");
|
||||
|
||||
if (firstInstruction == null)
|
||||
return false;
|
||||
|
@ -159,22 +151,24 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
|
||||
i = instructions.IndexOf(firstInstruction) + 1;
|
||||
|
||||
if (!instructions[i++].IsStloc()) //MemoryStream stream_ = new MemoryStream(array, true);
|
||||
if (!instructions[i++].IsStloc()) //MemoryStream stream_ = new MemoryStream(array, true);
|
||||
return false;
|
||||
|
||||
if (!instructions[i++].IsLdloc())
|
||||
return false;
|
||||
if (instructions[i].OpCode != OpCodes.Callvirt || instructions[i++].Operand.ToString() != "System.Int64 System.IO.Stream::get_Length()")
|
||||
if (instructions[i].OpCode != OpCodes.Callvirt || instructions[i++].Operand.ToString() !=
|
||||
"System.Int64 System.IO.Stream::get_Length()")
|
||||
return false;
|
||||
if (instructions[i].OpCode != OpCodes.Ldc_I8 || (long)instructions[i++].Operand != 13L)
|
||||
if (instructions[i].OpCode != OpCodes.Ldc_I8 || (long) instructions[i++].Operand != 13L)
|
||||
return false;
|
||||
if (instructions[i++].OpCode != OpCodes.Sub)
|
||||
return false;
|
||||
if (!instructions[i++].IsStloc()) //long long_ = memoryStream.Length - 13L;
|
||||
if (!instructions[i++].IsStloc()) //long long_ = memoryStream.Length - 13L;
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ExtractNestedTypes(TypeDef type)
|
||||
{
|
||||
foreach (var method in type.Methods)
|
||||
|
@ -187,9 +181,9 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
var ntype = (inst.Operand as MethodDef).DeclaringType;
|
||||
if (!ntype.IsNested)
|
||||
continue;
|
||||
if (types.Contains(ntype))
|
||||
if (Types.Contains(ntype))
|
||||
continue;
|
||||
types.Add(ntype);
|
||||
Types.Add(ntype);
|
||||
ExtractNestedTypes(ntype);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
|
@ -11,29 +9,28 @@ using dnlib.DotNet.Emit;
|
|||
|
||||
namespace de4dot.code.deobfuscators.ConfuserEx
|
||||
{
|
||||
class Context
|
||||
internal class Context
|
||||
{
|
||||
public uint FieldToken;
|
||||
public int ByteNum;
|
||||
public MethodDef CreateMethod;
|
||||
public uint FieldToken;
|
||||
|
||||
public Context(uint fieldToken, int byteNum, MethodDef createMethod)
|
||||
{
|
||||
this.FieldToken = fieldToken;
|
||||
this.ByteNum = byteNum; // 2nd parameter of the Delegate CreateMethod
|
||||
this.CreateMethod = createMethod;
|
||||
FieldToken = fieldToken;
|
||||
ByteNum = byteNum; // 2nd parameter of the Delegate CreateMethod
|
||||
CreateMethod = createMethod;
|
||||
}
|
||||
}
|
||||
|
||||
class ProxyCallFixer : ProxyCallFixer4
|
||||
internal class ProxyCallFixer : ProxyCallFixer4
|
||||
{
|
||||
public List<MethodDef> NativeMethods = new List<MethodDef>();
|
||||
private readonly InstructionEmulator _instructionEmulator = new InstructionEmulator();
|
||||
private readonly List<MethodDef> _processedMethods = new List<MethodDef>();
|
||||
private readonly ISimpleDeobfuscator _simpleDeobfuscator;
|
||||
public List<TypeDef> AttributeTypes = new List<TypeDef>();
|
||||
public List<MethodDef> DelegateCreatorMethods = new List<MethodDef>();
|
||||
|
||||
private readonly InstructionEmulator _instructionEmulator = new InstructionEmulator();
|
||||
private readonly ISimpleDeobfuscator _simpleDeobfuscator;
|
||||
private readonly List<MethodDef> _processedMethods = new List<MethodDef>();
|
||||
public List<MethodDef> NativeMethods = new List<MethodDef>();
|
||||
|
||||
public ProxyCallFixer(ModuleDefMD module, ISimpleDeobfuscator simpleDeobfuscator) : base(module)
|
||||
{
|
||||
|
@ -52,20 +49,21 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
_processedMethods.Add(cctor);
|
||||
}
|
||||
|
||||
List<Context> contexts = new List<Context>();
|
||||
var contexts = new List<Context>();
|
||||
var instructions = cctor.Body.Instructions;
|
||||
instructions.SimplifyMacros(cctor.Body.Variables, cctor.Parameters);
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
for (var i = 0; i < instructions.Count; i++)
|
||||
{
|
||||
var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldtoken, OpCodes.Ldc_I4, OpCodes.Call);
|
||||
var instrs =
|
||||
DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldtoken, OpCodes.Ldc_I4, OpCodes.Call);
|
||||
if (instrs == null)
|
||||
continue;
|
||||
|
||||
uint fieldToken = ((IField) instrs[0].Operand).MDToken.ToUInt32();
|
||||
int byteNum = (int)instrs[1].Operand;
|
||||
var fieldToken = ((IField) instrs[0].Operand).MDToken.ToUInt32();
|
||||
var byteNum = (int) instrs[1].Operand;
|
||||
var createMethod = instrs[2].Operand as MethodDef;
|
||||
|
||||
if(!DelegateCreatorMethods.Contains(createMethod))
|
||||
if (!DelegateCreatorMethods.Contains(createMethod))
|
||||
DelegateCreatorMethods.Add(createMethod);
|
||||
|
||||
contexts.Add(new Context(fieldToken, byteNum, createMethod));
|
||||
|
@ -84,7 +82,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
|
||||
private byte[] GetExtraDataToken(byte[] sigData)
|
||||
{
|
||||
byte[] extraData = new byte[4];
|
||||
var extraData = new byte[4];
|
||||
|
||||
// [original signature] [extra signature]
|
||||
// ... X C0 X X X
|
||||
|
@ -94,11 +92,14 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return extraData;
|
||||
}
|
||||
|
||||
protected override void GetCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode)
|
||||
protected override void GetCallInfo(object context, FieldDef field, out IMethod calledMethod,
|
||||
out OpCode callOpcode)
|
||||
{
|
||||
var contexts = (List<Context>) context;
|
||||
var ctx = contexts.First(c => c.FieldToken == field.MDToken.ToInt32());
|
||||
var originalMethod = DotNetUtils.Clone(ctx.CreateMethod); // backup original method and restore because changes are not universal
|
||||
var originalMethod =
|
||||
DotNetUtils.Clone(ctx
|
||||
.CreateMethod); // backup original method and restore because changes are not universal
|
||||
DeobfuscateIfNeeded(ctx.CreateMethod);
|
||||
|
||||
var instructions = ctx.CreateMethod.Body.Instructions;
|
||||
|
@ -106,32 +107,32 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
var parameters = ctx.CreateMethod.Parameters;
|
||||
|
||||
instructions.SimplifyMacros(variables, parameters);
|
||||
byte[] sigData = module.ReadBlob(ctx.FieldToken);
|
||||
byte[] extraDataToken = GetExtraDataToken(sigData);
|
||||
int modifierMDToken = ((CModOptSig)field.FieldType).Modifier.MDToken.ToInt32();
|
||||
var sigData = module.ReadBlob(ctx.FieldToken);
|
||||
var extraDataToken = GetExtraDataToken(sigData);
|
||||
var modifierMDToken = ((CModOptSig) field.FieldType).Modifier.MDToken.ToInt32();
|
||||
|
||||
ReplaceMetadataToken(ref instructions, modifierMDToken, variables[0]);
|
||||
ReplaceFieldNameChars(ref instructions, field.Name, variables[0]);
|
||||
InlineArrays(ref instructions, extraDataToken, variables[1], variables[2]);
|
||||
RemoveDecrementorBlock(ref instructions, variables[2]);
|
||||
|
||||
int firstInstruction = GetEmulationStartIndex(instructions, variables[1], variables[2]);
|
||||
int lastInstruction =
|
||||
var firstInstruction = GetEmulationStartIndex(instructions, variables[1], variables[2]);
|
||||
var lastInstruction =
|
||||
instructions.IndexOf(
|
||||
instructions.First(
|
||||
i => i.OpCode == OpCodes.Callvirt && i.Operand.ToString().Contains("GetCustomAttributes"))) - 4;
|
||||
|
||||
bool nativeMode = false;
|
||||
var nativeMode = false;
|
||||
if (instructions[lastInstruction - 1].OpCode == OpCodes.Call) // x86 protection
|
||||
{
|
||||
lastInstruction--; // don't try emulating native method
|
||||
nativeMode = true;
|
||||
}
|
||||
|
||||
int result = EmulateManagedMethod(ctx.CreateMethod, firstInstruction, lastInstruction);
|
||||
var result = EmulateManagedMethod(ctx.CreateMethod, firstInstruction, lastInstruction);
|
||||
if (nativeMode)
|
||||
{
|
||||
MethodDef nativeMethod = (MethodDef) instructions[lastInstruction].Operand;
|
||||
var nativeMethod = (MethodDef) instructions[lastInstruction].Operand;
|
||||
if (!NativeMethods.Contains(nativeMethod))
|
||||
NativeMethods.Add(nativeMethod);
|
||||
result = EmulateNativeMethod(nativeMethod, result);
|
||||
|
@ -140,10 +141,10 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
result *= GetMagicNumber(field.CustomAttributes[0]);
|
||||
calledMethod = module.ResolveMemberRef(new MDToken(result).Rid);
|
||||
|
||||
if(calledMethod == null)
|
||||
if (calledMethod == null)
|
||||
throw new Exception();
|
||||
|
||||
int charNum = GetCharNum(instructions, parameters.Last());
|
||||
var charNum = GetCharNum(instructions, parameters.Last());
|
||||
callOpcode = GetCallOpCode(calledMethod, charNum, ctx.ByteNum);
|
||||
|
||||
ctx.CreateMethod.Body = originalMethod.Body; // restore
|
||||
|
@ -151,20 +152,17 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
|
||||
private OpCode GetCallOpCode(IMethod calledMethod, int charNum, int byteNum)
|
||||
{
|
||||
if (calledMethod.ResolveMethodDef().IsStatic) {
|
||||
return OpCodes.Call;
|
||||
}
|
||||
if (calledMethod.ResolveMethodDef().IsStatic) return OpCodes.Call;
|
||||
|
||||
byte charOpCode = (byte)(charNum ^ byteNum);
|
||||
var charOpCode = (byte) (charNum ^ byteNum);
|
||||
|
||||
if (charOpCode == 0x28)
|
||||
return OpCodes.Call;
|
||||
else if (charOpCode == 0x6F)
|
||||
if (charOpCode == 0x6F)
|
||||
return OpCodes.Callvirt;
|
||||
else if (charOpCode == 0x73)
|
||||
if (charOpCode == 0x73)
|
||||
return OpCodes.Newobj;
|
||||
else
|
||||
throw new Exception();
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
private int EmulateNativeMethod(MethodDef externalMethod, int parameter)
|
||||
|
@ -173,29 +171,28 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return nativeMethod.Execute(parameter);
|
||||
}
|
||||
|
||||
private int EmulateManagedMethod(MethodDef method, int startIndex, int endIndex, params Tuple<Parameter, int>[] parameters)
|
||||
private int EmulateManagedMethod(MethodDef method, int startIndex, int endIndex,
|
||||
params Tuple<Parameter, int>[] parameters)
|
||||
{
|
||||
_instructionEmulator.Initialize(method, false);
|
||||
foreach(var parameter in parameters)
|
||||
foreach (var parameter in parameters)
|
||||
_instructionEmulator.SetArg(parameter.Item1, new Int32Value(parameter.Item2));
|
||||
|
||||
for (int i = startIndex; i < endIndex; i++) {
|
||||
_instructionEmulator.Emulate(method.Body.Instructions[i]);
|
||||
}
|
||||
for (var i = startIndex; i < endIndex; i++) _instructionEmulator.Emulate(method.Body.Instructions[i]);
|
||||
|
||||
return ((Int32Value) _instructionEmulator.Pop()).Value;
|
||||
}
|
||||
|
||||
private int GetMagicNumber(CustomAttribute customAttribute)
|
||||
{
|
||||
TypeDef attributeType = customAttribute.AttributeType.ResolveTypeDef();
|
||||
if(!AttributeTypes.Contains(attributeType))
|
||||
var attributeType = customAttribute.AttributeType.ResolveTypeDef();
|
||||
if (!AttributeTypes.Contains(attributeType))
|
||||
AttributeTypes.Add(attributeType);
|
||||
|
||||
var ctor = attributeType.FindConstructors().First();
|
||||
DeobfuscateIfNeeded(ctor);
|
||||
|
||||
int magicNum = Convert.ToInt32(customAttribute.ConstructorArguments[0].Value);
|
||||
var magicNum = Convert.ToInt32(customAttribute.ConstructorArguments[0].Value);
|
||||
var parameter = new Tuple<Parameter, int>();
|
||||
parameter.Item1 = ctor.Parameters[1];
|
||||
parameter.Item2 = magicNum;
|
||||
|
@ -225,7 +222,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
0x000005C6 FE0E0200 IL_002E: stloc.2 */
|
||||
private int GetEmulationStartIndex(IList<Instruction> instructions, Local localArray, Local localArraySize)
|
||||
{
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
for (var i = 0; i < instructions.Count; i++)
|
||||
{
|
||||
var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Callvirt, OpCodes.Stloc,
|
||||
OpCodes.Ldloc, OpCodes.Ldlen, OpCodes.Conv_I4, OpCodes.Stloc);
|
||||
|
@ -234,11 +231,11 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
continue;
|
||||
if (!instrs[0].Operand.ToString().Contains("ResolveSignature"))
|
||||
continue;
|
||||
if ((Local)instrs[1].Operand != localArray)
|
||||
if ((Local) instrs[1].Operand != localArray)
|
||||
continue;
|
||||
if ((Local)instrs[2].Operand != localArray)
|
||||
if ((Local) instrs[2].Operand != localArray)
|
||||
continue;
|
||||
if ((Local)instrs[5].Operand != localArraySize)
|
||||
if ((Local) instrs[5].Operand != localArraySize)
|
||||
continue;
|
||||
|
||||
return i + 6;
|
||||
|
@ -250,7 +247,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
0x000008F4 61 IL_02BC: xor */
|
||||
private int GetCharNum(IList<Instruction> instructions, Parameter byteParam)
|
||||
{
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
for (var i = 0; i < instructions.Count; i++)
|
||||
{
|
||||
var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldarg, OpCodes.Xor);
|
||||
|
||||
|
@ -268,7 +265,8 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
private void ReplaceFieldNameChars(ref IList<Instruction> instructions, string fieldName, Local fieldLocal)
|
||||
{
|
||||
bool foundInstrs;
|
||||
do {
|
||||
do
|
||||
{
|
||||
foundInstrs = ReplaceFieldNameChar(ref instructions, fieldName, fieldLocal);
|
||||
} while (foundInstrs);
|
||||
}
|
||||
|
@ -279,28 +277,28 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
0x0000037C 6F1600000A IL_0084: callvirt */
|
||||
private bool ReplaceFieldNameChar(ref IList<Instruction> instructions, string fieldName, Local fieldLocal)
|
||||
{
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
for (var i = 0; i < instructions.Count; i++)
|
||||
{
|
||||
var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldloc, OpCodes.Callvirt,
|
||||
OpCodes.Ldc_I4, OpCodes.Callvirt);
|
||||
|
||||
if(instrs == null)
|
||||
if (instrs == null)
|
||||
continue;
|
||||
if ((Local)instrs[0].Operand != fieldLocal)
|
||||
if ((Local) instrs[0].Operand != fieldLocal)
|
||||
continue;
|
||||
if (!instrs[1].Operand.ToString().Contains("get_Name"))
|
||||
continue;
|
||||
if (!instrs[3].Operand.ToString().Contains("get_Chars"))
|
||||
continue;
|
||||
|
||||
int charIndex = (int)instrs[2].Operand;
|
||||
var charIndex = (int) instrs[2].Operand;
|
||||
int @char = fieldName[charIndex];
|
||||
|
||||
instructions[i].OpCode = OpCodes.Ldc_I4;
|
||||
instructions[i].Operand = @char;
|
||||
instructions[i+1].OpCode = OpCodes.Nop;
|
||||
instructions[i+2].OpCode = OpCodes.Nop;
|
||||
instructions[i+3].OpCode = OpCodes.Nop;
|
||||
instructions[i + 1].OpCode = OpCodes.Nop;
|
||||
instructions[i + 2].OpCode = OpCodes.Nop;
|
||||
instructions[i + 3].OpCode = OpCodes.Nop;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -315,28 +313,29 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
private void InlineArrays(ref IList<Instruction> instructions, byte[] values, Local localArray, Local localInt)
|
||||
{
|
||||
bool foundInstrs;
|
||||
int i = 0;
|
||||
do {
|
||||
var i = 0;
|
||||
do
|
||||
{
|
||||
foundInstrs = InlineArray(ref instructions, values[i++], localArray, localInt);
|
||||
} while (i < 4 && foundInstrs);
|
||||
}
|
||||
|
||||
private bool InlineArray(ref IList<Instruction> instructions, int value, Local localArray, Local localInt)
|
||||
{
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
for (var i = 0; i < instructions.Count; i++)
|
||||
{
|
||||
var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldloc, OpCodes.Ldloc, OpCodes.Ldc_I4,
|
||||
OpCodes.Sub, OpCodes.Dup, OpCodes.Stloc, OpCodes.Ldelem_U1);
|
||||
|
||||
if (instrs == null)
|
||||
continue;
|
||||
if ((Local)instrs[0].Operand != localArray)
|
||||
if ((Local) instrs[0].Operand != localArray)
|
||||
continue;
|
||||
if ((Local)instrs[1].Operand != localInt)
|
||||
if ((Local) instrs[1].Operand != localInt)
|
||||
continue;
|
||||
if ((int)instrs[2].Operand != 1)
|
||||
if ((int) instrs[2].Operand != 1)
|
||||
continue;
|
||||
if ((Local)instrs[5].Operand != localInt)
|
||||
if ((Local) instrs[5].Operand != localInt)
|
||||
continue;
|
||||
|
||||
instructions[i].OpCode = OpCodes.Ldc_I4;
|
||||
|
@ -358,17 +357,18 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
0x00000374 0C IL_007C: stloc.2 */
|
||||
private void RemoveDecrementorBlock(ref IList<Instruction> instructions, Local localInt)
|
||||
{
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
for (var i = 0; i < instructions.Count; i++)
|
||||
{
|
||||
var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldloc, OpCodes.Ldc_I4, OpCodes.Sub, OpCodes.Stloc);
|
||||
var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldloc, OpCodes.Ldc_I4, OpCodes.Sub,
|
||||
OpCodes.Stloc);
|
||||
|
||||
if (instrs == null)
|
||||
continue;
|
||||
if ((Local)instrs[0].Operand != localInt)
|
||||
continue;
|
||||
if ((int)instrs[1].Operand != 1)
|
||||
if ((Local) instrs[0].Operand != localInt)
|
||||
continue;
|
||||
if ((Local)instrs[3].Operand != localInt)
|
||||
if ((int) instrs[1].Operand != 1)
|
||||
continue;
|
||||
if ((Local) instrs[3].Operand != localInt)
|
||||
continue;
|
||||
|
||||
instructions[i].OpCode = OpCodes.Nop;
|
||||
|
@ -386,18 +386,19 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
0x000005DE 6F1400000A IL_0046: callvirt instance int32[mscorlib] System.Reflection.MemberInfo::get_MetadataToken() */
|
||||
private void ReplaceMetadataToken(ref IList<Instruction> instructions, int metadataToken, Local fieldLocal)
|
||||
{
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
for (var i = 0; i < instructions.Count; i++)
|
||||
{
|
||||
var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldloc, OpCodes.Callvirt, OpCodes.Ldc_I4,
|
||||
var instrs = DotNetUtils.GetInstructions(instructions, i, OpCodes.Ldloc, OpCodes.Callvirt,
|
||||
OpCodes.Ldc_I4,
|
||||
OpCodes.Ldelem_Ref, OpCodes.Callvirt);
|
||||
|
||||
if (instrs == null)
|
||||
continue;
|
||||
if ((Local)instrs[0].Operand != fieldLocal)
|
||||
if ((Local) instrs[0].Operand != fieldLocal)
|
||||
continue;
|
||||
if (!instrs[1].Operand.ToString().Contains("GetOptionalCustomModifiers"))
|
||||
continue;
|
||||
if ((int)instrs[2].Operand != 0)
|
||||
if ((int) instrs[2].Operand != 0)
|
||||
continue;
|
||||
if (!instrs[4].Operand.ToString().Contains("get_MetadataToken"))
|
||||
continue;
|
||||
|
@ -412,4 +413,4 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,65 +1,41 @@
|
|||
using de4dot.blocks;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using de4dot.blocks;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.code.deobfuscators.ConfuserEx
|
||||
{
|
||||
public class ResourceDecrypter
|
||||
{
|
||||
TypeDef arrayType;
|
||||
MethodDef resourceDecInitMethod, assembyResolveMethod;
|
||||
FieldDef arrayField, asmField;
|
||||
byte[] decryptedBytes;
|
||||
private FieldDef _arrayField, _asmField;
|
||||
|
||||
bool canRemoveLzma = true;
|
||||
private byte[] _decryptedBytes;
|
||||
private readonly ISimpleDeobfuscator _deobfuscator;
|
||||
private readonly MethodDef _lzmaMethod;
|
||||
|
||||
public bool CanRemoveLzma
|
||||
{
|
||||
get { return canRemoveLzma; }
|
||||
}
|
||||
private readonly ModuleDef _module;
|
||||
|
||||
public TypeDef Type
|
||||
{
|
||||
get { return arrayType; }
|
||||
}
|
||||
public MethodDef Method
|
||||
{
|
||||
get { return resourceDecInitMethod; }
|
||||
}
|
||||
public MethodDef AssembyResolveMethod
|
||||
{
|
||||
get { return assembyResolveMethod; }
|
||||
}
|
||||
public List<FieldDef> Fields
|
||||
{
|
||||
get { return new List<FieldDef>() { arrayField, asmField }; }
|
||||
}
|
||||
public bool Detected
|
||||
{
|
||||
get
|
||||
{
|
||||
return resourceDecInitMethod != null && resourceDecInitMethod != null
|
||||
&& decryptedBytes != null && arrayField != null && asmField != null;
|
||||
}
|
||||
}
|
||||
|
||||
ModuleDef module;
|
||||
MethodDef lzmaMethod;
|
||||
ISimpleDeobfuscator deobfuscator;
|
||||
public ResourceDecrypter(ModuleDef module, MethodDef lzmaMethod, ISimpleDeobfuscator deobfsucator)
|
||||
{
|
||||
this.module = module;
|
||||
this.lzmaMethod = lzmaMethod;
|
||||
this.deobfuscator = deobfsucator;
|
||||
this._module = module;
|
||||
this._lzmaMethod = lzmaMethod;
|
||||
_deobfuscator = deobfsucator;
|
||||
}
|
||||
|
||||
public bool CanRemoveLzma { get; private set; } = true;
|
||||
|
||||
public TypeDef Type { get; private set; }
|
||||
public MethodDef Method { get; private set; }
|
||||
public MethodDef AssembyResolveMethod { get; private set; }
|
||||
public List<FieldDef> Fields => new List<FieldDef> {_arrayField, _asmField};
|
||||
|
||||
public bool Detected => Method != null && _decryptedBytes != null && _arrayField != null && _asmField != null;
|
||||
|
||||
public void Find()
|
||||
{
|
||||
var moduleCctor = DotNetUtils.GetModuleTypeCctor(module);
|
||||
var moduleCctor = DotNetUtils.GetModuleTypeCctor(_module);
|
||||
if (moduleCctor == null)
|
||||
return;
|
||||
foreach (var inst in moduleCctor.Body.Instructions)
|
||||
|
@ -73,14 +49,14 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
continue;
|
||||
if (!DotNetUtils.IsMethod(method, "System.Void", "()"))
|
||||
continue;
|
||||
deobfuscator.Deobfuscate(method, SimpleDeobfuscatorFlags.Force);
|
||||
if (!isResDecryptInit(method))
|
||||
_deobfuscator.Deobfuscate(method, SimpleDeobfuscatorFlags.Force);
|
||||
if (!IsResDecryptInit(method))
|
||||
continue;
|
||||
resourceDecInitMethod = method;
|
||||
Method = method;
|
||||
}
|
||||
}
|
||||
|
||||
bool isResDecryptInit(MethodDef method)
|
||||
private bool IsResDecryptInit(MethodDef method)
|
||||
{
|
||||
var instr = method.Body.Instructions;
|
||||
|
||||
|
@ -89,7 +65,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
|
||||
if (!instr[0].IsLdcI4())
|
||||
return false;
|
||||
if (!instr[1].IsStloc()) //uint num = 96u;
|
||||
if (!instr[1].IsStloc()) //uint num = 96u;
|
||||
return false;
|
||||
|
||||
if (!instr[2].IsLdcI4())
|
||||
|
@ -113,9 +89,11 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return false;
|
||||
if (instr[6].OpCode != OpCodes.Call)
|
||||
return false;
|
||||
if (instr[6].Operand.ToString() != "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)")
|
||||
if (instr[6].Operand.ToString() !=
|
||||
"System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)"
|
||||
)
|
||||
return false;
|
||||
if (!instr[7].IsStloc()) // uint[] array = new uint[] {.....};
|
||||
if (!instr[7].IsStloc()) // uint[] array = new uint[] {.....};
|
||||
return false;
|
||||
|
||||
var l = instr.Count;
|
||||
|
@ -123,13 +101,14 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return false;
|
||||
if (instr[l - 9].OpCode != OpCodes.Call)
|
||||
return false;
|
||||
if (instr[l - 9].Operand != lzmaMethod)
|
||||
if (instr[l - 9].Operand != _lzmaMethod)
|
||||
return false;
|
||||
if (instr[l - 8].OpCode != OpCodes.Call)
|
||||
return false;
|
||||
if (instr[l - 8].Operand.ToString() != "System.Reflection.Assembly System.Reflection.Assembly::Load(System.Byte[])")
|
||||
if (instr[l - 8].Operand.ToString() !=
|
||||
"System.Reflection.Assembly System.Reflection.Assembly::Load(System.Byte[])")
|
||||
return false;
|
||||
if (instr[l - 7].OpCode != OpCodes.Stsfld) //<Module>.assembly_0 = Assembly.Load(array4);
|
||||
if (instr[l - 7].OpCode != OpCodes.Stsfld) //<Module>.assembly_0 = Assembly.Load(array4);
|
||||
return false;
|
||||
var asField = instr[l - 7].Operand as FieldDef;
|
||||
if (asField == null)
|
||||
|
@ -150,84 +129,89 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return false;
|
||||
if (instr[l - 3].OpCode != OpCodes.Newobj)
|
||||
return false;
|
||||
if (instr[l - 2].OpCode != OpCodes.Callvirt) //AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(<Module>.smethod_1);
|
||||
if (instr[l - 2].OpCode != OpCodes.Callvirt
|
||||
) //AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(<Module>.smethod_1);
|
||||
return false;
|
||||
try
|
||||
{
|
||||
DecryptArray(ConvertArray<uint, byte>(aField.InitialValue));
|
||||
}
|
||||
catch { canRemoveLzma = false; return false; }
|
||||
arrayField = aField;
|
||||
arrayType = DotNetUtils.GetType(module, aField.FieldSig.Type);
|
||||
asmField = asField;
|
||||
assembyResolveMethod = mtd;
|
||||
catch
|
||||
{
|
||||
CanRemoveLzma = false;
|
||||
return false;
|
||||
}
|
||||
_arrayField = aField;
|
||||
Type = DotNetUtils.GetType(_module, aField.FieldSig.Type);
|
||||
_asmField = asField;
|
||||
AssembyResolveMethod = mtd;
|
||||
return true;
|
||||
}
|
||||
|
||||
private T[] ConvertArray<T, T1>(T1[] array)
|
||||
{
|
||||
int l = Marshal.SizeOf(typeof(T));
|
||||
int l1 = Marshal.SizeOf(typeof(T1));
|
||||
var buffer = new T[(array.Length * l1) / l];
|
||||
var l = Marshal.SizeOf(typeof(T));
|
||||
var l1 = Marshal.SizeOf(typeof(T1));
|
||||
var buffer = new T[array.Length * l1 / l];
|
||||
Buffer.BlockCopy(array, 0, buffer, 0, array.Length * l1);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private void DecryptArray(uint[] array) //TODO: Automatic detection
|
||||
{
|
||||
int num = array.Length;
|
||||
uint[] array2 = new uint[16];
|
||||
uint num2 = 825993394u;
|
||||
for (int i = 0; i < 16; i++)
|
||||
var num = array.Length;
|
||||
var array2 = new uint[16];
|
||||
var num2 = 825993394u;
|
||||
for (var i = 0; i < 16; i++)
|
||||
{
|
||||
num2 ^= num2 >> 13;
|
||||
num2 ^= num2 << 25;
|
||||
num2 ^= num2 >> 27;
|
||||
array2[i] = num2;
|
||||
}
|
||||
int num3 = 0;
|
||||
int num4 = 0;
|
||||
uint[] array3 = new uint[16];
|
||||
byte[] array4 = new byte[num * 4u];
|
||||
while ((long)num3 < (long)((ulong)num))
|
||||
var num3 = 0;
|
||||
var num4 = 0;
|
||||
var array3 = new uint[16];
|
||||
var array4 = new byte[num * 4u];
|
||||
while (num3 < (long) (ulong) num)
|
||||
{
|
||||
for (int j = 0; j < 16; j++)
|
||||
{
|
||||
for (var j = 0; j < 16; j++)
|
||||
array3[j] = array[num3 + j];
|
||||
}
|
||||
array3[0] = (array3[0] ^ array2[0]);
|
||||
array3[1] = (array3[1] ^ array2[1]);
|
||||
array3[2] = (array3[2] ^ array2[2]);
|
||||
array3[3] = (array3[3] ^ array2[3]);
|
||||
array3[4] = (array3[4] ^ array2[4]);
|
||||
array3[5] = (array3[5] ^ array2[5]);
|
||||
array3[6] = (array3[6] ^ array2[6]);
|
||||
array3[7] = (array3[7] ^ array2[7]);
|
||||
array3[8] = (array3[8] ^ array2[8]);
|
||||
array3[9] = (array3[9] ^ array2[9]);
|
||||
array3[10] = (array3[10] ^ array2[10]);
|
||||
array3[11] = (array3[11] ^ array2[11]);
|
||||
array3[12] = (array3[12] ^ array2[12]);
|
||||
array3[13] = (array3[13] ^ array2[13]);
|
||||
array3[14] = (array3[14] ^ array2[14]);
|
||||
array3[15] = (array3[15] ^ array2[15]);
|
||||
for (int k = 0; k < 16; k++)
|
||||
array3[0] = array3[0] ^ array2[0];
|
||||
array3[1] = array3[1] ^ array2[1];
|
||||
array3[2] = array3[2] ^ array2[2];
|
||||
array3[3] = array3[3] ^ array2[3];
|
||||
array3[4] = array3[4] ^ array2[4];
|
||||
array3[5] = array3[5] ^ array2[5];
|
||||
array3[6] = array3[6] ^ array2[6];
|
||||
array3[7] = array3[7] ^ array2[7];
|
||||
array3[8] = array3[8] ^ array2[8];
|
||||
array3[9] = array3[9] ^ array2[9];
|
||||
array3[10] = array3[10] ^ array2[10];
|
||||
array3[11] = array3[11] ^ array2[11];
|
||||
array3[12] = array3[12] ^ array2[12];
|
||||
array3[13] = array3[13] ^ array2[13];
|
||||
array3[14] = array3[14] ^ array2[14];
|
||||
array3[15] = array3[15] ^ array2[15];
|
||||
for (var k = 0; k < 16; k++)
|
||||
{
|
||||
uint num5 = array3[k];
|
||||
array4[num4++] = (byte)num5;
|
||||
array4[num4++] = (byte)(num5 >> 8);
|
||||
array4[num4++] = (byte)(num5 >> 16);
|
||||
array4[num4++] = (byte)(num5 >> 24);
|
||||
var num5 = array3[k];
|
||||
array4[num4++] = (byte) num5;
|
||||
array4[num4++] = (byte) (num5 >> 8);
|
||||
array4[num4++] = (byte) (num5 >> 16);
|
||||
array4[num4++] = (byte) (num5 >> 24);
|
||||
array2[k] ^= num5;
|
||||
}
|
||||
num3 += 16;
|
||||
}
|
||||
decryptedBytes = Lzma.Decompress(array4);
|
||||
_decryptedBytes = Lzma.Decompress(array4);
|
||||
}
|
||||
|
||||
private bool IsAssembyResolveMethod(MethodDef method, FieldDef field)
|
||||
{
|
||||
if (DotNetUtils.IsMethod(method, "", "()"))
|
||||
return false;
|
||||
deobfuscator.Deobfuscate(method, SimpleDeobfuscatorFlags.Force);
|
||||
_deobfuscator.Deobfuscate(method, SimpleDeobfuscatorFlags.Force);
|
||||
|
||||
var instr = method.Body.Instructions;
|
||||
if (instr.Count != 10)
|
||||
|
@ -271,23 +255,27 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
ModuleDef newModule;
|
||||
try
|
||||
{
|
||||
newModule = ModuleDefMD.Load(decryptedBytes);
|
||||
newModule = ModuleDefMD.Load(_decryptedBytes);
|
||||
}
|
||||
catch { canRemoveLzma = false; return; }
|
||||
List<Resource> toRemove = new List<Resource>();
|
||||
List<Resource> toAdd = new List<Resource>();
|
||||
foreach (var cryptedResource in module.Resources)
|
||||
foreach (var resource in newModule.Resources)
|
||||
if (cryptedResource.Name == resource.Name)
|
||||
{
|
||||
toRemove.Add(cryptedResource);
|
||||
toAdd.Add(resource);
|
||||
}
|
||||
catch
|
||||
{
|
||||
CanRemoveLzma = false;
|
||||
return;
|
||||
}
|
||||
var toRemove = new List<Resource>();
|
||||
var toAdd = new List<Resource>();
|
||||
foreach (var cryptedResource in _module.Resources)
|
||||
foreach (var resource in newModule.Resources)
|
||||
if (cryptedResource.Name == resource.Name)
|
||||
{
|
||||
toRemove.Add(cryptedResource);
|
||||
toAdd.Add(resource);
|
||||
}
|
||||
|
||||
foreach (var resToRemove in toRemove)
|
||||
module.Resources.Remove(resToRemove);
|
||||
_module.Resources.Remove(resToRemove);
|
||||
foreach (var resToAdd in toAdd)
|
||||
module.Resources.Add(resToAdd);
|
||||
_module.Resources.Add(resToAdd);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using de4dot.blocks;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
@ -128,7 +126,8 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
|
||||
public static bool IsValidInstr(this Instr instr)
|
||||
{
|
||||
return IsArithmetical(instr) || instr.IsConv() || IsLdc(instr) || IsLoc(instr) || instr.OpCode == OpCodes.Dup;
|
||||
return IsArithmetical(instr) || instr.IsConv() || IsLdc(instr) || IsLoc(instr) ||
|
||||
instr.OpCode == OpCodes.Dup;
|
||||
}
|
||||
|
||||
public static bool IsDup(this Block block)
|
||||
|
@ -188,7 +187,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return false;
|
||||
if (!DotNetUtils.IsMethod(method, "System.Int32", "(System.Int32)"))
|
||||
return false;
|
||||
for (int i = switchData.IsKeyHardCoded ? 2 : 1; i < instr.Count - 1; i++)
|
||||
for (var i = switchData.IsKeyHardCoded ? 2 : 1; i < instr.Count - 1; i++)
|
||||
if (!instr[i].IsValidInstr())
|
||||
return false;
|
||||
|
||||
|
@ -238,8 +237,8 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
var sources = block.Sources;
|
||||
if (sources.Count != 2)
|
||||
return false;
|
||||
if (!sources[0].IsDup() || !(sources[1]).IsDup()) //TODO: Case without DUP?
|
||||
return false;
|
||||
if (!sources[0].IsDup() || !sources[1].IsDup()) //TODO: Case without DUP?
|
||||
return false;
|
||||
if (sources[0].CountTargets() > 1 || sources[1].CountTargets() > 1)
|
||||
return false;
|
||||
if (sources[0].FallThrough != block || sources[1].FallThrough != block)
|
||||
|
@ -256,16 +255,11 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
|
||||
public static List<Block> GetTernaryPredicates(this List<Block> switchCaseBlocks)
|
||||
{
|
||||
List<Block> ternaryPredicates = new List<Block>();
|
||||
var ternaryPredicates = new List<Block>();
|
||||
|
||||
foreach (Block preBlock in switchCaseBlocks)
|
||||
{
|
||||
if (IsTernary(preBlock))
|
||||
{
|
||||
// switchCaseBlock -> 2x sourceBlock -> ternaryPredicateBlock
|
||||
foreach (var preBlock in switchCaseBlocks)
|
||||
if (IsTernary(preBlock)) // switchCaseBlock -> 2x sourceBlock -> ternaryPredicateBlock
|
||||
ternaryPredicates.Add(preBlock.Sources[0].Sources[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return ternaryPredicates;
|
||||
}
|
||||
|
@ -275,4 +269,4 @@ namespace de4dot.code.deobfuscators.ConfuserEx
|
|||
return ternaryPredicateBlock.FallThrough.FallThrough;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.Bea;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
|
||||
namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.Bea;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
|
||||
namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.Bea;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
|
||||
namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.Bea;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
|
||||
namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.Bea;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
|
||||
namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.Bea;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
|
||||
namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.Bea;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
|
||||
namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.Bea;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
|
||||
namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.Bea;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
|
||||
namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.Bea;
|
||||
using de4dot.code.deobfuscators.ConfuserEx.x86;
|
||||
|
||||
namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions
|
||||
{
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace de4dot.code.x86
|
||||
namespace de4dot.code.deobfuscators.ConfuserEx.x86
|
||||
{
|
||||
public class UnmanagedBuffer
|
||||
{
|
||||
public readonly IntPtr Ptr = IntPtr.Zero;
|
||||
public readonly int Length = 0;
|
||||
public readonly IntPtr Ptr;
|
||||
public readonly int Length;
|
||||
|
||||
public UnmanagedBuffer(byte[] data)
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using de4dot.Bea;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using de4dot.Bea;
|
||||
|
||||
namespace ConfuserDeobfuscator.Engine.Routines.Ex.x86
|
||||
namespace de4dot.code.deobfuscators.ConfuserEx.x86
|
||||
{
|
||||
public enum X86OpCode
|
||||
{
|
||||
|
|
|
@ -5,7 +5,6 @@ using System.Runtime.InteropServices;
|
|||
using ConfuserDeobfuscator.Engine.Routines.Ex.x86;
|
||||
using ConfuserDeobfuscator.Engine.Routines.Ex.x86.Instructions;
|
||||
using de4dot.Bea;
|
||||
using de4dot.code.x86;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace de4dot.code.deobfuscators.ConfuserEx.x86
|
||||
|
@ -27,7 +26,7 @@ namespace de4dot.code.deobfuscators.ConfuserEx.x86
|
|||
{"EDI", 0}
|
||||
};
|
||||
|
||||
readonly ModuleDefMD _module;
|
||||
private readonly ModuleDefMD _module;
|
||||
public X86Method(MethodDef method,ModuleDefMD module)
|
||||
{
|
||||
this._module = module;
|
||||
|
|
Loading…
Reference in New Issue