mirror of
https://github.com/Zypherion-Technologies/UnConfuserEx
synced 2026-06-23 09:25:30 +00:00
Add files via upload
This commit is contained in:
committed by
GitHub
parent
ec6db89288
commit
e56a256c7b
@@ -0,0 +1,23 @@
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MSILEmulator
|
||||
{
|
||||
public class Context
|
||||
{
|
||||
public Dictionary<int, object> Args = new();
|
||||
public Dictionary<IField, object> Fields = new();
|
||||
public Dictionary<int, object> Locals = new();
|
||||
public Dictionary<uint, int> Offsets = new();
|
||||
public Stack<object> Stack = new();
|
||||
|
||||
public Context(IList<Instruction> instructions)
|
||||
{
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
{
|
||||
Offsets[instructions[i].Offset] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator
|
||||
{
|
||||
internal class EmulatorException : Exception
|
||||
{
|
||||
|
||||
public EmulatorException()
|
||||
{
|
||||
}
|
||||
|
||||
public EmulatorException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public EmulatorException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using MSILEmulator.Instructions.Arithmetic;
|
||||
using MSILEmulator.Instructions.Branch;
|
||||
using MSILEmulator.Instructions.Load;
|
||||
using MSILEmulator.Instructions.Logic;
|
||||
using MSILEmulator.Instructions.Store;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MSILEmulator
|
||||
{
|
||||
public class ILMethod
|
||||
{
|
||||
private MethodDef? Method;
|
||||
private List<Instruction> Instructions;
|
||||
private Context Ctx;
|
||||
|
||||
public ILMethod(MethodDef method)
|
||||
{
|
||||
Method = method;
|
||||
Instructions = Method.Body.Instructions.ToList();
|
||||
Ctx = new(Instructions);
|
||||
}
|
||||
|
||||
public ILMethod(MethodDef method, int start, int end)
|
||||
{
|
||||
Method = method;
|
||||
Instructions = Method.Body.Instructions.Skip(start).Take(end - start).ToList();
|
||||
Ctx = new(Instructions);
|
||||
}
|
||||
|
||||
public ILMethod(IEnumerable<Instruction> instructions)
|
||||
{
|
||||
Method = null;
|
||||
Instructions = instructions.ToList();
|
||||
Ctx = new(Instructions);
|
||||
}
|
||||
|
||||
public void SetArg(int index, object value)
|
||||
{
|
||||
Ctx.Args[index] = value;
|
||||
}
|
||||
|
||||
public void SetLocal(int index, object value)
|
||||
{
|
||||
Ctx.Locals[index] = value;
|
||||
}
|
||||
|
||||
public Context Emulate()
|
||||
{
|
||||
|
||||
for (int i = 0; i < Instructions.Count; )
|
||||
{
|
||||
var instr = Instructions[i];
|
||||
|
||||
i = EmulateInstruction(Ctx, instr, i);
|
||||
|
||||
if (i == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Ctx;
|
||||
}
|
||||
|
||||
private int EmulateInstruction(Context ctx, Instruction instr, int index)
|
||||
{
|
||||
|
||||
switch (instr.OpCode.Code)
|
||||
{
|
||||
// Load
|
||||
case Code.Ldc_I4:
|
||||
case Code.Ldc_I4_S:
|
||||
ctx.Stack.Push(instr.GetLdcI4Value());
|
||||
break;
|
||||
case Code.Ldc_I4_0:
|
||||
case Code.Ldc_I4_1:
|
||||
case Code.Ldc_I4_2:
|
||||
case Code.Ldc_I4_3:
|
||||
case Code.Ldc_I4_4:
|
||||
case Code.Ldc_I4_5:
|
||||
case Code.Ldc_I4_6:
|
||||
case Code.Ldc_I4_7:
|
||||
case Code.Ldc_I4_8:
|
||||
ctx.Stack.Push((int)instr.OpCode.Code - (int)Code.Ldc_I4_0);
|
||||
break;
|
||||
case Code.Ldc_I4_M1:
|
||||
ctx.Stack.Push((int)-1);
|
||||
break;
|
||||
|
||||
case Code.Ldc_I8:
|
||||
ctx.Stack.Push((long)instr.Operand);
|
||||
break;
|
||||
|
||||
case Code.Ldarg:
|
||||
case Code.Ldarg_0:
|
||||
case Code.Ldarg_1:
|
||||
case Code.Ldarg_2:
|
||||
case Code.Ldarg_3:
|
||||
case Code.Ldarg_S:
|
||||
Ldarg.Emulate(ctx, instr);
|
||||
break;
|
||||
|
||||
case Code.Ldloc:
|
||||
case Code.Ldloc_0:
|
||||
case Code.Ldloc_1:
|
||||
case Code.Ldloc_2:
|
||||
case Code.Ldloc_3:
|
||||
case Code.Ldloc_S:
|
||||
Ldloc.Emulate(ctx, instr);
|
||||
break;
|
||||
|
||||
case Code.Ldelem_U4:
|
||||
Ldelem.EmulateU4(ctx, instr);
|
||||
break;
|
||||
|
||||
// Store
|
||||
case Code.Stloc:
|
||||
case Code.Stloc_0:
|
||||
case Code.Stloc_1:
|
||||
case Code.Stloc_2:
|
||||
case Code.Stloc_3:
|
||||
case Code.Stloc_S:
|
||||
Stloc.Emulate(ctx, instr);
|
||||
break;
|
||||
|
||||
case Code.Stelem_I4:
|
||||
Stelem.Emulate(ctx, instr);
|
||||
break;
|
||||
|
||||
case Code.Stfld:
|
||||
ctx.Fields[(IField)instr.Operand] = ctx.Stack.Pop();
|
||||
if (ctx.Stack.Count > 0)
|
||||
{
|
||||
ctx.Stack.Pop();
|
||||
}
|
||||
break;
|
||||
|
||||
// Arithmetic operators
|
||||
case Code.Add:
|
||||
Add.Emulate(ctx);
|
||||
break;
|
||||
case Code.Mul:
|
||||
Mul.Emulate(ctx);
|
||||
break;
|
||||
case Code.Neg:
|
||||
Neg.Emulate(ctx);
|
||||
break;
|
||||
case Code.Or:
|
||||
Or.Emulate(ctx);
|
||||
break;
|
||||
case Code.Sub:
|
||||
Sub.Emulate(ctx);
|
||||
break;
|
||||
|
||||
// Logic operators
|
||||
case Code.And:
|
||||
And.Emulate(ctx);
|
||||
break;
|
||||
case Code.Not:
|
||||
Not.Emulate(ctx);
|
||||
break;
|
||||
case Code.Shl:
|
||||
Shl.Emulate(ctx);
|
||||
break;
|
||||
case Code.Shr:
|
||||
Shr.Emulate(ctx);
|
||||
break;
|
||||
case Code.Shr_Un:
|
||||
Shr_Un.Emulate(ctx);
|
||||
break;
|
||||
case Code.Xor:
|
||||
Xor.Emulate(ctx);
|
||||
break;
|
||||
|
||||
|
||||
// Branching
|
||||
case Code.Br:
|
||||
case Code.Br_S:
|
||||
return ctx.Offsets[((Instruction)instr.Operand).Offset];
|
||||
case Code.Beq:
|
||||
case Code.Beq_S:
|
||||
return Beq.Emulate(ctx, instr);
|
||||
case Code.Bne_Un:
|
||||
case Code.Bne_Un_S:
|
||||
return Bne.Emulate(ctx, instr);
|
||||
|
||||
// Conversion
|
||||
case Code.Conv_U8:
|
||||
var type = ctx.Stack.Peek().GetType();
|
||||
if (type == typeof(int))
|
||||
ctx.Stack.Push((long)(int)ctx.Stack.Pop());
|
||||
else
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
|
||||
|
||||
// Misc
|
||||
case Code.Nop:
|
||||
// ...No-op
|
||||
break;
|
||||
|
||||
case Code.Ret:
|
||||
return -1;
|
||||
|
||||
default:
|
||||
throw new EmulatorException($"Unhandled OpCode {instr.OpCode}");
|
||||
}
|
||||
|
||||
return ++index;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Arithmetic
|
||||
{
|
||||
internal class Add
|
||||
{
|
||||
public static void Emulate(Context ctx)
|
||||
{
|
||||
int val2 = (int)ctx.Stack.Pop();
|
||||
int val1 = (int)ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(val1 + val2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Arithmetic
|
||||
{
|
||||
internal class Mul
|
||||
{
|
||||
public static void Emulate(Context ctx)
|
||||
{
|
||||
int val2 = (int)ctx.Stack.Pop();
|
||||
int val1 = (int)ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(val1 * val2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Arithmetic
|
||||
{
|
||||
internal class Neg
|
||||
{
|
||||
public static void Emulate(Context ctx)
|
||||
{
|
||||
int val = (int)ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(-val);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Arithmetic
|
||||
{
|
||||
internal class Sub
|
||||
{
|
||||
public static void Emulate(Context ctx)
|
||||
{
|
||||
int val2 = (int)ctx.Stack.Pop();
|
||||
int val1 = (int)ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(val1 - val2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace MSILEmulator.Instructions.Branch
|
||||
{
|
||||
internal class Beq
|
||||
{
|
||||
public static int Emulate(Context ctx, Instruction instr)
|
||||
{
|
||||
return BranchCompare.Emulate(ctx, instr, static (left, right) => left == right, static (left, right) => left == right);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace MSILEmulator.Instructions.Branch
|
||||
{
|
||||
internal class Bne
|
||||
{
|
||||
public static int Emulate(Context ctx, Instruction instr)
|
||||
{
|
||||
return BranchCompare.Emulate(ctx, instr, static (left, right) => left != right, static (left, right) => left != right);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
|
||||
namespace MSILEmulator.Instructions.Branch
|
||||
{
|
||||
internal static class BranchCompare
|
||||
{
|
||||
public static int Emulate(Context ctx, Instruction instr, Func<int, int, bool> compareInt, Func<long, long, bool> compareLong)
|
||||
{
|
||||
object val2 = ctx.Stack.Pop();
|
||||
object val1 = ctx.Stack.Pop();
|
||||
|
||||
if (val1.GetType() != val2.GetType())
|
||||
{
|
||||
throw new EmulatorException($"Attempted to compare different types {val1.GetType()} != {val2.GetType()}");
|
||||
}
|
||||
|
||||
bool branch = val1 switch
|
||||
{
|
||||
int leftInt => compareInt(leftInt, (int)val2),
|
||||
long leftLong => compareLong(leftLong, (long)val2),
|
||||
_ => throw new NotImplementedException($"Comparison of {val1.GetType().Name} not handled")
|
||||
};
|
||||
|
||||
return branch
|
||||
? ctx.Offsets[((Instruction)instr.Operand).Offset]
|
||||
: ctx.Offsets[instr.Offset] + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Load
|
||||
{
|
||||
internal class Ldarg
|
||||
{
|
||||
public static void Emulate(Context ctx, Instruction instr)
|
||||
{
|
||||
int index;
|
||||
if (instr.Operand == null)
|
||||
{
|
||||
index = instr.OpCode.Code - Code.Ldarg_0;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = (int)instr.Operand;
|
||||
}
|
||||
|
||||
if (ctx.Args.TryGetValue(index, out var val))
|
||||
{
|
||||
ctx.Stack.Push(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.Stack.Push(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Load
|
||||
{
|
||||
internal class Ldelem
|
||||
{
|
||||
public static void EmulateU4(Context ctx, Instruction instr)
|
||||
{
|
||||
int index = (int)ctx.Stack.Pop();
|
||||
var array = (uint[])ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(unchecked((int)array[index]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Load
|
||||
{
|
||||
internal class Ldloc
|
||||
{
|
||||
public static void Emulate(Context ctx, Instruction instr)
|
||||
{
|
||||
int index;
|
||||
if (instr.Operand == null)
|
||||
{
|
||||
index = instr.OpCode.Code - Code.Ldloc_0;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = ((Local)instr.Operand).Index;
|
||||
}
|
||||
|
||||
if (ctx.Locals.TryGetValue(index, out var local))
|
||||
{
|
||||
ctx.Stack.Push(local);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("Attempted to load local that hasn't been set.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Logic
|
||||
{
|
||||
internal class And
|
||||
{
|
||||
public static void Emulate(Context ctx)
|
||||
{
|
||||
int val2 = (int)ctx.Stack.Pop();
|
||||
int val1 = (int)ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(val1 & val2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Logic
|
||||
{
|
||||
internal class Not
|
||||
{
|
||||
public static void Emulate(Context ctx)
|
||||
{
|
||||
int val = (int)ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(~val);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Logic
|
||||
{
|
||||
internal class Or
|
||||
{
|
||||
public static void Emulate(Context ctx)
|
||||
{
|
||||
int val2 = (int)ctx.Stack.Pop();
|
||||
int val1 = (int)ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(val1 | val2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Logic
|
||||
{
|
||||
internal class Shl
|
||||
{
|
||||
public static void Emulate(Context ctx)
|
||||
{
|
||||
var shift = (int)ctx.Stack.Pop();
|
||||
var val = (int)ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(val << shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Logic
|
||||
{
|
||||
internal class Shr
|
||||
{
|
||||
public static void Emulate(Context ctx)
|
||||
{
|
||||
var shift = (int)ctx.Stack.Pop();
|
||||
var val = (int)ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(val >> shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Logic
|
||||
{
|
||||
internal class Shr_Un
|
||||
{
|
||||
public static void Emulate(Context ctx)
|
||||
{
|
||||
var shift = (int)ctx.Stack.Pop();
|
||||
var val = (int)ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(val >>> shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Logic
|
||||
{
|
||||
internal class Xor
|
||||
{
|
||||
public static void Emulate(Context ctx)
|
||||
{
|
||||
int val2 = (int)ctx.Stack.Pop();
|
||||
int val1 = (int)ctx.Stack.Pop();
|
||||
|
||||
ctx.Stack.Push(val2 ^ val1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Store
|
||||
{
|
||||
internal class Stelem
|
||||
{
|
||||
public static void Emulate(Context ctx, Instruction instr)
|
||||
{
|
||||
int value = (int)ctx.Stack.Pop();
|
||||
int index = (int)ctx.Stack.Pop();
|
||||
var array = (int[])ctx.Stack.Pop();
|
||||
|
||||
array[index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MSILEmulator.Instructions.Store
|
||||
{
|
||||
internal class Stloc
|
||||
{
|
||||
public static void Emulate(Context ctx, Instruction instr)
|
||||
{
|
||||
int index;
|
||||
if (instr.Operand == null)
|
||||
{
|
||||
index = instr.OpCode.Code - Code.Stloc_0;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = ((Local)instr.Operand).Index;
|
||||
}
|
||||
|
||||
ctx.Locals[index] = ctx.Stack.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="dnlib" Version="4.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user