添加int相关混淆算法
parent
35df6e520d
commit
e10a42f8dd
|
@ -1,9 +1,11 @@
|
||||||
namespace Obfuz.Virtualization
|
namespace Obfuz.Utils
|
||||||
{
|
{
|
||||||
public interface IRandom
|
public interface IRandom
|
||||||
{
|
{
|
||||||
int NextInt(int min, int max);
|
int NextInt(int min, int max);
|
||||||
|
|
||||||
int NextInt(int max);
|
int NextInt(int max);
|
||||||
|
|
||||||
|
int NextInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
using Obfuz.Virtualization;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Obfuz.Utils
|
||||||
|
{
|
||||||
|
public class RandomWithKey : IRandom
|
||||||
|
{
|
||||||
|
private readonly byte[] _key;
|
||||||
|
|
||||||
|
private readonly Random _random;
|
||||||
|
|
||||||
|
private int _nextIndex;
|
||||||
|
|
||||||
|
public RandomWithKey(byte[] key, int seed)
|
||||||
|
{
|
||||||
|
_key = key;
|
||||||
|
// TODO use key and seed to generate a random number
|
||||||
|
_random = new Random(GenerateSeed(key, seed));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GenerateSeed(byte[] key, int seed)
|
||||||
|
{
|
||||||
|
foreach (var b in key)
|
||||||
|
{
|
||||||
|
seed = seed * 31 + b;
|
||||||
|
}
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int NextInt(int min, int max)
|
||||||
|
{
|
||||||
|
return min + NextInt(max - min);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int NextInt(int max)
|
||||||
|
{
|
||||||
|
return (int)((uint)NextInt() % (uint)max);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetNextKeyByte()
|
||||||
|
{
|
||||||
|
if (_nextIndex >= _key.Length)
|
||||||
|
{
|
||||||
|
_nextIndex = 0;
|
||||||
|
}
|
||||||
|
return _key[_nextIndex++];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int NextInt()
|
||||||
|
{
|
||||||
|
return _random.Next() ^ GetNextKeyByte();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using dnlib.DotNet;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -8,5 +9,34 @@ namespace Obfuz.Virtualization
|
||||||
{
|
{
|
||||||
public class ConfigDataObfuscationPolicy : DataObfuscationPolicyBase
|
public class ConfigDataObfuscationPolicy : DataObfuscationPolicyBase
|
||||||
{
|
{
|
||||||
|
public override bool NeedObfuscateMethod(MethodDef method)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool NeedObfuscateInt(MethodDef method, int value)
|
||||||
|
{
|
||||||
|
return value > 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool NeedObfuscateLong(MethodDef method, long value)
|
||||||
|
{
|
||||||
|
return value > 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool NeedObfuscateFloat(MethodDef method, float value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool NeedObfuscateDouble(MethodDef method, double value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool NeedObfuscateString(MethodDef method, string value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
namespace Obfuz.Virtualization
|
using Obfuz.Utils;
|
||||||
|
|
||||||
|
namespace Obfuz.Virtualization
|
||||||
{
|
{
|
||||||
public struct CreateExpressionOptions
|
public struct CreateExpressionOptions
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Obfuz.Virtualization
|
||||||
|
{
|
||||||
|
public abstract class DataNodeCreatorBase : IDataNodeCreator
|
||||||
|
{
|
||||||
|
public abstract IDataNode CreateRandom(DataNodeType type, object value, CreateExpressionOptions options);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,9 @@
|
||||||
{
|
{
|
||||||
public abstract class DataNodeBase : IDataNode
|
public abstract class DataNodeBase : IDataNode
|
||||||
{
|
{
|
||||||
public DataNodeType Type { get; protected set; }
|
public DataNodeType Type { get; set; }
|
||||||
|
|
||||||
public IDataNode Expr { get; protected set; }
|
public abstract object Value { get; set; }
|
||||||
|
|
||||||
public abstract object Value { get; protected set; }
|
|
||||||
|
|
||||||
public abstract void Compile(CompileContext ctx);
|
public abstract void Compile(CompileContext ctx);
|
||||||
}
|
}
|
||||||
|
@ -14,12 +12,12 @@
|
||||||
|
|
||||||
public abstract class DataNodeBase<T> : DataNodeBase
|
public abstract class DataNodeBase<T> : DataNodeBase
|
||||||
{
|
{
|
||||||
public T Value2 { get; protected set; }
|
public T Value2 { get; set; }
|
||||||
|
|
||||||
public override object Value
|
public override object Value
|
||||||
{
|
{
|
||||||
get => Value2;
|
get => Value2;
|
||||||
protected set => Value2 = (T)value;
|
set => Value2 = (T)value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +29,7 @@
|
||||||
public override object Value
|
public override object Value
|
||||||
{
|
{
|
||||||
get => _value;
|
get => _value;
|
||||||
protected set => _value = value;
|
set => _value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace Obfuz.Virtualization
|
||||||
{
|
{
|
||||||
foreach (MethodDef method in type.Methods)
|
foreach (MethodDef method in type.Methods)
|
||||||
{
|
{
|
||||||
if (!method.HasBody && !_dataObfuscatorPolicy.NeedObfuscateMethod(method))
|
if (!method.HasBody || !_dataObfuscatorPolicy.NeedObfuscateMethod(method))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ namespace Obfuz.Virtualization
|
||||||
IList<Instruction> instructions = method.Body.Instructions;
|
IList<Instruction> instructions = method.Body.Instructions;
|
||||||
var obfuscatedInstructions = new List<Instruction>();
|
var obfuscatedInstructions = new List<Instruction>();
|
||||||
var resultInstructions = new List<Instruction>();
|
var resultInstructions = new List<Instruction>();
|
||||||
for (int i = 0; i < instructions.Count; )
|
for (int i = 0; i < instructions.Count; i++)
|
||||||
{
|
{
|
||||||
Instruction inst = instructions[i];
|
Instruction inst = instructions[i];
|
||||||
bool obfuscated = false;
|
bool obfuscated = false;
|
||||||
|
@ -130,10 +130,8 @@ namespace Obfuz.Virtualization
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: throw new NotSupportedException($"Unsupported operand type: {inst.OpCode.OperandType} for instruction: {inst}");
|
|
||||||
}
|
}
|
||||||
resultInstructions.Add(inst);
|
resultInstructions.Add(inst);
|
||||||
i++;
|
|
||||||
if (obfuscated)
|
if (obfuscated)
|
||||||
{
|
{
|
||||||
// current instruction may be the target of control flow instruction, so we can't remove it directly.
|
// current instruction may be the target of control flow instruction, so we can't remove it directly.
|
||||||
|
@ -141,9 +139,14 @@ namespace Obfuz.Virtualization
|
||||||
inst.OpCode = OpCodes.Nop;
|
inst.OpCode = OpCodes.Nop;
|
||||||
inst.Operand = null;
|
inst.Operand = null;
|
||||||
resultInstructions.AddRange(obfuscatedInstructions);
|
resultInstructions.AddRange(obfuscatedInstructions);
|
||||||
i += obfuscatedInstructions.Count + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instructions.Clear();
|
||||||
|
foreach (var obInst in obfuscatedInstructions)
|
||||||
|
{
|
||||||
|
instructions.Add(obInst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,34 +7,38 @@ namespace Obfuz.Virtualization
|
||||||
{
|
{
|
||||||
public class DefaultDataObfuscator : IDataObfuscator
|
public class DefaultDataObfuscator : IDataObfuscator
|
||||||
{
|
{
|
||||||
public bool ObfuscateInt(MethodDef method, int value, List<Instruction> obfuscatedInstructions)
|
private readonly RandomDataNodeCreator _nodeCreator = new RandomDataNodeCreator();
|
||||||
|
|
||||||
|
public void ObfuscateInt(MethodDef method, int value, List<Instruction> obfuscatedInstructions)
|
||||||
{
|
{
|
||||||
return false;
|
IDataNode node = _nodeCreator.CreateRandom(DataNodeType.Int32, value);
|
||||||
|
obfuscatedInstructions.Add(Instruction.CreateLdcI4(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryObfuscateLong(MethodDef method, long value, List<Instruction> obfuscatedInstructions)
|
public void ObfuscateLong(MethodDef method, long value, List<Instruction> obfuscatedInstructions)
|
||||||
{
|
{
|
||||||
return false;
|
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldc_I8, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryObfuscateFloat(MethodDef method, float value, List<Instruction> obfuscatedInstructions)
|
public void ObfuscateFloat(MethodDef method, float value, List<Instruction> obfuscatedInstructions)
|
||||||
{
|
{
|
||||||
return false;
|
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldc_R4, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryObfuscateDouble(MethodDef method, double value, List<Instruction> obfuscatedInstructions)
|
public void ObfuscateDouble(MethodDef method, double value, List<Instruction> obfuscatedInstructions)
|
||||||
{
|
{
|
||||||
return false;
|
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldc_R8, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryObfuscateBytes(MethodDef method, Array value, List<Instruction> obfuscatedInstructions)
|
public void ObfuscateBytes(MethodDef method, Array value, List<Instruction> obfuscatedInstructions)
|
||||||
{
|
{
|
||||||
return false;
|
throw new NotSupportedException();
|
||||||
|
//obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldc_I4, value.Length));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryObfuscateString(MethodDef method, string value, List<Instruction> obfuscatedInstructions)
|
public void ObfuscateString(MethodDef method, string value, List<Instruction> obfuscatedInstructions)
|
||||||
{
|
{
|
||||||
return false;
|
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldstr, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,10 @@ namespace Obfuz.Virtualization
|
||||||
|
|
||||||
public abstract void CreateArguments(DataNodeType type, object value, CreateExpressionOptions options, List<ConstValue> args);
|
public abstract void CreateArguments(DataNodeType type, object value, CreateExpressionOptions options, List<ConstValue> args);
|
||||||
|
|
||||||
public ConstExpression CreateCallable(IDataNode result, CreateExpressionOptions options)
|
public ConstExpression CreateCallable(DataNodeType type, object value, CreateExpressionOptions options)
|
||||||
{
|
{
|
||||||
var args = new List<ConstValue>();
|
var args = new List<ConstValue>();
|
||||||
CreateArguments(result.Type, result.Value, options, args);
|
CreateArguments(type, value, options, args);
|
||||||
|
|
||||||
options.depth += 1;
|
options.depth += 1;
|
||||||
var argNodes = new List<IDataNode>();
|
var argNodes = new List<IDataNode>();
|
||||||
|
@ -24,7 +24,7 @@ namespace Obfuz.Virtualization
|
||||||
argNodes.Add(argNode);
|
argNodes.Add(argNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ConstExpression(this, args.Select(a => options.expressionCreator.CreateRandom(a.type, a.value, options)).ToList(), new ConstValue(result.Type, result.Value));
|
return new ConstExpression(this, args.Select(a => options.expressionCreator.CreateRandom(a.type, a.value, options)).ToList(), new ConstValue(type, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Obfuz.Virtualization.Functions
|
||||||
{
|
{
|
||||||
int value = (int)v;
|
int value = (int)v;
|
||||||
|
|
||||||
int op1 = value >= 0 ? options.random.NextInt(value) : -options.random.NextInt(-value);
|
int op1 = options.random.NextInt();
|
||||||
int op2 = value - op1;
|
int op2 = value - op1;
|
||||||
args.Add(new ConstValue(DataNodeType.Int32, op1));
|
args.Add(new ConstValue(DataNodeType.Int32, op1));
|
||||||
args.Add(new ConstValue(DataNodeType.Int32, op2));
|
args.Add(new ConstValue(DataNodeType.Int32, op2));
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using static UnityEngine.Networking.UnityWebRequest;
|
||||||
|
|
||||||
|
namespace Obfuz.Virtualization.Functions
|
||||||
|
{
|
||||||
|
public class Int32FunctionXor : Int32FunctionBase
|
||||||
|
{
|
||||||
|
public override DataNodeType ReturnType => DataNodeType.Int32;
|
||||||
|
|
||||||
|
public override void CreateArguments(DataNodeType type, object v, CreateExpressionOptions options, List<ConstValue> args)
|
||||||
|
{
|
||||||
|
int value = (int)v;
|
||||||
|
|
||||||
|
int op1 = options.random.NextInt();
|
||||||
|
int op2 = value ^ op1;
|
||||||
|
args.Add(new ConstValue(DataNodeType.Int32, op1));
|
||||||
|
args.Add(new ConstValue(DataNodeType.Int32, op2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,8 +13,6 @@ namespace Obfuz.Virtualization
|
||||||
|
|
||||||
object Value { get; }
|
object Value { get; }
|
||||||
|
|
||||||
IDataNode Expr { get; }
|
|
||||||
|
|
||||||
void Compile(CompileContext ctx);
|
void Compile(CompileContext ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
{
|
{
|
||||||
DataNodeType ReturnType { get; }
|
DataNodeType ReturnType { get; }
|
||||||
|
|
||||||
ConstExpression CreateCallable(IDataNode result, CreateExpressionOptions options);
|
ConstExpression CreateCallable(DataNodeType type, object value, CreateExpressionOptions options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
using Obfuz.Utils;
|
||||||
|
using Obfuz.Virtualization.Functions;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Obfuz.Virtualization
|
||||||
|
{
|
||||||
|
public class RandomDataNodeCreator : DataNodeCreatorBase
|
||||||
|
{
|
||||||
|
private readonly Dictionary<DataNodeType, List<IFunction>> _functions = new Dictionary<DataNodeType, List<IFunction>>();
|
||||||
|
|
||||||
|
private readonly IRandom _random = new RandomWithKey(new byte[] { 0x1, 0x2, 0x3, 0x4 }, 0x5);
|
||||||
|
|
||||||
|
public RandomDataNodeCreator()
|
||||||
|
{
|
||||||
|
var int32Funcs = new List<IFunction>()
|
||||||
|
{
|
||||||
|
new Int32FunctionAdd(),
|
||||||
|
new Int32FunctionXor(),
|
||||||
|
};
|
||||||
|
_functions.Add(DataNodeType.Int32, int32Funcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IDataNode CreateRandom(DataNodeType type, object value, CreateExpressionOptions options)
|
||||||
|
{
|
||||||
|
if (!_functions.TryGetValue(type, out var funcs))
|
||||||
|
{
|
||||||
|
throw new System.Exception($"No functions available for type {type}");
|
||||||
|
}
|
||||||
|
if (options.depth >= 2)
|
||||||
|
{
|
||||||
|
return new ConstDataNode() { Type = type, Value = value };
|
||||||
|
}
|
||||||
|
var func = funcs[options.random.NextInt(funcs.Count)];
|
||||||
|
++options.depth;
|
||||||
|
return func.CreateCallable(type, value, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDataNode CreateRandom(DataNodeType type, object value)
|
||||||
|
{
|
||||||
|
var options = new CreateExpressionOptions
|
||||||
|
{
|
||||||
|
depth = 0,
|
||||||
|
random = _random,
|
||||||
|
expressionCreator = this,
|
||||||
|
};
|
||||||
|
return CreateRandom(type, value, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue