2025-06-17 20:21:28 +08:00
using dnlib.DotNet ;
using dnlib.DotNet.Emit ;
using Obfuz.Emit ;
using System.Collections.Generic ;
using UnityEngine ;
namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators
{
class BasicObfuscator : ObfuscatorBase
{
2025-07-21 11:37:29 +08:00
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 )
2025-06-17 20:21:28 +08:00
{
switch ( code )
{
case Code . Add :
{
switch ( op1 )
{
2025-07-21 11:37:29 +08:00
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 ;
}
}
2025-06-17 20:21:28 +08:00
default : return null ;
}
}
case Code . Sub :
{
switch ( op1 )
{
2025-07-21 11:37:29 +08:00
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 ;
}
}
2025-06-17 20:21:28 +08:00
default : return null ;
}
}
case Code . Mul :
{
switch ( op1 )
{
2025-07-21 11:37:29 +08:00
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 ;
}
}
2025-06-17 20:21:28 +08:00
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 )
2025-06-17 20:21:28 +08:00
{
2025-07-21 11:37:29 +08:00
IMethod opMethod = GetUnaryOpMethod ( ctx . importer , inst . OpCode . Code , op ) ;
2025-06-17 20:21:28 +08:00
if ( opMethod = = null )
{
2025-07-21 11:37:29 +08:00
Debug . LogWarning ( $"BasicObfuscator: Cannot obfuscate unary operation {inst.OpCode.Code} with different operand types: op={op}. This is a limitation of the BasicObfuscator." ) ;
2025-06-17 20:21:28 +08:00
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 )
2025-06-17 20:21:28 +08:00
{
2025-07-21 11:37:29 +08:00
IMethod opMethod = GetBinaryOpMethod ( ctx . importer , inst . OpCode . Code , op1 , op2 ) ;
2025-06-17 20:21:28 +08:00
if ( opMethod = = null )
{
2025-07-21 11:37:29 +08:00
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." ) ;
2025-06-17 20:21:28 +08:00
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 )
2025-06-17 20:21:28 +08:00
{
2025-07-21 11:37:29 +08:00
IMethod opMethod = GetUnaryOpMethod ( ctx . importer , inst . OpCode . Code , op ) ;
2025-06-17 20:21:28 +08:00
if ( opMethod = = null )
{
2025-07-21 11:37:29 +08:00
Debug . LogWarning ( $"BasicObfuscator: Cannot obfuscate unary operation {inst.OpCode.Code} with different operand types: op={op}. This is a limitation of the BasicObfuscator." ) ;
2025-06-17 20:21:28 +08:00
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 )
2025-06-17 20:21:28 +08:00
{
2025-07-21 11:37:29 +08:00
IMethod opMethod = GetBinaryOpMethod ( ctx . importer , inst . OpCode . Code , op1 , op2 ) ;
2025-06-17 20:21:28 +08:00
if ( opMethod = = null )
{
2025-07-21 11:37:29 +08:00
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." ) ;
2025-06-17 20:21:28 +08:00
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 )
2025-06-17 20:21:28 +08:00
{
2025-07-21 11:37:29 +08:00
IMethod opMethod = GetBinaryOpMethod ( ctx . importer , inst . OpCode . Code , op1 , op2 ) ;
2025-06-17 20:21:28 +08:00
if ( opMethod = = null )
{
2025-07-21 11:37:29 +08:00
Debug . LogWarning ( $"BasicObfuscator: Cannot obfuscate binary operation {inst.OpCode.Code} with operand type {op2}. This is a limitation of the BasicObfuscator." ) ;
2025-06-17 20:21:28 +08:00
return false ;
}
outputInsts . Add ( Instruction . Create ( OpCodes . Call , opMethod ) ) ;
return true ;
}
}
}