Use the MSILEmulator for dynamic constants decryption.

This commit is contained in:
Harry Stoltz
2023-04-08 19:00:39 +01:00
parent 7a330a5c2a
commit b18778beff
2 changed files with 13 additions and 124 deletions
@@ -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++)
{
+1 -1
View File
@@ -43,8 +43,8 @@ namespace UnConfuserEx
new AntiTamperRemover(),
new ControlFlowRemover(),
new ResourcesRemover(),
new ConstantsRemover(),
new ResourcesRemover(),
new RefProxyRemover(),
new AntiDumpRemover(),
new AntiDebugRemover(),