修复 AddXor的bug

backup
walon 2025-04-22 22:53:51 +08:00
parent 3fded4273c
commit 6d786330d1
6 changed files with 155 additions and 43 deletions

View File

@ -1,4 +1,5 @@
using dnlib.DotNet; using dnlib.DotNet;
using dnlib.DotNet.Emit;
using Obfuz.Utils; using Obfuz.Utils;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -23,13 +24,15 @@ namespace Obfuz.Emit
} }
} }
public class RvaDataAllocator public class ModuleRvaDataAllocator
{ {
// randomized // randomized
const int maxRvaDataSize = 0x100; const int maxRvaDataSize = 0x100;
private readonly ModuleDef _module;
private readonly IRandom _random; private readonly IRandom _random;
class RvaField class RvaField
{ {
public FieldDef holderDataField; public FieldDef holderDataField;
@ -53,49 +56,50 @@ namespace Obfuz.Emit
private TypeDef _rvaTypeDef; private TypeDef _rvaTypeDef;
private readonly Dictionary<(ModuleDef, int), TypeDef> _dataHolderTypeBySizes = new Dictionary<(ModuleDef, int), TypeDef>(); private readonly Dictionary<int, TypeDef> _dataHolderTypeBySizes = new Dictionary<int, TypeDef>();
public RvaDataAllocator(IRandom random) public ModuleRvaDataAllocator(ModuleDef mod, IRandom random)
{ {
_module = mod;
_random = random; _random = random;
} }
private (FieldDef, FieldDef) CreateDataHolderRvaField(ModuleDef mod, TypeDef dataHolderType) private (FieldDef, FieldDef) CreateDataHolderRvaField(TypeDef dataHolderType)
{ {
if (_rvaTypeDef == null) if (_rvaTypeDef == null)
{ {
mod.EnableTypeDefFindCache = false; _module.EnableTypeDefFindCache = false;
//_rvaTypeDef = mod.Find("$ObfuzRVA$", false); //_rvaTypeDef = _module.Find("$ObfuzRVA$", false);
//if (_rvaTypeDef != null) //if (_rvaTypeDef != null)
//{ //{
// throw new Exception($"can't obfuscate a obfuscated assembly"); // throw new Exception($"can't obfuscate a obfuscated assembly");
//} //}
ITypeDefOrRef objectTypeRef = mod.Import(typeof(object)); ITypeDefOrRef objectTypeRef = _module.Import(typeof(object));
_rvaTypeDef = new TypeDefUser("$Obfuz$RVA$",objectTypeRef); _rvaTypeDef = new TypeDefUser("$Obfuz$RVA$", objectTypeRef);
mod.Types.Add(_rvaTypeDef); _module.Types.Add(_rvaTypeDef);
mod.EnableTypeDefFindCache = true; _module.EnableTypeDefFindCache = true;
} }
var holderField = new FieldDefUser($"$RVA_Data{_rvaTypeDef.Fields.Count}", new FieldSig(dataHolderType.ToTypeSig()), FieldAttributes.InitOnly | FieldAttributes.Static | FieldAttributes.HasFieldRVA); var holderField = new FieldDefUser($"$RVA_Data{_rvaTypeDef.Fields.Count}", new FieldSig(dataHolderType.ToTypeSig()), FieldAttributes.InitOnly | FieldAttributes.Static | FieldAttributes.HasFieldRVA);
holderField.DeclaringType = _rvaTypeDef; holderField.DeclaringType = _rvaTypeDef;
var runtimeValueField = new FieldDefUser($"$RVA_Value{_rvaTypeDef.Fields.Count}", new FieldSig(new SZArraySig(mod.CorLibTypes.Byte)), FieldAttributes.Static); var runtimeValueField = new FieldDefUser($"$RVA_Value{_rvaTypeDef.Fields.Count}", new FieldSig(new SZArraySig(_module.CorLibTypes.Byte)), FieldAttributes.Static);
runtimeValueField.DeclaringType = _rvaTypeDef; runtimeValueField.DeclaringType = _rvaTypeDef;
return (holderField, runtimeValueField); return (holderField, runtimeValueField);
} }
private TypeDef GetDataHolderType(ModuleDef mod, int size) private TypeDef GetDataHolderType(int size)
{ {
size = (size + 15) & ~15; // align to 6 bytes size = (size + 15) & ~15; // align to 6 bytes
if (_dataHolderTypeBySizes.TryGetValue((mod, size), out var type)) if (_dataHolderTypeBySizes.TryGetValue(size, out var type))
return type; return type;
var dataHolderType = new TypeDefUser($"$ObfuzRVA$DataHolder{size}", mod.Import(typeof(ValueType))); var dataHolderType = new TypeDefUser($"$ObfuzRVA$DataHolder{size}", _module.Import(typeof(ValueType)));
dataHolderType.Layout = TypeAttributes.ExplicitLayout; dataHolderType.Layout = TypeAttributes.ExplicitLayout;
dataHolderType.PackingSize = 1; dataHolderType.PackingSize = 1;
dataHolderType.ClassSize = (uint)size; dataHolderType.ClassSize = (uint)size;
_dataHolderTypeBySizes.Add((mod, size), dataHolderType); _dataHolderTypeBySizes.Add(size, dataHolderType);
mod.Types.Add(dataHolderType); _module.Types.Add(dataHolderType);
return dataHolderType; return dataHolderType;
} }
@ -104,10 +108,10 @@ namespace Obfuz.Emit
return (size + alignment - 1) & ~(alignment - 1); return (size + alignment - 1) & ~(alignment - 1);
} }
private RvaField CreateRvaField(ModuleDef mod, int size) private RvaField CreateRvaField(int size)
{ {
TypeDef dataHolderType = GetDataHolderType(mod, size); TypeDef dataHolderType = GetDataHolderType(size);
var (holderDataField, runtimeValueField) = CreateDataHolderRvaField(mod, dataHolderType); var (holderDataField, runtimeValueField) = CreateDataHolderRvaField(dataHolderType);
var newRvaField = new RvaField var newRvaField = new RvaField
{ {
holderDataField = holderDataField, holderDataField = holderDataField,
@ -119,13 +123,13 @@ namespace Obfuz.Emit
return newRvaField; return newRvaField;
} }
private RvaField GetRvaField(ModuleDef mod, int preservedSize, int alignment) private RvaField GetRvaField(int preservedSize, int alignment)
{ {
Assert.IsTrue(preservedSize % alignment == 0); Assert.IsTrue(preservedSize % alignment == 0);
// for big size, create a new field // for big size, create a new field
if (preservedSize >= maxRvaDataSize) if (preservedSize >= maxRvaDataSize)
{ {
return CreateRvaField(mod, preservedSize); return CreateRvaField(preservedSize);
} }
if (_currentField != null) if (_currentField != null)
@ -147,61 +151,101 @@ namespace Obfuz.Emit
_currentField.FillPadding(); _currentField.FillPadding();
} }
_currentField = CreateRvaField(mod, maxRvaDataSize); _currentField = CreateRvaField(maxRvaDataSize);
return _currentField; return _currentField;
} }
public RvaData Allocate(ModuleDef mod, int value) public RvaData Allocate(int value)
{ {
RvaField field = GetRvaField(mod, 4, 4); RvaField field = GetRvaField(4, 4);
int offset = field.bytes.Count; int offset = field.bytes.Count;
Assert.IsTrue(offset % 4 == 0); Assert.IsTrue(offset % 4 == 0);
field.bytes.AddRange(BitConverter.GetBytes(value)); field.bytes.AddRange(BitConverter.GetBytes(value));
return new RvaData(field.runtimeValueField, offset, 4); return new RvaData(field.runtimeValueField, offset, 4);
} }
public RvaData Allocate(ModuleDef mod, long value) public RvaData Allocate(long value)
{ {
RvaField field = GetRvaField(mod, 8, 8); RvaField field = GetRvaField(8, 8);
int offset = field.bytes.Count; int offset = field.bytes.Count;
Assert.IsTrue(offset % 8 == 0); Assert.IsTrue(offset % 8 == 0);
field.bytes.AddRange(BitConverter.GetBytes(value)); field.bytes.AddRange(BitConverter.GetBytes(value));
return new RvaData(field.runtimeValueField, offset, 8); return new RvaData(field.runtimeValueField, offset, 8);
} }
public RvaData Allocate(ModuleDef mod, float value) public RvaData Allocate(float value)
{ {
RvaField field = GetRvaField(mod, 4, 4); RvaField field = GetRvaField(4, 4);
int offset = field.bytes.Count; int offset = field.bytes.Count;
Assert.IsTrue(offset % 4 == 0); Assert.IsTrue(offset % 4 == 0);
field.bytes.AddRange(BitConverter.GetBytes(value)); field.bytes.AddRange(BitConverter.GetBytes(value));
return new RvaData(field.runtimeValueField, offset, 4); return new RvaData(field.runtimeValueField, offset, 4);
} }
public RvaData Allocate(ModuleDef mod, double value) public RvaData Allocate(double value)
{ {
RvaField field = GetRvaField(mod, 8, 8); RvaField field = GetRvaField(8, 8);
int offset = field.bytes.Count; int offset = field.bytes.Count;
Assert.IsTrue(offset % 8 == 0); Assert.IsTrue(offset % 8 == 0);
field.bytes.AddRange(BitConverter.GetBytes(value)); field.bytes.AddRange(BitConverter.GetBytes(value));
return new RvaData(field.runtimeValueField, offset, 8); return new RvaData(field.runtimeValueField, offset, 8);
} }
public RvaData Allocate(ModuleDef mod, string value) public RvaData Allocate(string value)
{ {
byte[] bytes = Encoding.UTF8.GetBytes(value); byte[] bytes = Encoding.UTF8.GetBytes(value);
return Allocate(mod, bytes); return Allocate(bytes);
} }
public RvaData Allocate(ModuleDef mod, byte[] value) public RvaData Allocate(byte[] value)
{ {
RvaField field = GetRvaField(mod, value.Length, 1); RvaField field = GetRvaField(value.Length, 1);
int offset = field.bytes.Count; int offset = field.bytes.Count;
field.bytes.AddRange(value); field.bytes.AddRange(value);
return new RvaData(field.runtimeValueField, offset, value.Length); return new RvaData(field.runtimeValueField, offset, value.Length);
} }
public void SetFieldsRVA() private void CreateCCtorOfRvaTypeDef()
{
if (_rvaTypeDef == null)
{
return;
}
ModuleDef mod = _rvaTypeDef.Module;
var cctor = new MethodDefUser(".cctor",
MethodSig.CreateStatic(_module.CorLibTypes.Void),
MethodImplAttributes.IL | MethodImplAttributes.Managed,
MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Private);
cctor.DeclaringType = _rvaTypeDef;
//_rvaTypeDef.Methods.Add(cctor);
var body = new CilBody();
cctor.Body = body;
var ins = body.Instructions;
IMethod method = mod.Import(typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("InitializeArray", new[] { typeof(Array), typeof(RuntimeFieldHandle) }));
Assert.IsNotNull(method);
foreach (var field in _rvaFields)
{
// ldc
// newarr
// dup
// stsfld
// ldtoken
// RuntimeHelpers.InitializeArray(array, fieldHandle);
ins.Add(Instruction.Create(OpCodes.Ldc_I4, (int)field.size));
ins.Add(Instruction.Create(OpCodes.Newarr, field.runtimeValueField.FieldType.Next.ToTypeDefOrRef()));
ins.Add(Instruction.Create(OpCodes.Dup));
ins.Add(Instruction.Create(OpCodes.Stsfld, field.runtimeValueField));
ins.Add(Instruction.Create(OpCodes.Ldtoken, field.holderDataField));
ins.Add(Instruction.Create(OpCodes.Call, method));
// TODO Decrpyt
}
ins.Add(Instruction.Create(OpCodes.Ret));
}
private void SetFieldsRVA()
{ {
foreach (var field in _rvaFields) foreach (var field in _rvaFields)
{ {
@ -213,5 +257,71 @@ namespace Obfuz.Emit
field.holderDataField.InitialValue = field.bytes.ToArray(); field.holderDataField.InitialValue = field.bytes.ToArray();
} }
} }
public void Done()
{
SetFieldsRVA();
CreateCCtorOfRvaTypeDef();
}
}
public class RvaDataAllocator
{
private readonly IRandom _random;
private readonly Dictionary<ModuleDef, ModuleRvaDataAllocator> _modules = new Dictionary<ModuleDef, ModuleRvaDataAllocator>();
public RvaDataAllocator(IRandom random)
{
_random = random;
}
private ModuleRvaDataAllocator GetModuleRvaDataAllocator(ModuleDef mod)
{
if (!_modules.TryGetValue(mod, out var allocator))
{
allocator = new ModuleRvaDataAllocator(mod, _random);
_modules.Add(mod, allocator);
}
return allocator;
}
public RvaData Allocate(ModuleDef mod, int value)
{
return GetModuleRvaDataAllocator(mod).Allocate(value);
}
public RvaData Allocate(ModuleDef mod, long value)
{
return GetModuleRvaDataAllocator(mod).Allocate(value);
}
public RvaData Allocate(ModuleDef mod, float value)
{
return GetModuleRvaDataAllocator(mod).Allocate(value);
}
public RvaData Allocate(ModuleDef mod, double value)
{
return GetModuleRvaDataAllocator(mod).Allocate(value);
}
public RvaData Allocate(ModuleDef mod, string value)
{
return GetModuleRvaDataAllocator(mod).Allocate(value);
}
public RvaData Allocate(ModuleDef mod, byte[] value)
{
return GetModuleRvaDataAllocator(mod).Allocate(value);
}
public void Done()
{
foreach (var allocator in _modules.Values)
{
allocator.Done();
}
}
} }
} }

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Runtime.CompilerServices;
namespace Obfuz.Virtualization namespace Obfuz.Virtualization
{ {
@ -41,8 +42,8 @@ namespace Obfuz.Virtualization
} }
case DataNodeType.Bytes: case DataNodeType.Bytes:
{ {
// create ldstr // ldsfld
// ldtoken
// RuntimeHelpers.InitializeArray(array, fieldHandle); // RuntimeHelpers.InitializeArray(array, fieldHandle);
break; break;
} }

View File

@ -116,7 +116,7 @@ namespace Obfuz.Virtualization
ctx.output.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); ctx.output.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.offset)); output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.offset));
output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.size)); output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.size));
output.Add(Instruction.Create(OpCodes.Newarr, new SZArraySig(mod.CorLibTypes.Byte).ToTypeDefOrRef())); output.Add(Instruction.Create(OpCodes.Newarr, mod.CorLibTypes.Byte.ToTypeDefOrRef()));
output.Add(Instruction.Create(OpCodes.Ldc_I4, 0)); output.Add(Instruction.Create(OpCodes.Ldc_I4, 0));
output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.size)); output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.size));
output.Add(Instruction.Create(OpCodes.Call, convertMethod)); output.Add(Instruction.Create(OpCodes.Call, convertMethod));

View File

@ -74,7 +74,7 @@ namespace Obfuz.Virtualization
public void Stop() public void Stop()
{ {
_rvaDataAllocator.SetFieldsRVA(); _rvaDataAllocator.Done();
} }
} }
} }

View File

@ -24,7 +24,7 @@ namespace Obfuz.Virtualization.Functions
public override void CompileSelf(CompileContext ctx, List<Instruction> output) public override void CompileSelf(CompileContext ctx, List<Instruction> output)
{ {
output.Add(Instruction.Create(OpCodes.And)); output.Add(Instruction.Create(OpCodes.Xor));
} }
} }
} }

View File

@ -30,10 +30,11 @@ namespace Obfuz.Virtualization
{ {
throw new System.Exception($"No functions available for type {type}"); throw new System.Exception($"No functions available for type {type}");
} }
if (options.depth >= 4) if (options.depth >= 2)
{ {
//return new ConstDataNode() { Type = type, Value = value }; //return new ConstDataNode() { Type = type, Value = value };
return _random.NextInt(100) < 50 ? //return _random.NextInt(100) < 50 ?
return true ?
new ConstFromFieldRvaDataNode() { Type = type, Value = value } : new ConstFromFieldRvaDataNode() { Type = type, Value = value } :
new ConstDataNode() { Type = type, Value = value }; new ConstDataNode() { Type = type, Value = value };
} }