96 lines
2.5 KiB
C#
96 lines
2.5 KiB
C#
using System;
|
|
using System.Linq;
|
|
using dnlib.DotNet.Emit;
|
|
using dnlib.DotNet.PolymorphicWriter;
|
|
using dnlib.DotNet.Writer;
|
|
using HarmonyLib;
|
|
using Obfuz.Settings;
|
|
|
|
internal static class DnlibPolymorphicContext
|
|
{
|
|
[ThreadStatic] public static byte[] OpcodeMapping;
|
|
}
|
|
|
|
[HarmonyPatch(typeof(PolymorphicMetadata), "WriteMethodBodies")]
|
|
static class WriteMethodBodiesPatch
|
|
{
|
|
static void Prefix()
|
|
{
|
|
if (!KedrExtensionSettings.Instance.enableOpcodeShuffle)
|
|
return;
|
|
|
|
var seed = HashUtil.Hash(ObfuzSettings.Instance.polymorphicDllSettings.codeGenerationSecretKey);
|
|
var opcodeMapping = Enumerable.Range(0, 248).Select(x => (byte)x).ToArray();
|
|
var rng = new System.Random((int)seed);
|
|
RandomUtil.Shuffle(opcodeMapping, rng);
|
|
|
|
DnlibPolymorphicContext.OpcodeMapping = opcodeMapping;
|
|
}
|
|
|
|
static void Finalizer()
|
|
{
|
|
DnlibPolymorphicContext.OpcodeMapping = null;
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch(typeof(MethodBodyWriterBase), "WriteOpCode")]
|
|
static class WriteOpCodePatch
|
|
{
|
|
static bool Prefix(ref ArrayWriter writer, Instruction instr)
|
|
{
|
|
if (DnlibPolymorphicContext.OpcodeMapping is null)
|
|
return true;
|
|
|
|
WriteOpCode(ref writer, instr);
|
|
return false;
|
|
}
|
|
|
|
private static void WriteOpCode(ref ArrayWriter writer, Instruction instr)
|
|
{
|
|
var code = (int)instr.OpCode.Code;
|
|
int num = code >> 8;
|
|
|
|
if (code <= 255)
|
|
{
|
|
if (code < (int)dnlib.DotNet.Emit.Code.Prefix7)
|
|
{
|
|
code = DnlibPolymorphicContext.OpcodeMapping[code];
|
|
}
|
|
|
|
writer.WriteByte((byte)code);
|
|
return;
|
|
}
|
|
|
|
switch (num)
|
|
{
|
|
case 240:
|
|
case 241:
|
|
case 242:
|
|
case 243:
|
|
case 244:
|
|
case 245:
|
|
case 246:
|
|
case 247:
|
|
case 248:
|
|
case 249:
|
|
case 250:
|
|
case 251:
|
|
case 254:
|
|
writer.WriteByte((byte)num);
|
|
writer.WriteByte((byte)instr.OpCode.Code);
|
|
return;
|
|
}
|
|
|
|
switch (instr.OpCode.Code)
|
|
{
|
|
case dnlib.DotNet.Emit.Code.UNKNOWN1:
|
|
writer.WriteByte(0);
|
|
break;
|
|
case dnlib.DotNet.Emit.Code.UNKNOWN2:
|
|
writer.WriteUInt16(0);
|
|
break;
|
|
default:
|
|
throw new Exception("Unknown opcode");
|
|
}
|
|
}
|
|
} |