mirror of
https://github.com/MadMin3r/UnconfuserEx
synced 2026-06-23 09:25:19 +00:00
Use the MSILEmulator for dynamic constants decryption.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using dnlib.DotNet.Emit;
|
||||
using MSILEmulator;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -9,15 +10,16 @@ namespace UnConfuserEx.Protections.Constants
|
||||
internal class DynamicDecryptor : IDecryptor
|
||||
{
|
||||
private IList<Instruction> decryptInstructions;
|
||||
private Func<uint[], uint[], uint[]> decryptDelegate;
|
||||
private ILMethod decryptMethod;
|
||||
private int[] arrayIndices;
|
||||
|
||||
public DynamicDecryptor(IList<Instruction> decryptInstructions)
|
||||
{
|
||||
this.decryptInstructions = decryptInstructions;
|
||||
decryptDelegate = GetDecryptDelegate();
|
||||
SetupDecryptMethod();
|
||||
}
|
||||
|
||||
private Func<uint[], uint[], uint[]> GetDecryptDelegate()
|
||||
private void SetupDecryptMethod()
|
||||
{
|
||||
SortedSet<int> arrays = new();
|
||||
for (int i = 0; i < decryptInstructions.Count - 2; i++)
|
||||
@@ -35,130 +37,13 @@ namespace UnConfuserEx.Protections.Constants
|
||||
}
|
||||
}
|
||||
}
|
||||
int[] arrayIndices = arrays.ToArray();
|
||||
arrayIndices = arrays.ToArray();
|
||||
if (arrayIndices.Length != 2)
|
||||
{
|
||||
throw new Exception("There should be two key arrays used in a dynamic derivation");
|
||||
}
|
||||
|
||||
var deriverMethod = new SRE.DynamicMethod("", typeof(uint[]), new Type[] { typeof(uint[]), typeof(uint[]) });
|
||||
var il = deriverMethod.GetILGenerator();
|
||||
|
||||
// Setup locals
|
||||
Dictionary<int, int> locals = new();
|
||||
locals.Add(arrayIndices[0], 0);
|
||||
il.DeclareLocal(typeof(uint[])); // key
|
||||
locals.Add(arrayIndices[1], 1);
|
||||
il.DeclareLocal(typeof(uint[])); // temp
|
||||
|
||||
// Store passed arrays in the expected locals
|
||||
il.Emit(SRE.OpCodes.Ldarg_0);
|
||||
il.Emit(SRE.OpCodes.Stloc_S, 0);
|
||||
il.Emit(SRE.OpCodes.Ldarg_1);
|
||||
il.Emit(SRE.OpCodes.Stloc_S, 1);
|
||||
|
||||
// Derivation
|
||||
foreach (var instr in decryptInstructions)
|
||||
{
|
||||
var opcode = (SRE.OpCode)typeof(SRE.OpCodes).GetField(instr.OpCode.Code.ToString())!.GetValue(null)!;
|
||||
|
||||
if (instr.Operand == null)
|
||||
{
|
||||
if (instr.OpCode.OpCodeType == OpCodeType.Macro)
|
||||
{
|
||||
if (instr.IsLdloc())
|
||||
{
|
||||
var index = instr.OpCode.Value - OpCodes.Ldloc_0.Value;
|
||||
int operand;
|
||||
if (locals.ContainsKey(index))
|
||||
{
|
||||
operand = locals[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
operand = locals.Count;
|
||||
locals.Add(index, operand);
|
||||
|
||||
il.DeclareLocal(typeof(uint));
|
||||
}
|
||||
il.Emit(SRE.OpCodes.Ldloc_S, operand);
|
||||
}
|
||||
else if (instr.IsStloc())
|
||||
{
|
||||
var index = instr.OpCode.Value - OpCodes.Ldloc_0.Value;
|
||||
int operand;
|
||||
if (locals.ContainsKey(index))
|
||||
{
|
||||
operand = locals[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
operand = locals.Count;
|
||||
locals.Add(index, operand);
|
||||
|
||||
il.DeclareLocal(typeof(uint));
|
||||
}
|
||||
il.Emit(SRE.OpCodes.Stloc_S, operand);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(opcode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(opcode);
|
||||
}
|
||||
}
|
||||
else if (instr.Operand is Local local)
|
||||
{
|
||||
var index = local.Index;
|
||||
int operand;
|
||||
if (locals.ContainsKey(index))
|
||||
{
|
||||
operand = locals[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
operand = locals.Count;
|
||||
locals.Add(index, operand);
|
||||
|
||||
il.DeclareLocal(typeof(uint));
|
||||
}
|
||||
il.Emit(opcode, operand);
|
||||
}
|
||||
else if (instr.Operand is sbyte sb)
|
||||
{
|
||||
il.Emit(opcode, sb);
|
||||
}
|
||||
else if (instr.Operand is int i)
|
||||
{
|
||||
il.Emit(opcode, i);
|
||||
}
|
||||
else if (instr.Operand is short s)
|
||||
{
|
||||
il.Emit(opcode, s);
|
||||
}
|
||||
else if (instr.Operand is byte b)
|
||||
{
|
||||
il.Emit(opcode, b);
|
||||
}
|
||||
else if (instr.Operand is long l)
|
||||
{
|
||||
il.Emit(opcode, l);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Unhandled operand type: { instr.Operand.GetType() }");
|
||||
}
|
||||
}
|
||||
|
||||
// Return the temp array
|
||||
il.Emit(SRE.OpCodes.Ldloc_S, 1);
|
||||
il.Emit(SRE.OpCodes.Ret);
|
||||
|
||||
var deriverDelegate = (Func<uint[], uint[], uint[]>)deriverMethod.CreateDelegate(typeof(Func<uint[], uint[], uint[]>));
|
||||
return deriverDelegate;
|
||||
decryptMethod = new ILMethod(decryptInstructions);
|
||||
}
|
||||
|
||||
public byte[] DecryptData(uint[] data, uint[] key)
|
||||
@@ -166,6 +51,10 @@ namespace UnConfuserEx.Protections.Constants
|
||||
uint[] temp = new uint[key.Length];
|
||||
byte[] ret = new byte[data.Length << 2];
|
||||
int s = 0, d = 0;
|
||||
|
||||
decryptMethod.SetLocal(arrayIndices[0], key);
|
||||
decryptMethod.SetLocal(arrayIndices[1], temp);
|
||||
|
||||
while (s < data.Length)
|
||||
{
|
||||
for (int j = 0; j < 16; j++)
|
||||
@@ -173,7 +62,7 @@ namespace UnConfuserEx.Protections.Constants
|
||||
temp[j] = data[s + j];
|
||||
}
|
||||
|
||||
temp = decryptDelegate.Invoke(key, temp);
|
||||
decryptMethod.Emulate();
|
||||
|
||||
for (int j = 0; j < 16; j++)
|
||||
{
|
||||
|
||||
@@ -43,8 +43,8 @@ namespace UnConfuserEx
|
||||
new AntiTamperRemover(),
|
||||
|
||||
new ControlFlowRemover(),
|
||||
new ResourcesRemover(),
|
||||
new ConstantsRemover(),
|
||||
new ResourcesRemover(),
|
||||
new RefProxyRemover(),
|
||||
new AntiDumpRemover(),
|
||||
new AntiDebugRemover(),
|
||||
|
||||
Reference in New Issue
Block a user