Add symbolObfusSettings.nameRandomSeed to randomise generated symbol names
Upstream assigns obfuscated names from a monotonic base-52 counter, so two builds of the same source produce an identical mapping and a build with a small source change keeps almost every previous name. An attacker who reverses build N therefore carries that work forward to build N+1. nameRandomSeed = 0 keeps the original counter, so this is opt-in and the default behaviour is unchanged.pull/36/head
parent
5932a6f9a6
commit
dcf38b3f0f
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2025 Code Philosophy
|
||||
// Copyright 2025 Code Philosophy
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -30,6 +30,11 @@ namespace Obfuz.ObfusPasses.SymbolObfus.NameMakers
|
|||
}
|
||||
|
||||
public static INameMaker CreateNameMakerBaseASCIICharSet(string namePrefix)
|
||||
{
|
||||
return CreateNameMakerBaseASCIICharSet(namePrefix, 0);
|
||||
}
|
||||
|
||||
public static INameMaker CreateNameMakerBaseASCIICharSet(string namePrefix, int seed)
|
||||
{
|
||||
var words = new List<string>();
|
||||
for (int i = 0; i < 26; i++)
|
||||
|
|
@ -37,7 +42,7 @@ namespace Obfuz.ObfusPasses.SymbolObfus.NameMakers
|
|||
words.Add(((char)('a' + i)).ToString());
|
||||
words.Add(((char)('A' + i)).ToString());
|
||||
}
|
||||
return new WordSetNameMaker(namePrefix, words);
|
||||
return new WordSetNameMaker(namePrefix, words, seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2025 Code Philosophy
|
||||
// Copyright 2025 Code Philosophy
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -28,19 +28,35 @@ namespace Obfuz.ObfusPasses.SymbolObfus.NameMakers
|
|||
{
|
||||
private readonly string _namePrefix;
|
||||
private readonly List<string> _wordSet;
|
||||
private readonly System.Random _random;
|
||||
private readonly int _nameSpace;
|
||||
private int _nextIndex;
|
||||
|
||||
public NameScope(string namePrefix, List<string> wordSet)
|
||||
public NameScope(string namePrefix, List<string> wordSet) : this(namePrefix, wordSet, 0)
|
||||
{
|
||||
}
|
||||
|
||||
// A zero seed keeps the original deterministic base-N counter. Any other seed draws
|
||||
// names at random from a space wide enough that collisions are rare; NameScopeBase
|
||||
// retries on collision, so correctness does not depend on the space being large.
|
||||
public NameScope(string namePrefix, List<string> wordSet, int seed)
|
||||
{
|
||||
_namePrefix = namePrefix;
|
||||
_wordSet = wordSet;
|
||||
_nextIndex = 0;
|
||||
_random = seed != 0 ? new System.Random(seed) : null;
|
||||
int space = 1;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
space *= wordSet.Count;
|
||||
}
|
||||
_nameSpace = space;
|
||||
}
|
||||
|
||||
protected override void BuildNewName(StringBuilder nameBuilder, string originalName, string lastName)
|
||||
{
|
||||
nameBuilder.Append(_namePrefix);
|
||||
for (int i = _nextIndex++; ;)
|
||||
for (int i = _random != null ? _random.Next(_nameSpace) : _nextIndex++; ;)
|
||||
{
|
||||
nameBuilder.Append(_wordSet[i % _wordSet.Count]);
|
||||
i = i / _wordSet.Count;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2025 Code Philosophy
|
||||
// Copyright 2025 Code Philosophy
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -27,16 +27,30 @@ namespace Obfuz.ObfusPasses.SymbolObfus.NameMakers
|
|||
{
|
||||
private readonly string _namePrefix;
|
||||
private readonly List<string> _wordSet;
|
||||
private readonly int _seed;
|
||||
private int _scopeIndex;
|
||||
|
||||
public WordSetNameMaker(string namePrefix, List<string> wordSet)
|
||||
public WordSetNameMaker(string namePrefix, List<string> wordSet) : this(namePrefix, wordSet, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public WordSetNameMaker(string namePrefix, List<string> wordSet, int seed)
|
||||
{
|
||||
_namePrefix = namePrefix;
|
||||
_wordSet = wordSet;
|
||||
_seed = seed;
|
||||
}
|
||||
|
||||
protected override INameScope CreateNameScope()
|
||||
{
|
||||
return new NameScope(_namePrefix, _wordSet);
|
||||
if (_seed == 0)
|
||||
{
|
||||
return new NameScope(_namePrefix, _wordSet);
|
||||
}
|
||||
|
||||
// Distinct per scope, otherwise every scope would emit the same sequence.
|
||||
int scopeSeed = unchecked(_seed + _scopeIndex++ * (int)0x9E3779B9);
|
||||
return new NameScope(_namePrefix, _wordSet, scopeSeed != 0 ? scopeSeed : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2025 Code Philosophy
|
||||
// Copyright 2025 Code Philosophy
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -66,7 +66,7 @@ namespace Obfuz.ObfusPasses.SymbolObfus
|
|||
_obfuscationRuleFiles = settings.ruleFiles.ToList();
|
||||
_renameRecordMap = new RenameRecordMap(settings.symbolMappingFile, settings.debug, settings.keepUnknownSymbolInSymbolMappingFile);
|
||||
_virtualMethodGroupCalculator = new VirtualMethodGroupCalculator();
|
||||
_nameMaker = settings.debug ? NameMakerFactory.CreateDebugNameMaker() : NameMakerFactory.CreateNameMakerBaseASCIICharSet(settings.obfuscatedNamePrefix);
|
||||
_nameMaker = settings.debug ? NameMakerFactory.CreateDebugNameMaker() : NameMakerFactory.CreateNameMakerBaseASCIICharSet(settings.obfuscatedNamePrefix, settings.nameRandomSeed);
|
||||
_customPolicyTypes = settings.customRenamePolicyTypes;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2025 Code Philosophy
|
||||
// Copyright 2025 Code Philosophy
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -34,6 +34,7 @@ namespace Obfuz.Settings
|
|||
public bool detectReflectionCompatibility;
|
||||
public bool keepUnknownSymbolInSymbolMappingFile;
|
||||
public string symbolMappingFile;
|
||||
public int nameRandomSeed;
|
||||
public List<string> ruleFiles;
|
||||
public List<Type> customRenamePolicyTypes;
|
||||
}
|
||||
|
|
@ -58,6 +59,9 @@ namespace Obfuz.Settings
|
|||
[Tooltip("symbol mapping file path")]
|
||||
public string symbolMappingFile = "Assets/Obfuz/SymbolObfus/symbol-mapping.xml";
|
||||
|
||||
[Tooltip("random seed for generated names. 0 keeps the original deterministic sequence; any other value randomises which name each symbol gets, so the mapping differs between builds")]
|
||||
public int nameRandomSeed = 0;
|
||||
|
||||
[Tooltip("debug symbol mapping file path, used for debugging purposes")]
|
||||
public string debugSymbolMappingFile = "Assets/Obfuz/SymbolObfus/symbol-mapping-debug.xml";
|
||||
|
||||
|
|
@ -82,6 +86,7 @@ namespace Obfuz.Settings
|
|||
detectReflectionCompatibility = detectReflectionCompatibility,
|
||||
keepUnknownSymbolInSymbolMappingFile = keepUnknownSymbolInSymbolMappingFile,
|
||||
symbolMappingFile = GetSymbolMappingFile(),
|
||||
nameRandomSeed = nameRandomSeed,
|
||||
ruleFiles = ruleFiles?.ToList() ?? new List<string>(),
|
||||
customRenamePolicyTypes = customRenamePolicyTypes?.Select(typeName => ReflectionUtil.FindUniqueTypeInCurrentAppDomain(typeName)).ToList() ?? new List<Type>(),
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue