obfuz/Editor/ObfusPasses/ExprObfus/Obfuscators/BasicObfuscator.cs

283 lines
12 KiB
C#
Raw Permalink Normal View History

using dnlib.DotNet;
using dnlib.DotNet.Emit;
using Obfuz.Emit;
using System.Collections.Generic;
using UnityEngine;
namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators
{
class BasicObfuscator : ObfuscatorBase
{
private IMethod GetUnaryOpMethod(DefaultMetadataImporter importer, Code code, EvalDataType op1)
{
switch (code)
{
case Code.Neg:
{
switch (op1)
{
case EvalDataType.Int32: return importer.NegInt;
case EvalDataType.Int64: return importer.NegLong;
case EvalDataType.Float: return importer.NegFloat;
case EvalDataType.Double: return importer.NegDouble;
default: return null;
}
}
case Code.Not:
{
switch (op1)
{
case EvalDataType.Int32: return importer.NotInt;
case EvalDataType.Int64: return importer.NotLong;
default: return null;
}
}
default: return null;
}
}
private IMethod GetBinaryOpMethod(DefaultMetadataImporter importer, Code code, EvalDataType op1, EvalDataType op2)
{
switch (code)
{
case Code.Add:
{
switch (op1)
{
case EvalDataType.Int32: return op2 == op1 ? importer.AddInt : null;
case EvalDataType.Int64: return op2 == op1 ? importer.AddLong : null;
case EvalDataType.Float: return op2 == op1 ? importer.AddFloat : null;
case EvalDataType.Double: return op2 == op1 ? importer.AddDouble : null;
case EvalDataType.I:
{
switch (op2)
{
case EvalDataType.I: return importer.AddIntPtr;
case EvalDataType.Int32: return importer.AddIntPtrInt;
default: return null;
}
}
default: return null;
}
}
case Code.Sub:
{
switch (op1)
{
case EvalDataType.Int32: return op2 == op1 ? importer.SubtractInt : null;
case EvalDataType.Int64: return op2 == op1 ? importer.SubtractLong : null;
case EvalDataType.Float: return op2 == op1 ? importer.SubtractFloat : null;
case EvalDataType.Double: return op2 == op1 ? importer.SubtractDouble : null;
case EvalDataType.I:
{
switch (op2)
{
case EvalDataType.I: return importer.SubtractIntPtr;
case EvalDataType.Int32: return importer.SubtractIntPtrInt;
default: return null;
}
}
default: return null;
}
}
case Code.Mul:
{
switch (op1)
{
case EvalDataType.Int32: return op2 == op1 ? importer.MultiplyInt : null;
case EvalDataType.Int64: return op2 == op1 ? importer.MultiplyLong : null;
case EvalDataType.Float: return op2 == op1 ? importer.MultiplyFloat : null;
case EvalDataType.Double: return op2 == op1 ? importer.MultiplyDouble : null;
case EvalDataType.I:
{
switch (op2)
{
case EvalDataType.I: return importer.MultiplyIntPtr;
case EvalDataType.Int32: return importer.MultiplyIntPtrInt;
default: return null;
}
}
default: return null;
}
}
case Code.Div:
{
switch (op1)
{
case EvalDataType.Int32: return importer.DivideInt;
case EvalDataType.Int64: return importer.DivideLong;
case EvalDataType.Float: return importer.DivideFloat;
case EvalDataType.Double: return importer.DivideDouble;
default: return null;
}
}
case Code.Div_Un:
{
switch (op1)
{
case EvalDataType.Int32: return importer.DivideUnInt;
case EvalDataType.Int64: return importer.DivideUnLong;
default: return null;
}
}
case Code.Rem:
{
switch (op1)
{
case EvalDataType.Int32: return importer.RemInt;
case EvalDataType.Int64: return importer.RemLong;
case EvalDataType.Float: return importer.RemFloat;
case EvalDataType.Double: return importer.RemDouble;
default: return null;
}
}
case Code.Rem_Un:
{
switch (op1)
{
case EvalDataType.Int32: return importer.RemUnInt;
case EvalDataType.Int64: return importer.RemUnLong;
default: return null;
}
}
case Code.Neg:
{
switch (op1)
{
case EvalDataType.Int32: return importer.NegInt;
case EvalDataType.Int64: return importer.NegLong;
case EvalDataType.Float: return importer.NegFloat;
case EvalDataType.Double: return importer.NegDouble;
default: return null;
}
}
case Code.And:
{
switch (op1)
{
case EvalDataType.Int32: return importer.AndInt;
case EvalDataType.Int64: return importer.AndLong;
default: return null;
}
}
case Code.Or:
{
switch (op1)
{
case EvalDataType.Int32: return importer.OrInt;
case EvalDataType.Int64: return importer.OrLong;
default: return null;
}
}
case Code.Xor:
{
switch (op1)
{
case EvalDataType.Int32: return importer.XorInt;
case EvalDataType.Int64: return importer.XorLong;
default: return null;
}
}
case Code.Not:
{
switch (op1)
{
case EvalDataType.Int32: return importer.NotInt;
case EvalDataType.Int64: return importer.NotLong;
default: return null;
}
}
case Code.Shl:
{
switch (op1)
{
case EvalDataType.Int32: return importer.ShlInt;
case EvalDataType.Int64: return importer.ShlLong;
default: return null;
}
}
case Code.Shr:
{
switch (op1)
{
case EvalDataType.Int32: return importer.ShrInt;
case EvalDataType.Int64: return importer.ShrLong;
default: return null;
}
}
case Code.Shr_Un:
{
switch (op1)
{
case EvalDataType.Int32: return importer.ShrUnInt;
case EvalDataType.Int64: return importer.ShrUnLong;
default: return null;
}
}
default: return null;
}
}
2025-06-20 16:56:14 +08:00
public override bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
{
IMethod opMethod = GetUnaryOpMethod(ctx.importer, inst.OpCode.Code, op);
if (opMethod == null)
{
Debug.LogWarning($"BasicObfuscator: Cannot obfuscate unary operation {inst.OpCode.Code} with different operand types: op={op}. This is a limitation of the BasicObfuscator.");
return false;
}
outputInsts.Add(Instruction.Create(OpCodes.Call, opMethod));
return true;
}
2025-06-20 16:56:14 +08:00
public override bool ObfuscateBasicBinOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
{
IMethod opMethod = GetBinaryOpMethod(ctx.importer, inst.OpCode.Code, op1, op2);
if (opMethod == null)
{
Debug.LogWarning($"BasicObfuscator: Cannot obfuscate binary operation {inst.OpCode.Code} with different operand types: op1={op1}, op2={op2}, ret={ret}. This is a limitation of the BasicObfuscator.");
return false;
}
outputInsts.Add(Instruction.Create(OpCodes.Call, opMethod));
return true;
}
2025-06-20 16:56:14 +08:00
public override bool ObfuscateUnaryBitwiseOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
{
IMethod opMethod = GetUnaryOpMethod(ctx.importer, inst.OpCode.Code, op);
if (opMethod == null)
{
Debug.LogWarning($"BasicObfuscator: Cannot obfuscate unary operation {inst.OpCode.Code} with different operand types: op={op}. This is a limitation of the BasicObfuscator.");
return false;
}
outputInsts.Add(Instruction.Create(OpCodes.Call, opMethod));
return true;
}
2025-06-20 16:56:14 +08:00
public override bool ObfuscateBinBitwiseOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
{
IMethod opMethod = GetBinaryOpMethod(ctx.importer, inst.OpCode.Code, op1, op2);
if (opMethod == null)
{
Debug.LogWarning($"BasicObfuscator: Cannot obfuscate binary operation {inst.OpCode.Code} with different operand types: op1={op1}, op2={op2}, ret={ret}. This is a limitation of the BasicObfuscator.");
return false;
}
outputInsts.Add(Instruction.Create(OpCodes.Call, opMethod));
return true;
}
2025-06-20 16:56:14 +08:00
public override bool ObfuscateBitShiftOp(Instruction inst, EvalDataType op1, EvalDataType op2, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
{
IMethod opMethod = GetBinaryOpMethod(ctx.importer, inst.OpCode.Code, op1, op2);
if (opMethod == null)
{
Debug.LogWarning($"BasicObfuscator: Cannot obfuscate binary operation {inst.OpCode.Code} with operand type {op2}. This is a limitation of the BasicObfuscator.");
return false;
}
outputInsts.Add(Instruction.Create(OpCodes.Call, opMethod));
return true;
}
}
}