├── dnlib.dll
├── MemeVM.Runtime
├── NoMoreStackItem.cs
├── Engine
│ ├── VMState.cs
│ ├── LocalStorage.cs
│ ├── Stack.cs
│ └── VM.cs
├── Instruction.cs
├── IHandler.cs
├── Handlers
│ ├── Pop.cs
│ ├── Null.cs
│ ├── Ret.cs
│ ├── Jmp.cs
│ ├── Int.cs
│ ├── Long.cs
│ ├── Ldarg.cs
│ ├── Ldloc.cs
│ ├── Stloc.cs
│ ├── Add.cs
│ ├── Cgt.cs
│ ├── Clt.cs
│ ├── Cmp.cs
│ ├── Dup.cs
│ ├── Jf.cs
│ ├── Jt.cs
│ ├── String.cs
│ ├── Ldfld.cs
│ ├── Newarr.cs
│ ├── Stfld.cs
│ └── Call.cs
├── Entry.cs
├── OpCode.cs
├── Dispatcher.cs
├── Helpers
│ └── Map.cs
├── Properties
│ └── AssemblyInfo.cs
├── Body.cs
└── MemeVM.Runtime.csproj
├── Confuser.Core.dll
├── MemeVM.Confuser
├── Program.cs
├── App.config
├── MemeVMProtection.cs
├── Properties
│ └── AssemblyInfo.cs
└── MemeVM.Confuser.csproj
├── MemeVM
├── Translation
│ ├── Helpers
│ │ ├── Offset.cs
│ │ ├── TokenGetter.cs
│ │ ├── Offsets.cs
│ │ └── Map.cs
│ ├── VMInstruction.cs
│ ├── IHandler.cs
│ ├── Handlers
│ │ ├── Dup.cs
│ │ ├── Ret.cs
│ │ ├── Ldelem.cs
│ │ ├── Add.cs
│ │ ├── Pop.cs
│ │ ├── Useless.cs
│ │ ├── Ldnull.cs
│ │ ├── Int.cs
│ │ ├── Long.cs
│ │ ├── Ldarg.cs
│ │ ├── Ldloc.cs
│ │ ├── Starg.cs
│ │ ├── Stloc.cs
│ │ ├── Ldstr.cs
│ │ ├── Ldfld.cs
│ │ ├── Stfld.cs
│ │ ├── Newarr.cs
│ │ ├── Comparisons.cs
│ │ ├── Call.cs
│ │ └── Branching.cs
│ ├── VMOpCode.cs
│ ├── Dispatcher.cs
│ └── VMBody.cs
├── Context.cs
├── Properties
│ └── AssemblyInfo.cs
├── InjectPhase.cs
├── MemeVM.csproj
└── VirtualizatonPhase.cs
├── README.md
├── MemeVM.sln
├── .gitattributes
└── .gitignore
/dnlib.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobitoFatitoRE/MemeVM/HEAD/dnlib.dll
--------------------------------------------------------------------------------
/MemeVM.Runtime/NoMoreStackItem.cs:
--------------------------------------------------------------------------------
1 | namespace MemeVM.Runtime { struct NoMoreStackItem { } }
--------------------------------------------------------------------------------
/Confuser.Core.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobitoFatitoRE/MemeVM/HEAD/Confuser.Core.dll
--------------------------------------------------------------------------------
/MemeVM.Runtime/Engine/VMState.cs:
--------------------------------------------------------------------------------
1 | namespace MemeVM.Runtime.Engine {
2 | enum VMState {
3 | Next,
4 | Exception,
5 | Rethrow,
6 | Return
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/MemeVM.Confuser/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MemeVM.Confuser {
4 | class Program {
5 | static void Main(string[] args) {
6 | //
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/MemeVM.Confuser/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Helpers/Offset.cs:
--------------------------------------------------------------------------------
1 | namespace MemeVM.Translation.Helpers {
2 | struct Offset {
3 | internal Offset(int start, int val) {
4 | Starts = start;
5 | Value = val;
6 | }
7 |
8 | internal int Starts;
9 | internal int Value;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Instruction.cs:
--------------------------------------------------------------------------------
1 | namespace MemeVM.Runtime {
2 | struct Instruction {
3 | internal Instruction(OpCode code, object op = null) {
4 | Code = code;
5 | Operand = op;
6 | }
7 |
8 | internal OpCode Code;
9 | internal object Operand;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/IHandler.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime {
5 | interface IHandler {
6 | OpCode Handles { get; }
7 | void Handle(VM machine, Body body, Instruction instruction);
8 | Instruction Deserialize(BinaryReader reader);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/MemeVM/Translation/VMInstruction.cs:
--------------------------------------------------------------------------------
1 | namespace MemeVM.Translation {
2 | struct VMInstruction {
3 | internal VMInstruction(VMOpCode code, object op = null) {
4 | OpCode = code;
5 | Operand = op;
6 | }
7 |
8 | internal VMOpCode OpCode;
9 | internal object Operand;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Helpers/TokenGetter.cs:
--------------------------------------------------------------------------------
1 | using dnlib.DotNet;
2 | using dnlib.DotNet.Writer;
3 |
4 | namespace MemeVM.Translation.Helpers {
5 | static class TokenGetter {
6 | internal static ModuleWriterBase Writer;
7 |
8 | internal static int GetMdToken(IMemberDef member) =>
9 | Writer.Module == member.Module ? Writer.MetaData.GetToken(member).ToInt32() : member.MDToken.ToInt32();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Pop.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Pop : IHandler {
6 | public OpCode Handles => OpCode.Pop;
7 | public void Handle(VM machine, Body body, Instruction instruction) =>
8 | machine.Stack.Pop();
9 |
10 | public Instruction Deserialize(BinaryReader reader) =>
11 | new Instruction(OpCode.Pop);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Null.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Null : IHandler {
6 | public OpCode Handles => OpCode.Null;
7 | public void Handle(VM machine, Body body, Instruction instruction) =>
8 | machine.Stack.Push(null);
9 |
10 | public Instruction Deserialize(BinaryReader reader) =>
11 | new Instruction(OpCode.Null);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Ret.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Ret : IHandler {
6 | public OpCode Handles => OpCode.Ret;
7 | public void Handle(VM machine, Body body, Instruction instruction) =>
8 | machine.State = VMState.Return;
9 |
10 | public Instruction Deserialize(BinaryReader reader) =>
11 | new Instruction(OpCode.Ret);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/MemeVM/Context.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using dnlib.DotNet;
4 | using MemeVM.Translation;
5 |
6 | namespace MemeVM {
7 | static class Context {
8 | internal static IMethod Entry;
9 | internal static ModuleDef RuntimeModule;
10 | internal static readonly Random Random = new Random();
11 | internal static readonly Dictionary Bodies = new Dictionary();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/MemeVM/Translation/IHandler.cs:
--------------------------------------------------------------------------------
1 | using dnlib.DotNet;
2 | using dnlib.DotNet.Emit;
3 | using MemeVM.Translation.Helpers;
4 |
5 | namespace MemeVM.Translation {
6 | interface IHandler {
7 | OpCode[] Translates { get; }
8 | VMOpCode Output { get; }
9 | VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success);
10 | byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Jmp.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Jmp : IHandler {
6 | public OpCode Handles => OpCode.Jmp;
7 | public void Handle(VM machine, Body body, Instruction instruction) =>
8 | machine.Ip = (int) instruction.Operand;
9 |
10 | public Instruction Deserialize(BinaryReader reader) =>
11 | new Instruction(OpCode.Jmp, reader.ReadInt32());
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Int.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Int : IHandler {
6 | public OpCode Handles => OpCode.Int32;
7 | public void Handle(VM machine, Body body, Instruction instruction) =>
8 | machine.Stack.Push(instruction.Operand);
9 |
10 | public Instruction Deserialize(BinaryReader reader) =>
11 | new Instruction(OpCode.Int32, reader.ReadInt32());
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Long.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Long : IHandler {
6 | public OpCode Handles => OpCode.Int64;
7 | public void Handle(VM machine, Body body, Instruction instruction) =>
8 | machine.Stack.Push(instruction.Operand);
9 |
10 | public Instruction Deserialize(BinaryReader reader) =>
11 | new Instruction(OpCode.Int64, reader.ReadInt64());
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Ldarg.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Ldarg : IHandler {
6 | public OpCode Handles => OpCode.Ldarg;
7 | public void Handle(VM machine, Body body, Instruction instruction) =>
8 | machine.Stack.Push(machine.Parameters[(short)instruction.Operand]);
9 |
10 | public Instruction Deserialize(BinaryReader reader) =>
11 | new Instruction(OpCode.Ldarg, reader.ReadInt16());
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Ldloc.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Ldloc : IHandler {
6 | public OpCode Handles => OpCode.Ldloc;
7 | public void Handle(VM machine, Body body, Instruction instruction) =>
8 | machine.Stack.Push(machine.Locals.Get((short)instruction.Operand));
9 |
10 | public Instruction Deserialize(BinaryReader reader) =>
11 | new Instruction(OpCode.Ldloc, reader.ReadInt16());
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Stloc.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Stloc : IHandler {
6 | public OpCode Handles => OpCode.Stloc;
7 | public void Handle(VM machine, Body body, Instruction instruction) =>
8 | machine.Locals.Set((short) instruction.Operand, machine.Stack.Pop());
9 |
10 | public Instruction Deserialize(BinaryReader reader) =>
11 | new Instruction(OpCode.Stloc, reader.ReadInt16());
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Add.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Add : IHandler {
6 | public OpCode Handles => OpCode.Add;
7 | public void Handle(VM machine, Body body, Instruction instruction) {
8 | dynamic one = machine.Stack.Pop(), two = machine.Stack.Pop();
9 |
10 | machine.Stack.Push(one + two);
11 | }
12 |
13 | public Instruction Deserialize(BinaryReader reader) =>
14 | new Instruction(OpCode.Add);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Cgt.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Cgt : IHandler {
6 | public OpCode Handles => OpCode.Cgt;
7 | public void Handle(VM machine, Body body, Instruction instruction) {
8 | dynamic one = machine.Stack.Pop(), two = machine.Stack.Pop();
9 |
10 | machine.Stack.Push(one > two);
11 | }
12 |
13 | public Instruction Deserialize(BinaryReader reader) =>
14 | new Instruction(OpCode.Cgt);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Clt.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Clt : IHandler {
6 | public OpCode Handles => OpCode.Clt;
7 | public void Handle(VM machine, Body body, Instruction instruction) {
8 | dynamic one = machine.Stack.Pop(), two = machine.Stack.Pop();
9 |
10 | machine.Stack.Push(one < two);
11 | }
12 |
13 | public Instruction Deserialize(BinaryReader reader) =>
14 | new Instruction(OpCode.Clt);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Cmp.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Cmp : IHandler {
6 | public OpCode Handles => OpCode.Cmp;
7 | public void Handle(VM machine, Body body, Instruction instruction) {
8 | dynamic one = machine.Stack.Pop(), two = machine.Stack.Pop();
9 |
10 | machine.Stack.Push(one == two);
11 | }
12 |
13 | public Instruction Deserialize(BinaryReader reader) =>
14 | new Instruction(OpCode.Cmp);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Dup.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Dup : IHandler {
6 | public OpCode Handles => OpCode.Dup;
7 | public void Handle(VM machine, Body body, Instruction instruction) {
8 | var value = machine.Stack.Pop();
9 | machine.Stack.Push(value);
10 | machine.Stack.Push(value);
11 | }
12 |
13 | public Instruction Deserialize(BinaryReader reader) =>
14 | new Instruction(OpCode.Dup);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Helpers/Offsets.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | namespace MemeVM.Translation.Helpers {
5 | class Offsets {
6 | internal Offsets() =>
7 | _offsets = new List();
8 |
9 | readonly List _offsets;
10 |
11 | internal void Add(int index, int offset) =>
12 | _offsets.Add(new Offset(index, offset));
13 |
14 | internal int Get(int index) =>
15 | _offsets.Where(o => o.Starts < index).Sum(off => off.Value) - 1 + index;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MemeVM
2 | A small virtualizer for .NET which works together with ConfuserEx
3 |
4 | ## Wtf is this???!
5 |
6 | This projects takes your existing .NET MSIL code and "translates" it to instructions only our virtual machine will understand.
7 |
8 | ## Limitations
9 |
10 | - Can be slow
11 | - Lots of unimplemented OpCodes
12 | - Branching is buggy
13 | - No support for typed references
14 | - No support for pointers
15 |
16 | # Note
17 |
18 | This is not meant to be used as a serious layer of Obfuscation, it was just an experiment.
19 | Feel free to commit if you have any improvements
20 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Jf.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Jf : IHandler {
6 | public OpCode Handles => OpCode.Jf;
7 | public void Handle(VM machine, Body body, Instruction instruction) {
8 | var value = machine.Stack.Pop();
9 | if (value == null || !(bool)value)
10 | machine.Ip = (int)instruction.Operand;
11 | }
12 |
13 | public Instruction Deserialize(BinaryReader reader) =>
14 | new Instruction(OpCode.Jf, reader.ReadInt32());
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Jt.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using MemeVM.Runtime.Engine;
3 |
4 | namespace MemeVM.Runtime.Handlers {
5 | class Jt : IHandler {
6 | public OpCode Handles => OpCode.Jt;
7 | public void Handle(VM machine, Body body, Instruction instruction) {
8 | var value = machine.Stack.Pop();
9 | if (value != null && (bool) value)
10 | machine.Ip = (int)instruction.Operand;
11 | }
12 |
13 | public Instruction Deserialize(BinaryReader reader) =>
14 | new Instruction(OpCode.Jt, reader.ReadInt32());
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Entry.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MemeVM.Runtime
4 | {
5 | public static class Entry {
6 | public static T Run(RuntimeTypeHandle handle, int index, object[] parameters) {
7 | var result = Dispatcher.Run(Type.GetTypeFromHandle(handle).Assembly, index, parameters);
8 |
9 | if (result is NoMoreStackItem)
10 | return default(T);
11 |
12 | if (typeof(T).IsEnum)
13 | return (T)Enum.ToObject(typeof(T), result);
14 |
15 | return (T)Convert.ChangeType(result, typeof(T));
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/String.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Text;
3 | using MemeVM.Runtime.Engine;
4 |
5 | namespace MemeVM.Runtime.Handlers {
6 | class String : IHandler {
7 | public OpCode Handles => OpCode.String;
8 | public void Handle(VM machine, Body body, Instruction instruction) =>
9 | machine.Stack.Push(instruction.Operand);
10 |
11 | public Instruction Deserialize(BinaryReader reader) {
12 | var len = reader.ReadInt32();
13 |
14 | return new Instruction(OpCode.String, Encoding.UTF8.GetString(reader.ReadBytes(len)));
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Dup.cs:
--------------------------------------------------------------------------------
1 | using dnlib.DotNet;
2 | using dnlib.DotNet.Emit;
3 | using MemeVM.Translation.Helpers;
4 |
5 | namespace MemeVM.Translation.Handlers {
6 | class Dup : IHandler {
7 | public OpCode[] Translates => new[] { OpCodes.Dup };
8 | public VMOpCode Output => VMOpCode.Dup;
9 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
10 | success = true;
11 | return new VMInstruction(VMOpCode.Dup);
12 | }
13 |
14 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) =>
15 | new[] { (byte)VMOpCode.Dup };
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Ret.cs:
--------------------------------------------------------------------------------
1 | using dnlib.DotNet;
2 | using dnlib.DotNet.Emit;
3 | using MemeVM.Translation.Helpers;
4 |
5 | namespace MemeVM.Translation.Handlers {
6 | class Ret : IHandler {
7 | public OpCode[] Translates => new[] { OpCodes.Ret };
8 | public VMOpCode Output => VMOpCode.Ret;
9 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
10 | success = true;
11 | return new VMInstruction(VMOpCode.Ret);
12 | }
13 |
14 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
15 | return new[] { (byte)VMOpCode.Ret };
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Ldelem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | /*class Ldelem : IHandler {
8 | public OpCode[] Translates => new[] { OpCodes.Ldelem, OpCodes.Ldelem_Ref };
9 | public VMOpCode Output => VMOpCode.Ldelem;
10 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
11 | throw new NotImplementedException();
12 | }
13 |
14 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
15 | throw new NotImplementedException();
16 | }
17 | }*/
18 | }
19 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Add.cs:
--------------------------------------------------------------------------------
1 | using dnlib.DotNet;
2 | using dnlib.DotNet.Emit;
3 | using MemeVM.Translation.Helpers;
4 |
5 | namespace MemeVM.Translation.Handlers {
6 | class Add : IHandler {
7 | public OpCode[] Translates => new[] { OpCodes.Add, OpCodes.Add_Ovf, OpCodes.Add_Ovf_Un };
8 | public VMOpCode Output => VMOpCode.Add;
9 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
10 | success = true;
11 | return new VMInstruction(VMOpCode.Add);
12 | }
13 |
14 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
15 | return new[] { (byte)VMOpCode.Add };
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Pop.cs:
--------------------------------------------------------------------------------
1 | using dnlib.DotNet;
2 | using dnlib.DotNet.Emit;
3 | using MemeVM.Translation.Helpers;
4 |
5 | namespace MemeVM.Translation.Handlers {
6 | class Pop : IHandler {
7 | public OpCode[] Translates => new[] { OpCodes.Pop };
8 | public VMOpCode Output => VMOpCode.Pop;
9 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
10 | success = true;
11 | return new VMInstruction(VMOpCode.Pop);
12 | }
13 |
14 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
15 | var buf = new byte[1];
16 | buf[0] = (byte)VMOpCode.Pop;
17 | return buf;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Useless.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | class Useless : IHandler {
8 | public OpCode[] Translates => new[] { OpCodes.Nop, OpCodes.Break };
9 | public VMOpCode Output => VMOpCode.UNUSED;
10 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
11 | helper.Add(index, -1);
12 | success = true;
13 | return new VMInstruction(VMOpCode.UNUSED);
14 | }
15 |
16 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) =>
17 | Array.Empty();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Ldnull.cs:
--------------------------------------------------------------------------------
1 | using dnlib.DotNet;
2 | using dnlib.DotNet.Emit;
3 | using MemeVM.Translation.Helpers;
4 |
5 | namespace MemeVM.Translation.Handlers {
6 | class Ldnull : IHandler {
7 | public OpCode[] Translates => new[] { OpCodes.Ldnull };
8 | public VMOpCode Output => VMOpCode.Null;
9 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
10 | success = true;
11 | return new VMInstruction(VMOpCode.Null);
12 | }
13 |
14 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
15 | var buf = new byte[1];
16 | buf[0] = (byte)VMOpCode.Null;
17 | return buf;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/OpCode.cs:
--------------------------------------------------------------------------------
1 | namespace MemeVM.Runtime {
2 | enum OpCode : byte {
3 | Int32,
4 | Int64,
5 | Float,
6 | Double,
7 | String,
8 | Null,
9 |
10 | Add,
11 | Sub,
12 | Mul,
13 | Div,
14 | Rem,
15 |
16 | Dup,
17 | Pop,
18 |
19 | Jmp,
20 | Jt,
21 | Jf,
22 | Je,
23 | Jne,
24 | Jge,
25 | Jgt,
26 | Jle,
27 | Jlt,
28 |
29 | Cmp,
30 | Cgt,
31 | Clt,
32 |
33 | Newarr,
34 |
35 | Ldarg,
36 | Ldloc,
37 | Ldfld,
38 | Ldelem,
39 |
40 | Starg,
41 | Stloc,
42 | Stfld,
43 | Stelem,
44 |
45 | Call,
46 |
47 | Ret
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Engine/LocalStorage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MemeVM.Runtime.Engine {
4 | class LocalStorage {
5 | object[] _locals;
6 |
7 | internal LocalStorage() =>
8 | _locals = new object[10];
9 |
10 | ~LocalStorage() {
11 | Array.Clear(_locals, 0, _locals.Length);
12 | _locals = null;
13 | }
14 |
15 | internal object Get(short index) =>
16 | _locals[index];
17 |
18 | internal void Set(short index, object val) {
19 | if (index >= _locals.Length) {
20 | var arr = new object[2 * _locals.Length];
21 | Array.Copy(_locals, 0, arr, 0, _locals.Length);
22 | _locals = arr;
23 | }
24 |
25 | _locals[index] = val;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Dispatcher.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Reflection;
3 | using MemeVM.Runtime.Engine;
4 |
5 | namespace MemeVM.Runtime {
6 | static class Dispatcher {
7 | static readonly Dictionary Bodies = new Dictionary();
8 |
9 | internal static object Run(Assembly asm, int index, object[] parameters) {
10 | var body = GetBody(asm);
11 | body.CurrentAssembly = asm;
12 |
13 | var instance = new VM(body.GetMethod(index).ToArray(), body, parameters);
14 | return instance.Run();
15 | }
16 |
17 | internal static Body GetBody(Assembly asm) {
18 | if (!Bodies.ContainsKey(asm))
19 | Bodies.Add(asm, new Body(asm.GetManifestResourceStream(" ")));
20 |
21 | return Bodies[asm];
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/MemeVM/Translation/VMOpCode.cs:
--------------------------------------------------------------------------------
1 | namespace MemeVM.Translation {
2 | enum VMOpCode : byte {
3 | Int32,
4 | Int64,
5 | Float,
6 | Double,
7 | String,
8 | Null,
9 |
10 | Add,
11 | Sub,
12 | Mul,
13 | Div,
14 | Rem,
15 |
16 | Dup,
17 | Pop,
18 |
19 | Jmp,
20 | Jt,
21 | Jf,
22 | Je,
23 | Jne,
24 | Jge,
25 | Jgt,
26 | Jle,
27 | Jlt,
28 |
29 | Cmp,
30 | Cgt,
31 | Clt,
32 |
33 | Newarr,
34 |
35 | Ldarg,
36 | Ldloc,
37 | Ldfld,
38 | Ldelem,
39 |
40 | Starg,
41 | Stloc,
42 | Stfld,
43 | Stelem,
44 |
45 | Call,
46 |
47 | Ret,
48 |
49 | //DONT CHANGE
50 | UNUSED
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Helpers/Map.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace MemeVM.Runtime.Helpers {
6 | static class Map {
7 | static Map() {
8 | foreach (var type in typeof(Map).Module.GetTypes()) {
9 | if (type.IsInterface)
10 | continue;
11 |
12 | if (!typeof(IHandler).IsAssignableFrom(type))
13 | continue;
14 |
15 | var instance = (IHandler)Activator.CreateInstance(type);
16 | OpCodeToHandler.Add(instance.Handles, instance);
17 | }
18 | }
19 |
20 | private static readonly Dictionary OpCodeToHandler = new Dictionary();
21 |
22 | internal static IHandler Lookup(OpCode code) =>
23 | OpCodeToHandler[code];
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Ldfld.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using MemeVM.Runtime.Engine;
4 |
5 | namespace MemeVM.Runtime.Handlers {
6 | class Ldfld : IHandler {
7 | public OpCode Handles => OpCode.Ldfld;
8 | public void Handle(VM machine, Body body, Instruction instruction) {
9 | var id = ((Tuple)instruction.Operand).Item1;
10 | var token = ((Tuple)instruction.Operand).Item2;
11 |
12 | var asm = body.GetReference(id);
13 | var field = asm.ManifestModule.ResolveField(token);
14 | var obj = field.IsStatic ? null : machine.Stack.Pop();
15 | machine.Stack.Push(field.GetValue(obj));
16 | }
17 |
18 | public Instruction Deserialize(BinaryReader reader) =>
19 | new Instruction(OpCode.Ldfld, new Tuple(reader.ReadInt16(), reader.ReadInt32()));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Newarr.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using MemeVM.Runtime.Engine;
4 |
5 | namespace MemeVM.Runtime.Handlers {
6 | class Newarr : IHandler {
7 | public OpCode Handles => OpCode.Newarr;
8 | public void Handle(VM machine, Body body, Instruction instruction) {
9 | var tuple = (Tuple)instruction.Operand;
10 |
11 | var refid = tuple.Item1;
12 | var token = tuple.Item2;
13 |
14 | var asm = body.GetReference(refid).ManifestModule;
15 | var type = asm.ResolveType(token);
16 | var length = (int)machine.Stack.Pop();
17 |
18 | machine.Stack.Push(Array.CreateInstance(type, length));
19 | }
20 |
21 | public Instruction Deserialize(BinaryReader reader) =>
22 | new Instruction(OpCode.Newarr, new Tuple(reader.ReadInt16(), reader.ReadInt32()));
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/MemeVM.Confuser/MemeVMProtection.cs:
--------------------------------------------------------------------------------
1 | using Confuser.Core;
2 |
3 | namespace MemeVM.Confuser {
4 | [BeforeProtection("Ki.Resources", "Ki.Constants", "Ki.AntiTamper", "Ki.ControlFlow")]
5 | public class MemeVMProtection : Protection {
6 | public override string Name => "MemeVM";
7 | public override string Description => "Virtualization for .NET";
8 | public override string Id => "memevm";
9 | public override string FullId => "xsilent007.MemeVM";
10 | public override ProtectionPreset Preset => ProtectionPreset.None;
11 |
12 | protected override void Initialize(ConfuserContext context) { }
13 |
14 | protected override void PopulatePipeline(ProtectionPipeline pipeline) {
15 | pipeline.InsertPostStage(PipelineStage.Inspection, new InjectPhase(this));
16 | pipeline.InsertPreStage(PipelineStage.ProcessModule, new VirtualizatonPhase(this));
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Int.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | class Int : IHandler {
8 | public OpCode[] Translates => new[] { OpCodes.Ldc_I4 };
9 | public VMOpCode Output => VMOpCode.Int32;
10 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
11 | success = true;
12 | return new VMInstruction(VMOpCode.Int32, (int)method.Body.Instructions[index].Operand);
13 | }
14 |
15 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
16 | var buf = new byte[5];
17 | buf[0] = (byte)VMOpCode.Int32;
18 | Array.Copy(BitConverter.GetBytes((int)instruction.Operand), 0, buf, 1, 4);
19 |
20 | return buf;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Long.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | class Long : IHandler {
8 | public OpCode[] Translates => new[] { OpCodes.Ldc_I8 };
9 | public VMOpCode Output => VMOpCode.Int64;
10 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
11 | success = true;
12 | return new VMInstruction(VMOpCode.Int32, (long)method.Body.Instructions[index].Operand);
13 | }
14 |
15 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
16 | var buf = new byte[9];
17 | buf[0] = (byte)VMOpCode.Int64;
18 |
19 | Array.Copy(BitConverter.GetBytes((long)instruction.Operand), 0, buf, 1, 8);
20 | return buf;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Stfld.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using MemeVM.Runtime.Engine;
4 |
5 | namespace MemeVM.Runtime.Handlers {
6 | class Stfld : IHandler {
7 | public OpCode Handles => OpCode.Stfld;
8 | public void Handle(VM machine, Body body, Instruction instruction) {
9 | var id = ((Tuple)instruction.Operand).Item1;
10 | var token = ((Tuple)instruction.Operand).Item2;
11 |
12 | var asm = body.GetReference(id);
13 | var field = asm.ManifestModule.ResolveField(token);
14 | var obj = field.IsStatic ? null : machine.Stack.Pop();
15 | field.SetValue(obj, Convert.ChangeType(machine.Stack.Pop(), field.FieldType));
16 | }
17 |
18 | public Instruction Deserialize(BinaryReader reader) =>
19 | new Instruction(OpCode.Stfld, new Tuple(reader.ReadInt16(), reader.ReadInt32()));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Dispatcher.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using dnlib.DotNet;
3 | using MemeVM.Translation.Helpers;
4 |
5 | namespace MemeVM.Translation {
6 | static class Dispatcher {
7 | internal static List TranslateMethod(VMBody body, MethodDef method) {
8 | var list = new List();
9 |
10 | for (var i = 0; i < method.Body.Instructions.Count; i++) {
11 | var translator = Map.Lookup(method.Body.Instructions[i].OpCode);
12 | if (translator == null)
13 | return null;
14 |
15 | var res = translator.Translate(body, method, i, body.OffsetHelper, out var good);
16 | if (res.OpCode != VMOpCode.UNUSED) list.Add(res);
17 | if (!good)
18 | return null;
19 | }
20 |
21 | //TODO: Exception handlers
22 |
23 | return list;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Ldarg.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | class Ldarg : IHandler {
8 | public OpCode[] Translates => new[] { OpCodes.Ldarg };
9 | public VMOpCode Output => VMOpCode.Ldarg;
10 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
11 | var arg = (short)method.Parameters.IndexOf((Parameter)method.Body.Instructions[index].Operand);
12 | success = true;
13 | return new VMInstruction(VMOpCode.Ldarg, arg);
14 | }
15 |
16 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
17 | var buf = new byte[3];
18 | buf[0] = (byte)VMOpCode.Ldarg;
19 | Array.Copy(BitConverter.GetBytes((short)instruction.Operand), 0, buf, 1, 2);
20 | return buf;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Ldloc.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | class Ldloc : IHandler {
8 | public OpCode[] Translates => new[] { OpCodes.Ldloc };
9 | public VMOpCode Output => VMOpCode.Ldloc;
10 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
11 | var loc = (short)method.Body.Variables.IndexOf((Local)method.Body.Instructions[index].Operand);
12 | success = true;
13 | return new VMInstruction(VMOpCode.Ldloc, loc);
14 | }
15 |
16 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
17 | var buf = new byte[3];
18 | buf[0] = (byte)VMOpCode.Ldloc;
19 | Array.Copy(BitConverter.GetBytes((short)instruction.Operand), 0, buf, 1, 2);
20 | return buf;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Starg.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | class Starg : IHandler {
8 | public OpCode[] Translates => new[] { OpCodes.Starg };
9 | public VMOpCode Output => VMOpCode.Starg;
10 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
11 | var arg = (short)method.Parameters.IndexOf((Parameter)method.Body.Instructions[index].Operand);
12 | success = true;
13 | return new VMInstruction(VMOpCode.Starg, arg);
14 | }
15 |
16 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
17 | var buf = new byte[3];
18 | buf[0] = (byte)VMOpCode.Starg;
19 | Array.Copy(BitConverter.GetBytes((short)instruction.Operand), 0, buf, 1, 2);
20 | return buf;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Stloc.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | class Stloc : IHandler {
8 | public OpCode[] Translates => new[] { OpCodes.Stloc };
9 | public VMOpCode Output => VMOpCode.Stloc;
10 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
11 | var loc = (short)method.Body.Variables.IndexOf((Local)method.Body.Instructions[index].Operand);
12 | success = true;
13 | return new VMInstruction(VMOpCode.Stloc, loc);
14 | }
15 |
16 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
17 | var buf = new byte[3];
18 | buf[0] = (byte)VMOpCode.Stloc;
19 | Array.Copy(BitConverter.GetBytes((short)instruction.Operand), 0, buf, 1, 2);
20 | return buf;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Engine/Stack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MemeVM.Runtime.Engine {
4 | class Stack {
5 | object[] _array;
6 | uint _index;
7 |
8 | internal Stack() {
9 | _array = new object[10];
10 | _index = 0;
11 | }
12 |
13 | ~Stack() {
14 | Array.Clear(_array, 0, _array.Length);
15 | _array = null;
16 | _index = 0;
17 | }
18 |
19 | internal void Push(object val) {
20 | if (_index == _array.Length) {
21 | var arr = new object[2 * _array.Length];
22 | Array.Copy(_array, 0, arr, 0, _index);
23 | _array = arr;
24 | }
25 |
26 | _array[_index++] = val;
27 | }
28 |
29 | internal object Pop() {
30 | if (_index == 0)
31 | return new NoMoreStackItem();
32 |
33 | var res = _array[--_index];
34 | _array[_index] = null;
35 | return res;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Engine/VM.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using MemeVM.Runtime.Helpers;
3 |
4 | namespace MemeVM.Runtime.Engine {
5 | class VM {
6 | readonly Instruction[] _instructions;
7 |
8 | internal int Ip;
9 | internal VMState State;
10 | internal readonly Stack Stack;
11 | internal readonly LocalStorage Locals;
12 | internal readonly Body VMBody;
13 | internal object[] Parameters;
14 |
15 | internal VM(Instruction[] program, Body body, object[] parameters) {
16 | _instructions = program;
17 |
18 | Ip = 0;
19 | State = VMState.Next;
20 | Stack = new Stack();
21 | Locals = new LocalStorage();
22 | VMBody = body;
23 | Parameters = parameters;
24 | }
25 |
26 | internal object Run() {
27 | for (;State == VMState.Next; ++Ip)
28 | Map.Lookup(_instructions[Ip].Code).Handle(this, VMBody, _instructions[Ip]);
29 |
30 | if (State == VMState.Return)
31 | return Stack.Pop();
32 |
33 | throw (Exception)Stack.Pop();
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Ldstr.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using dnlib.DotNet;
7 | using dnlib.DotNet.Emit;
8 | using MemeVM.Translation.Helpers;
9 |
10 | namespace MemeVM.Translation.Handlers {
11 | class Ldstr : IHandler {
12 | public OpCode[] Translates => new[] { OpCodes.Ldstr };
13 | public VMOpCode Output => VMOpCode.String;
14 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
15 | var operand = (string)method.Body.Instructions[index].Operand;
16 |
17 | success = true;
18 | return new VMInstruction(VMOpCode.String, operand);
19 | }
20 |
21 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
22 | var str = Encoding.UTF8.GetBytes((string)instruction.Operand);
23 | var buf = new byte[5 + str.Length];
24 | buf[0] = (byte)VMOpCode.String;
25 | Array.Copy(BitConverter.GetBytes(str.Length), 0, buf, 1, 4);
26 | Array.Copy(str, 0, buf, 5, str.Length);
27 | return buf;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Helpers/Map.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using dnlib.DotNet.Emit;
4 |
5 | namespace MemeVM.Translation.Helpers {
6 | static class Map {
7 | static Map() {
8 | foreach (var type in typeof(Map).Assembly.DefinedTypes) {
9 | if (type.IsInterface)
10 | continue;
11 |
12 | if (!typeof(IHandler).IsAssignableFrom(type))
13 | continue;
14 |
15 | var instance = (IHandler)Activator.CreateInstance(type);
16 |
17 | foreach (var regular in instance.Translates)
18 | OpCodeToHandler.Add(regular, instance);
19 |
20 | VMOpCodeToHandler.Add(instance.Output, instance);
21 | }
22 | }
23 |
24 | static readonly Dictionary OpCodeToHandler = new Dictionary();
25 | static readonly Dictionary VMOpCodeToHandler = new Dictionary();
26 |
27 | internal static IHandler Lookup(OpCode opcode) =>
28 | OpCodeToHandler.ContainsKey(opcode) ? OpCodeToHandler[opcode] : null;
29 |
30 | internal static IHandler Lookup(VMOpCode opcode) =>
31 | VMOpCodeToHandler.ContainsKey(opcode) ? VMOpCodeToHandler[opcode] : null;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/MemeVM/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("MemeVM")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("MemeVM")]
13 | [assembly: AssemblyCopyright("Copyright © xsilent007 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("ef18f7f2-1f03-481c-98f9-4a18a2f12c11")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Ldfld.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | class Ldfld : IHandler {
8 | public OpCode[] Translates => new[] { OpCodes.Ldfld, OpCodes.Ldsfld };
9 | public VMOpCode Output => VMOpCode.Ldfld;
10 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
11 | var op = ((IField)method.Body.Instructions[index].Operand).ResolveFieldDef();
12 | if (op == null) {
13 | success = false;
14 | return new VMInstruction(VMOpCode.UNUSED);
15 | }
16 |
17 | var fqname = op.Module.Assembly.FullName;
18 | if (!body.References.Contains(fqname))
19 | body.References.Add(fqname);
20 |
21 | success = true;
22 | return new VMInstruction(VMOpCode.Ldfld, new Tuple((short)body.References.IndexOf(fqname), op));
23 | }
24 |
25 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
26 | var buf = new byte[7];
27 | buf[0] = (byte)VMOpCode.Ldfld;
28 | var (refid, field) = (Tuple)instruction.Operand;
29 | Array.Copy(BitConverter.GetBytes(refid), 0, buf, 1, 2);
30 | Array.Copy(BitConverter.GetBytes(TokenGetter.GetMdToken(field)), 0, buf, 3, 4);
31 | return buf;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Stfld.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | class Stfld : IHandler {
8 | public OpCode[] Translates => new[] { OpCodes.Stfld, OpCodes.Stsfld };
9 | public VMOpCode Output => VMOpCode.Stfld;
10 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
11 | var op = ((IField)method.Body.Instructions[index].Operand).ResolveFieldDef();
12 | if (op == null) {
13 | success = false;
14 | return new VMInstruction(VMOpCode.UNUSED);
15 | }
16 |
17 | var fqname = op.Module.Assembly.FullName;
18 | if (!body.References.Contains(fqname))
19 | body.References.Add(fqname);
20 |
21 | success = true;
22 | return new VMInstruction(VMOpCode.Stfld, new Tuple((short)body.References.IndexOf(fqname), op));
23 | }
24 |
25 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
26 | var buf = new byte[7];
27 | buf[0] = (byte)VMOpCode.Stfld;
28 | var (refid, field) = (Tuple)instruction.Operand;
29 | Array.Copy(BitConverter.GetBytes(refid), 0, buf, 1, 2);
30 | Array.Copy(BitConverter.GetBytes(TokenGetter.GetMdToken(field)), 0, buf, 3, 4);
31 | return buf;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/MemeVM.Confuser/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("MemeVM.Confuser")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("MemeVM.Confuser")]
13 | [assembly: AssemblyCopyright("Copyright © xsilent007 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("77b2c83b-ca34-4738-9384-c52f0121647c")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
38 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Newarr.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | //TODO: Generics
8 | class Newarr : IHandler {
9 | public OpCode[] Translates => new[] { OpCodes.Newarr };
10 | public VMOpCode Output => VMOpCode.Newarr;
11 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
12 | var type = ((ITypeDefOrRef)method.Body.Instructions[index].Operand).ResolveTypeDef();
13 | if (type == null) {
14 | success = false;
15 | return new VMInstruction(VMOpCode.UNUSED);
16 | }
17 |
18 | var fqname = type.Module.Assembly.FullName;
19 | if (!body.References.Contains(fqname))
20 | body.References.Add(fqname);
21 |
22 | success = true;
23 | return new VMInstruction(VMOpCode.Newarr, new Tuple((short)body.References.IndexOf(fqname), type));
24 | }
25 |
26 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
27 | var buf = new byte[7];
28 | buf[0] = (byte)VMOpCode.Newarr;
29 | var (referenceid, type) = (Tuple)instruction.Operand;
30 | Array.Copy(BitConverter.GetBytes(referenceid), 0, buf, 1, 2);
31 | Array.Copy(BitConverter.GetBytes(TokenGetter.GetMdToken(type)), 0, buf, 3, 4);
32 | return buf;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/MemeVM/Translation/VMBody.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using dnlib.DotNet;
5 | using MemeVM.Translation.Helpers;
6 |
7 | namespace MemeVM.Translation {
8 | class VMBody {
9 | internal VMBody() {
10 | References = new List();
11 | MethodToIndex = new Dictionary();
12 | Translated = new Dictionary>();
13 | OffsetHelper = new Offsets();
14 | }
15 |
16 | internal List References;
17 | internal Dictionary MethodToIndex;
18 | internal Dictionary> Translated;
19 | internal Offsets OffsetHelper;
20 |
21 | internal byte[] Serialize() {
22 | var arr = new List();
23 |
24 | var rCount = References.Count;
25 | arr.AddRange(BitConverter.GetBytes(rCount));
26 | foreach (var reference in References) {
27 | arr.AddRange(BitConverter.GetBytes(reference.Length));
28 | arr.AddRange(Encoding.UTF8.GetBytes(reference));
29 | }
30 |
31 | var mCount = Translated.Count;
32 | arr.AddRange(BitConverter.GetBytes(mCount));
33 | foreach (var method in Translated.Values) {
34 | arr.AddRange(BitConverter.GetBytes(method.Count));
35 | foreach (var instruction in method) {
36 | arr.AddRange(Map.Lookup(instruction.OpCode).Serialize(this, instruction, OffsetHelper));
37 | }
38 | }
39 |
40 | return arr.ToArray();
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Comparisons.cs:
--------------------------------------------------------------------------------
1 | using dnlib.DotNet;
2 | using dnlib.DotNet.Emit;
3 | using MemeVM.Translation.Helpers;
4 |
5 | namespace MemeVM.Translation.Handlers {
6 | class Ceq : IHandler {
7 | public OpCode[] Translates => new[] { OpCodes.Ceq };
8 | public VMOpCode Output => VMOpCode.Cmp;
9 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
10 | success = true;
11 | return new VMInstruction(VMOpCode.Cmp);
12 | }
13 |
14 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) =>
15 | new[] { (byte)VMOpCode.Cmp };
16 | }
17 |
18 | class Cgt : IHandler {
19 | public OpCode[] Translates => new[] { OpCodes.Cgt };
20 | public VMOpCode Output => VMOpCode.Cgt;
21 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
22 | success = true;
23 | return new VMInstruction(VMOpCode.Cgt);
24 | }
25 |
26 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) =>
27 | new[] { (byte)VMOpCode.Cgt };
28 | }
29 |
30 | class Clt : IHandler {
31 | public OpCode[] Translates => new[] { OpCodes.Clt };
32 | public VMOpCode Output => VMOpCode.Clt;
33 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
34 | success = true;
35 | return new VMInstruction(VMOpCode.Clt);
36 | }
37 |
38 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) =>
39 | new[] { (byte)VMOpCode.Clt };
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("MemeVM.Runtime")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("MemeVM.Runtime")]
13 | [assembly: AssemblyCopyright("Copyright © xsilent007 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("14d5d12e-9a32-4516-904e-df3393626317")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
38 | [assembly: Obfuscation(Exclude = false, Feature = "+ref proxy(mode=strong,encoding=expression,internal=true,typeErasure=true);+ctrl flow(predicate=expression);+rename(renEnum=true);+constants(mode=dynamic,elements=SNPI,cfg=true)")]
39 |
--------------------------------------------------------------------------------
/MemeVM/InjectPhase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Reflection;
6 | using Confuser.Core;
7 | using dnlib.DotNet;
8 |
9 | namespace MemeVM {
10 | public class InjectPhase : ProtectionPhase {
11 | public InjectPhase(ConfuserComponent parent) : base(parent) { }
12 | public override string Name => "MemeVM.Injection";
13 | public override ProtectionTargets Targets => ProtectionTargets.Methods;
14 |
15 | protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
16 | if (!parameters.Targets.Any())
17 | return;
18 |
19 | var current = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? throw new InvalidOperationException();
20 | var runtimePath = Path.Combine(current, "MemeVM.Runtime.dll");
21 | var newPath = Path.Combine(context.OutputDirectory, "MemeVM.Runtime.dll");
22 |
23 | var cliPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Confuser.CLI.exe");
24 |
25 | Directory.CreateDirectory(Path.GetDirectoryName(newPath));
26 | File.Copy(runtimePath, newPath, true);
27 |
28 | context.Logger.Info("Protecting VM runtime...");
29 | var info = new ProcessStartInfo {
30 | FileName = cliPath,
31 | Arguments = "-n -o " + context.OutputDirectory + " " + newPath,
32 | CreateNoWindow = true,
33 | UseShellExecute = false,
34 | WindowStyle = ProcessWindowStyle.Hidden
35 | };
36 | Process.Start(info)?.WaitForExit();
37 |
38 | Context.RuntimeModule = ModuleDefMD.Load(newPath);
39 | Context.Entry = Context.RuntimeModule.Types.Single(t => t.IsPublic).Methods[0];
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Call.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | //TODO: Generic methods...
8 | class Call : IHandler {
9 | public OpCode[] Translates => new[] { OpCodes.Call, OpCodes.Callvirt, OpCodes.Newobj };
10 | public VMOpCode Output => VMOpCode.Call;
11 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
12 | var operand = method.Body.Instructions[index].Operand;
13 | if (operand is MethodSpec) {
14 | success = false;
15 | return new VMInstruction(VMOpCode.UNUSED);
16 | }
17 |
18 | var target = ((IMethod)operand).ResolveMethodDef();
19 | var fqname = target.Module.Assembly.FullName;
20 | if (!body.References.Contains(fqname))
21 | body.References.Add(fqname);
22 |
23 | success = true;
24 | return new VMInstruction(VMOpCode.Call, new Tuple((short)body.References.IndexOf(fqname), target));
25 | }
26 |
27 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
28 | var buf = new byte[8];
29 | buf[0] = (byte)VMOpCode.Call;
30 | var (referenceId, method) = (Tuple)instruction.Operand;
31 |
32 | if (!body.Translated.ContainsKey(method)) {
33 | Array.Copy(BitConverter.GetBytes(referenceId), 0, buf, 1, 2);
34 | Array.Copy(BitConverter.GetBytes(TokenGetter.GetMdToken(method)), 0, buf, 3, 4);
35 | buf[7] = 0;
36 | return buf;
37 | }
38 |
39 | Array.Copy(BitConverter.GetBytes((short)body.MethodToIndex[method]), 0, buf, 1, 2);
40 | Array.Copy(BitConverter.GetBytes(method.Parameters.Count), 0, buf, 3, 4);
41 | buf[7] = 1;
42 | return buf;
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Body.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.IO.Compression;
5 | using System.Linq;
6 | using System.Reflection;
7 | using System.Text;
8 | using MemeVM.Runtime.Helpers;
9 |
10 | namespace MemeVM.Runtime {
11 | class Body {
12 | internal Body(Stream resourceStream) {
13 | _references = new Dictionary();
14 | _methods = new List>();
15 |
16 | using (var def = new DeflateStream(resourceStream, CompressionMode.Decompress)) {
17 | using (var reader = new BinaryReader(def)) {
18 | var rCount = reader.ReadInt32();
19 | for (var i = 0; i < rCount; i++) {
20 | var len = reader.ReadInt32();
21 | _references.Add(Encoding.UTF8.GetString(reader.ReadBytes(len)), null);
22 | }
23 |
24 | var mCount = reader.ReadInt32();
25 | for (var i = 0; i < mCount; i++) {
26 | var len = reader.ReadInt32();
27 | var list = new List();
28 | for (var j = 0; j < len; j++) {
29 | var code = (OpCode)reader.ReadByte();
30 | list.Add(Map.Lookup(code).Deserialize(reader));
31 | }
32 |
33 | _methods.Add(list);
34 | }
35 | }
36 | }
37 | }
38 |
39 | readonly Dictionary _references;
40 | readonly List> _methods;
41 |
42 | internal Assembly CurrentAssembly { get; set; }
43 |
44 | internal Assembly GetReference(short index) {
45 | var pair = _references.ElementAt(index);
46 |
47 | if (pair.Value == null)
48 | _references[pair.Key] = AppDomain.CurrentDomain.Load(new AssemblyName(pair.Key));
49 |
50 | return _references[pair.Key];
51 | }
52 |
53 | internal List GetMethod(int index) =>
54 | _methods[index];
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/MemeVM.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.572
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MemeVM.Confuser", "MemeVM.Confuser\MemeVM.Confuser.csproj", "{77B2C83B-CA34-4738-9384-C52F0121647C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MemeVM", "MemeVM\MemeVM.csproj", "{EF18F7F2-1F03-481C-98F9-4A18A2F12C11}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MemeVM.Runtime", "MemeVM.Runtime\MemeVM.Runtime.csproj", "{14D5D12E-9A32-4516-904E-DF3393626317}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {77B2C83B-CA34-4738-9384-C52F0121647C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {77B2C83B-CA34-4738-9384-C52F0121647C}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {77B2C83B-CA34-4738-9384-C52F0121647C}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {77B2C83B-CA34-4738-9384-C52F0121647C}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {EF18F7F2-1F03-481C-98F9-4A18A2F12C11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {EF18F7F2-1F03-481C-98F9-4A18A2F12C11}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {EF18F7F2-1F03-481C-98F9-4A18A2F12C11}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {EF18F7F2-1F03-481C-98F9-4A18A2F12C11}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {14D5D12E-9A32-4516-904E-DF3393626317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {14D5D12E-9A32-4516-904E-DF3393626317}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {14D5D12E-9A32-4516-904E-DF3393626317}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {14D5D12E-9A32-4516-904E-DF3393626317}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {29EFAB72-200E-43AA-B91F-043CE66650CC}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/Handlers/Call.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Reflection;
5 | using MemeVM.Runtime.Engine;
6 |
7 | namespace MemeVM.Runtime.Handlers {
8 | //TODO: Generic methods
9 | class Call : IHandler {
10 | public OpCode Handles => OpCode.Call;
11 | public void Handle(VM machine, Body body, Instruction instruction) {
12 | var op = (Tuple)instruction.Operand;
13 |
14 | if (!op.Item3) {
15 | HandleNormal(machine, body, instruction);
16 | return;
17 | }
18 |
19 | var index = op.Item1;
20 | var pcount = op.Item2;
21 |
22 | var parameters = new object[pcount];
23 | for (var i = parameters.Length - 1; i >= 0; i--)
24 | parameters[i] = machine.Stack.Pop();
25 |
26 | var res = Dispatcher.Run(body.CurrentAssembly, index, parameters);
27 | if (!(res is NoMoreStackItem))
28 | machine.Stack.Push(res);
29 | }
30 |
31 | static void HandleNormal(VM machine, Body body, Instruction instruction) {
32 | var op = (Tuple)instruction.Operand;
33 |
34 | var asm = body.GetReference(op.Item1);
35 | var info = asm.ManifestModule.ResolveMember(op.Item2);
36 | var target = asm.ManifestModule.ResolveMethod(op.Item2);
37 |
38 | var rawparams = target.GetParameters();
39 | var paramscount = rawparams.Length;
40 | var parameters = new object[paramscount];
41 | for (var i = parameters.Length - 1; i >= 0; i--)
42 | parameters[i] = machine.Stack.Pop();
43 |
44 | if ((info.MemberType & MemberTypes.Constructor) == MemberTypes.Constructor) {
45 | var ctorinfo = (ConstructorInfo)info;
46 | machine.Stack.Push(ctorinfo.Invoke(parameters));
47 | return;
48 | }
49 |
50 | var methodinfo = (MethodInfo)info;
51 | var parent = methodinfo.IsStatic ? null : machine.Stack.Pop();
52 | var res = target.Invoke(parent, parameters);
53 | if (methodinfo.ReturnType != typeof(void))
54 | machine.Stack.Push(res);
55 | }
56 |
57 | public Instruction Deserialize(BinaryReader reader) =>
58 | new Instruction(OpCode.Call, new Tuple(reader.ReadInt16(), reader.ReadInt32(), reader.ReadBoolean()));
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/MemeVM.Confuser/MemeVM.Confuser.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {77B2C83B-CA34-4738-9384-C52F0121647C}
8 | Exe
9 | MemeVM.Confuser
10 | MemeVM.Confuser
11 | v4.7.2
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 | ..\Confuser.Core.dll
38 |
39 |
40 | ..\dnlib.dll
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | {ef18f7f2-1f03-481c-98f9-4a18a2f12c11}
62 | MemeVM
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/MemeVM/Translation/Handlers/Branching.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using dnlib.DotNet;
3 | using dnlib.DotNet.Emit;
4 | using MemeVM.Translation.Helpers;
5 |
6 | namespace MemeVM.Translation.Handlers {
7 | class Br : IHandler {
8 | public OpCode[] Translates => new[] { OpCodes.Br };
9 | public VMOpCode Output => VMOpCode.Jmp;
10 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
11 | var operand = method.Body.Instructions.IndexOf((Instruction)method.Body.Instructions[index].Operand);
12 | success = true;
13 | return new VMInstruction(VMOpCode.Jmp, operand);
14 | }
15 |
16 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
17 | var buf = new byte[5];
18 | buf[0] = (byte)VMOpCode.Jmp;
19 | Array.Copy(BitConverter.GetBytes(helper.Get((int)instruction.Operand)), 0, buf, 1, 4);
20 | return buf;
21 | }
22 | }
23 |
24 | class Brtrue : IHandler {
25 | public OpCode[] Translates => new[] { OpCodes.Brtrue };
26 | public VMOpCode Output => VMOpCode.Jt;
27 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
28 | var operand = method.Body.Instructions.IndexOf((Instruction)method.Body.Instructions[index].Operand);
29 | success = true;
30 | return new VMInstruction(VMOpCode.Jt, operand);
31 | }
32 |
33 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
34 | var buf = new byte[5];
35 | buf[0] = (byte)VMOpCode.Jt;
36 | Array.Copy(BitConverter.GetBytes(helper.Get((int)instruction.Operand)), 0, buf, 1, 4);
37 | return buf;
38 | }
39 | }
40 |
41 | class Brfalse : IHandler {
42 | public OpCode[] Translates => new[] { OpCodes.Brfalse };
43 | public VMOpCode Output => VMOpCode.Jf;
44 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
45 | var operand = method.Body.Instructions.IndexOf((Instruction)method.Body.Instructions[index].Operand);
46 | success = true;
47 | return new VMInstruction(VMOpCode.Jf, operand);
48 | }
49 |
50 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
51 | var buf = new byte[5];
52 | buf[0] = (byte)VMOpCode.Jf;
53 | Array.Copy(BitConverter.GetBytes(helper.Get((int)instruction.Operand)), 0, buf, 1, 4);
54 | return buf;
55 | }
56 | }
57 |
58 | class Beq : IHandler {
59 | public OpCode[] Translates => new[] { OpCodes.Beq };
60 | public VMOpCode Output => VMOpCode.Je;
61 | public VMInstruction Translate(VMBody body, MethodDef method, int index, Offsets helper, out bool success) {
62 | success = true;
63 | return new VMInstruction(VMOpCode.Je, method.Body.Instructions.IndexOf(method.Body.Instructions[index]));
64 | }
65 |
66 | public byte[] Serialize(VMBody body, VMInstruction instruction, Offsets helper) {
67 | var buf = new byte[5];
68 | buf[0] = (byte)VMOpCode.Je;
69 | Array.Copy(BitConverter.GetBytes(helper.Get((int)instruction.Operand)), 0, buf, 1, 4);
70 | return buf;
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/MemeVM.Runtime/MemeVM.Runtime.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {14D5D12E-9A32-4516-904E-DF3393626317}
8 | Library
9 | Properties
10 | MemeVM.Runtime
11 | MemeVM.Runtime
12 | v4.0
13 | 512
14 | true
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/MemeVM/MemeVM.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {EF18F7F2-1F03-481C-98F9-4A18A2F12C11}
8 | Library
9 | Properties
10 | MemeVM
11 | MemeVM
12 | v4.7.2
13 | 512
14 | true
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 | ..\Confuser.Core.dll
36 |
37 |
38 | ..\dnlib.dll
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
262 |
263 | ConfuserEx/*
--------------------------------------------------------------------------------
/MemeVM/VirtualizatonPhase.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.IO.Compression;
3 | using System.Linq;
4 | using Confuser.Core;
5 | using Confuser.Core.Services;
6 | using dnlib.DotNet;
7 | using dnlib.DotNet.Emit;
8 | using dnlib.DotNet.Writer;
9 | using MemeVM.Translation;
10 | using MemeVM.Translation.Helpers;
11 |
12 | namespace MemeVM {
13 | public class VirtualizatonPhase : ProtectionPhase {
14 | public VirtualizatonPhase(ConfuserComponent parent) : base(parent) { }
15 | public override string Name => "MemeVM.Virtualization";
16 | public override ProtectionTargets Targets => ProtectionTargets.Methods;
17 |
18 | protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
19 | if (!parameters.Targets.Any())
20 | return;
21 |
22 | context.CurrentModuleWriterListener.OnWriterEvent += InsertVMBodies;
23 |
24 | // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop
25 | foreach (MethodDef method in parameters.Targets.WithProgress(context.Logger)) {
26 | if (!method.HasBody || method.DeclaringType.IsGlobalModuleType || method.Body.HasExceptionHandlers)
27 | continue;
28 |
29 | var module = method.Module;
30 |
31 | if (!Context.Bodies.ContainsKey(module))
32 | Context.Bodies.Add(module, new VMBody());
33 |
34 | var translated = Dispatcher.TranslateMethod(Context.Bodies[module], method);
35 | if (translated == null)
36 | continue;
37 |
38 | Context.Bodies[module].Translated.Add(method, translated);
39 | Context.Bodies[module].MethodToIndex.Add(method, Context.Bodies[module].Translated.Count - 1);
40 | context.CheckCancellation();
41 | }
42 |
43 | foreach (var pair in Context.Bodies) {
44 | if (pair.Value.Translated.Count < 1)
45 | continue;
46 |
47 | var target = pair.Key.Import(Context.Entry);
48 | foreach (var translated in pair.Value.Translated.WithProgress(context.Logger)) {
49 | var method = translated.Key;
50 | method.Body = new CilBody { MaxStack = 1 };
51 | var body = method.Body.Instructions;
52 |
53 | body.Add(OpCodes.Ldtoken.ToInstruction(method.DeclaringType));
54 | body.Add(OpCodes.Ldc_I4.ToInstruction(pair.Value.MethodToIndex[method]));
55 |
56 | AddParameters(method);
57 |
58 | var genericType = method.ReturnType == method.Module.CorLibTypes.Void ? target.DeclaringType.ToTypeSig() : method.ReturnType;
59 | var sig = new MethodSpecUser((MemberRef)target, new GenericInstMethodSig(genericType));
60 | body.Add(OpCodes.Call.ToInstruction(sig));
61 |
62 | if (method.ReturnType == method.Module.CorLibTypes.Void)
63 | body.Add(OpCodes.Pop.ToInstruction());
64 |
65 | body.Add(OpCodes.Ret.ToInstruction());
66 | context.CheckCancellation();
67 | }
68 | }
69 |
70 | Context.RuntimeModule.Dispose();
71 | }
72 |
73 | static void InsertVMBodies(object sender, ModuleWriterListenerEventArgs e) {
74 | var writer = (ModuleWriterBase)sender;
75 | if (e.WriterEvent != ModuleWriterEvent.MDMemberDefRidsAllocated)
76 | return;
77 |
78 | TokenGetter.Writer = writer;
79 |
80 | var body = Context.Bodies[writer.Module];
81 | var data = body.Serialize();
82 | writer.Module.Resources.Add(new EmbeddedResource(" ", Compress(data)));
83 | }
84 |
85 | static byte[] Compress(byte[] array) {
86 | using (var ms = new MemoryStream()) {
87 | using (var def = new DeflateStream(ms, CompressionLevel.Optimal)) {
88 | def.Write(array, 0, array.Length);
89 | }
90 |
91 | return ms.ToArray();
92 | }
93 | }
94 |
95 | static void AddParameters(MethodDef method) {
96 | if (method.Parameters.Count == 0) {
97 | method.Body.Instructions.Add(OpCodes.Ldnull.ToInstruction());
98 | return;
99 | }
100 |
101 | method.Body.Instructions.Add(OpCodes.Ldc_I4.ToInstruction(method.Parameters.Count));
102 | method.Body.Instructions.Add(OpCodes.Newarr.ToInstruction(method.Module.CorLibTypes.Object));
103 | method.Body.Instructions.Add(OpCodes.Dup.ToInstruction());
104 |
105 | for (var i = 0; i < method.Parameters.Count; i++) {
106 | method.Body.Instructions.Add(OpCodes.Ldc_I4.ToInstruction(i));
107 | method.Body.Instructions.Add(OpCodes.Ldarg.ToInstruction(method.Parameters[i]));
108 |
109 | var cor = method.Module.CorLibTypes;
110 | var param = method.Parameters[i];
111 | if (!param.IsHiddenThisParameter) {
112 | if (param.Type != cor.String && param.Type != cor.Object && param.Type != cor.TypedReference) {
113 | var spec = new TypeSpecUser(param.Type);
114 | method.Body.Instructions.Add(new Instruction(OpCodes.Box, spec));
115 | }
116 | }
117 |
118 | method.Body.Instructions.Add(OpCodes.Stelem_Ref.ToInstruction());
119 | method.Body.Instructions.Add(OpCodes.Dup.ToInstruction());
120 | }
121 |
122 | method.Body.Instructions.Remove(method.Body.Instructions.Last());
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------