Skip to content

Commit 373a68b

Browse files
authored
Merge c8efe56 into b8f7e0d
2 parents b8f7e0d + c8efe56 commit 373a68b

File tree

12 files changed

+291
-117
lines changed

12 files changed

+291
-117
lines changed

Confuser.Renamer/AnalyzePhase.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ protected override void Execute(ConfuserContext context, ProtectionParameters pa
4242
foreach (var res in module.Resources)
4343
service.AddReservedIdentifier(res.Name);
4444
}
45-
else
46-
service.SetOriginalName(def);
45+
else {
46+
service.StoreNames(def);
47+
}
4748

4849
if (def is TypeDef typeDef) {
4950
service.GetVTables().GetVTable(typeDef);

Confuser.Renamer/Analyzers/VTableAnalyzer.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ public static void Analyze(INameService service, ICollection<ModuleDefMD> module
5555
var typeDef = type.BaseType?.ResolveTypeDef();
5656
var baseMethod = typeDef?.FindMethod(methodDef.Name, methodDef.Signature as MethodSig);
5757
if (baseMethod != null) {
58-
string unifiedName = service.GetOriginalFullName(slot.Overrides.MethodDef);
59-
service.SetOriginalName(slot.MethodDef, unifiedName);
60-
service.SetOriginalName(baseMethod, unifiedName);
58+
string unifiedName = service.GetNormalizedName(slot.Overrides.MethodDef);
59+
service.SetNormalizedName(slot.MethodDef, unifiedName);
60+
service.SetNormalizedName(baseMethod, unifiedName);
6161
}
6262
}
6363
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace Confuser.Renamer {
2+
public struct DisplayNormalizedName {
3+
public string DisplayName { get; }
4+
5+
public string NormalizedName { get; }
6+
7+
public DisplayNormalizedName(string displayName, string normalizedName) {
8+
DisplayName = displayName;
9+
NormalizedName = normalizedName;
10+
}
11+
}
12+
}

Confuser.Renamer/MessageDeobfuscator.cs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
namespace Confuser.Renamer {
77
public class MessageDeobfuscator {
8-
static readonly Regex MapSymbolMatcher = new Regex("_[a-zA-Z0-9]+");
9-
static readonly Regex PasswordSymbolMatcher = new Regex("[a-zA-Z0-9_$]{23,}");
8+
static readonly Regex MapSymbolRegex = new Regex("_[a-zA-Z0-9]+");
9+
static readonly Regex PasswordSymbolRegex = new Regex("[a-zA-Z0-9_$]{23,}");
1010

1111
readonly Dictionary<string, string> _symbolMap;
1212
readonly ReversibleRenamer _renamer;
@@ -34,32 +34,34 @@ public static MessageDeobfuscator Load(string symbolMapFileName) {
3434

3535
public MessageDeobfuscator(string password) => _renamer = new ReversibleRenamer(password);
3636

37-
public string Deobfuscate(string obfuscatedMessage) {
37+
public string DeobfuscateMessage(string message) {
3838
if (_symbolMap != null) {
39-
return MapSymbolMatcher.Replace(obfuscatedMessage, DecodeSymbolMap);
39+
return MapSymbolRegex.Replace(message, m => DeobfuscateSymbol(m.Value, true));
4040
}
4141

42-
return PasswordSymbolMatcher.Replace(obfuscatedMessage, DecodeSymbolPassword);
42+
return PasswordSymbolRegex.Replace(message, m => DeobfuscateSymbol(m.Value, true));
4343
}
4444

45-
string DecodeSymbolMap(Match match) {
46-
var symbol = match.Value;
47-
if (_symbolMap.TryGetValue(symbol, out string result))
48-
return ExtractShortName(result);
49-
return ExtractShortName(symbol);
50-
}
45+
public string DeobfuscateSymbol(string obfuscatedIdentifier, bool shortName) {
46+
string fullName;
5147

52-
string DecodeSymbolPassword(Match match) {
53-
var sym = match.Value;
54-
try {
55-
return ExtractShortName(_renamer.Decrypt(sym));
48+
if (_symbolMap != null) {
49+
if (!_symbolMap.TryGetValue(obfuscatedIdentifier, out fullName))
50+
fullName = obfuscatedIdentifier;
5651
}
57-
catch {
58-
return sym;
52+
else {
53+
try {
54+
fullName = _renamer.Decrypt(obfuscatedIdentifier);
55+
}
56+
catch {
57+
fullName = obfuscatedIdentifier;
58+
}
5959
}
60+
61+
return shortName ? ExtractShortName(fullName) : fullName;
6062
}
6163

62-
static string ExtractShortName(string fullName) {
64+
public static string ExtractShortName(string fullName) {
6365
const string doubleParen = "::";
6466
int doubleParenIndex = fullName.IndexOf(doubleParen, StringComparison.Ordinal);
6567
if (doubleParenIndex != -1) {

Confuser.Renamer/NameService.cs

Lines changed: 97 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ public interface INameService {
3535
void AddReference<T>(T obj, INameReference<T> reference);
3636
IList<INameReference> GetReferences(object obj);
3737

38-
void SetOriginalName(IDnlibDef obj, string fullName = null);
39-
string GetOriginalFullName(IDnlibDef obj);
38+
void StoreNames(IDnlibDef obj);
39+
void SetNormalizedName(IDnlibDef obj, string name);
40+
string GetDisplayName(IDnlibDef obj);
41+
string GetNormalizedName(IDnlibDef obj);
4042

4143
bool IsRenamed(IDnlibDef def);
4244
void SetIsRenamed(IDnlibDef def);
@@ -48,7 +50,8 @@ internal class NameService : INameService {
4850
static readonly object CanRenameKey = new object();
4951
static readonly object RenameModeKey = new object();
5052
static readonly object ReferencesKey = new object();
51-
static readonly object OriginalFullNameKey = new object();
53+
static readonly object DisplayNameKey = new object();
54+
static readonly object NormalizedNameKey = new object();
5255
static readonly object IsRenamedKey = new object();
5356

5457
readonly ConfuserContext context;
@@ -62,6 +65,7 @@ internal class NameService : INameService {
6265
readonly byte[] nameId = new byte[8];
6366
readonly Dictionary<string, string> _originalToObfuscatedNameMap = new Dictionary<string, string>();
6467
readonly Dictionary<string, string> _obfuscatedToOriginalNameMap = new Dictionary<string, string>();
68+
readonly Dictionary<string, string> _prefixesMap = new Dictionary<string, string>();
6569
internal ReversibleRenamer reversibleRenamer;
6670

6771
public NameService(ConfuserContext context) {
@@ -99,6 +103,7 @@ public bool CanRename(object obj) {
99103
return false;
100104
return context.Annotations.Get(obj, CanRenameKey, true);
101105
}
106+
102107
return false;
103108
}
104109

@@ -140,8 +145,8 @@ public void ReduceRenameMode(object obj, RenameMode val) {
140145
if (original < val)
141146
context.Annotations.Set(obj, RenameModeKey, val);
142147
if (val <= RenameMode.Reflection && obj is IDnlibDef dnlibDef) {
143-
string nameWithoutParams = GetSimplifiedFullName(dnlibDef, true);
144-
SetOriginalName(dnlibDef, nameWithoutParams);
148+
var name = ExtractDisplayNormalizedName(dnlibDef, true);
149+
SetNormalizedName(dnlibDef, name.NormalizedName);
145150
}
146151
}
147152

@@ -153,10 +158,11 @@ public void Analyze(IDnlibDef def) {
153158
if (analyze == null)
154159
analyze = context.Pipeline.FindPhase<AnalyzePhase>();
155160

156-
SetOriginalName(def);
161+
StoreNames(def);
157162
if (def is TypeDef typeDef) {
158163
GetVTables().GetVTable(typeDef);
159164
}
165+
160166
analyze.Analyze(this, context, ProtectionParameters.Empty, def, true);
161167
}
162168

@@ -199,6 +205,7 @@ string ParseGenericName(string name, out int count) {
199205
return name.Substring(0, graveIndex);
200206
}
201207
}
208+
202209
count = 0;
203210
return name;
204211
}
@@ -208,10 +215,10 @@ string ParseGenericName(string name, out int count) {
208215
public string ObfuscateName(string name, RenameMode mode) => ObfuscateName(null, name, mode, false);
209216

210217
public string ObfuscateName(IDnlibDef dnlibDef, RenameMode mode) {
211-
var originalFullName = GetOriginalFullName(dnlibDef);
218+
var normalizedName = GetNormalizedName(dnlibDef);
212219
bool preserveGenericParams = GetParam(dnlibDef, "preserveGenericParams")
213220
?.Equals("true", StringComparison.OrdinalIgnoreCase) == true;
214-
return ObfuscateName(null, originalFullName, mode, preserveGenericParams);
221+
return ObfuscateName(null, normalizedName, mode, preserveGenericParams);
215222
}
216223

217224
public string ObfuscateName(string format, string name, RenameMode mode, bool preserveGenericParams = false) {
@@ -225,20 +232,17 @@ public string ObfuscateName(string format, string name, RenameMode mode, bool pr
225232
if (string.IsNullOrEmpty(name) || mode == RenameMode.Empty)
226233
return string.Empty;
227234

228-
if (mode == RenameMode.Debug || mode == RenameMode.Retain)
229-
{
235+
if (mode == RenameMode.Debug || mode == RenameMode.Retain) {
230236
// When flattening there are issues, in case there is a . in the name of the assembly.
231237
newName = name.Replace('.', '_');
232238
newName = mode == RenameMode.Debug ? "_" + newName : newName;
233239
}
234-
else if (mode == RenameMode.Reversible)
235-
{
240+
else if (mode == RenameMode.Reversible) {
236241
if (reversibleRenamer == null)
237242
throw new ArgumentException("Password not provided for reversible renaming.");
238243
newName = reversibleRenamer.Encrypt(name);
239244
}
240-
else if (!_originalToObfuscatedNameMap.TryGetValue(name, out newName))
241-
{
245+
else if (!_originalToObfuscatedNameMap.TryGetValue(name, out newName)) {
242246
byte[] hash = Utils.Xor(Utils.SHA1(Encoding.UTF8.GetBytes(name)), nameSeed);
243247
while (true) {
244248
newName = ObfuscateNameInternal(hash, mode);
@@ -277,13 +281,19 @@ public string RandomName(RenameMode mode) {
277281
return ObfuscateName(Utils.ToHexString(random.NextBytes(16)), mode);
278282
}
279283

280-
public void SetOriginalName(IDnlibDef dnlibDef, string newFullName = null) {
284+
public void StoreNames(IDnlibDef dnlibDef) {
281285
AddReservedIdentifier(dnlibDef.Name);
282286
if (dnlibDef is TypeDef typeDef) {
283287
AddReservedIdentifier(typeDef.Namespace);
284288
}
285-
string fullName = newFullName ?? GetSimplifiedFullName(dnlibDef);
286-
context.Annotations.Set(dnlibDef, OriginalFullNameKey, fullName);
289+
290+
var name = ExtractDisplayNormalizedName(dnlibDef);
291+
context.Annotations.Set(dnlibDef, DisplayNameKey, name.DisplayName);
292+
context.Annotations.Set(dnlibDef, NormalizedNameKey, name.NormalizedName);
293+
}
294+
295+
public void SetNormalizedName(IDnlibDef dnlibDef, string name) {
296+
context.Annotations.Set(dnlibDef, NormalizedNameKey, name);
287297
}
288298

289299
public void AddReservedIdentifier(string id) => identifiers.Add(id);
@@ -318,6 +328,7 @@ public void MarkHelper(IDnlibDef def, IMarkerService marker, ConfuserComponent p
318328
if (!type.IsSpecialName && !type.IsRuntimeSpecialName)
319329
type.Name = RandomName();
320330
}
331+
321332
SetCanRename(def, false);
322333
Analyze(def);
323334
marker.Mark(def, parentComp);
@@ -326,28 +337,28 @@ public void MarkHelper(IDnlibDef def, IMarkerService marker, ConfuserComponent p
326337
#region Charsets
327338

328339
static readonly char[] asciiCharset = Enumerable.Range(32, 95)
329-
.Select(ord => (char)ord)
330-
.Except(new[] { '.' })
331-
.ToArray();
340+
.Select(ord => (char)ord)
341+
.Except(new[] {'.'})
342+
.ToArray();
332343

333-
static readonly char[] reflectionCharset = asciiCharset.Except(new[] { ' ', '[', ']' }).ToArray();
344+
static readonly char[] reflectionCharset = asciiCharset.Except(new[] {' ', '[', ']'}).ToArray();
334345

335346
static readonly char[] letterCharset = Enumerable.Range(0, 26)
336-
.SelectMany(ord => new[] { (char)('a' + ord), (char)('A' + ord) })
337-
.ToArray();
347+
.SelectMany(ord => new[] {(char)('a' + ord), (char)('A' + ord)})
348+
.ToArray();
338349

339350
static readonly char[] alphaNumCharset = Enumerable.Range(0, 26)
340-
.SelectMany(ord => new[] { (char)('a' + ord), (char)('A' + ord) })
341-
.Concat(Enumerable.Range(0, 10).Select(ord => (char)('0' + ord)))
342-
.ToArray();
351+
.SelectMany(ord => new[] {(char)('a' + ord), (char)('A' + ord)})
352+
.Concat(Enumerable.Range(0, 10).Select(ord => (char)('0' + ord)))
353+
.ToArray();
343354

344355
// Especially chosen, just to mess with people.
345356
// Inspired by: http://xkcd.com/1137/ :D
346357
static readonly char[] unicodeCharset = new char[] { }
347358
.Concat(Enumerable.Range(0x200b, 5).Select(ord => (char)ord))
348359
.Concat(Enumerable.Range(0x2029, 6).Select(ord => (char)ord))
349360
.Concat(Enumerable.Range(0x206a, 6).Select(ord => (char)ord))
350-
.Except(new[] { '\u2029' })
361+
.Except(new[] {'\u2029'})
351362
.ToArray();
352363

353364
#endregion
@@ -360,51 +371,88 @@ public IList<INameReference> GetReferences(object obj) {
360371
return context.Annotations.GetLazy(obj, ReferencesKey, key => new List<INameReference>());
361372
}
362373

363-
public string GetOriginalFullName(IDnlibDef obj) =>
364-
context.Annotations.Get(obj, OriginalFullNameKey, (string)null) ?? GetSimplifiedFullName(obj);
374+
public string GetDisplayName(IDnlibDef obj) =>
375+
context.Annotations.Get(obj, DisplayNameKey, (string)null);
376+
377+
public string GetNormalizedName(IDnlibDef obj) =>
378+
context.Annotations.Get(obj, NormalizedNameKey, (string)null);
365379

366380
public IReadOnlyDictionary<string, string> GetNameMap() => _obfuscatedToOriginalNameMap;
367381

368382
public bool IsRenamed(IDnlibDef def) => context.Annotations.Get(def, IsRenamedKey, !CanRename(def));
369383

370384
public void SetIsRenamed(IDnlibDef def) => context.Annotations.Set(def, IsRenamedKey, true);
371385

372-
string GetSimplifiedFullName(IDnlibDef dnlibDef, bool forceShortNames = false) {
373-
string result;
374-
386+
DisplayNormalizedName ExtractDisplayNormalizedName(IDnlibDef dnlibDef, bool forceShortNames = false) {
375387
var shortNames = forceShortNames ||
376388
GetParam(dnlibDef, "shortNames")?.Equals("true", StringComparison.OrdinalIgnoreCase) ==
377389
true;
378-
if (shortNames) {
379-
result = dnlibDef is MethodDef ? (string)dnlibDef.Name : dnlibDef.FullName;
390+
var renameMode = GetRenameMode(dnlibDef);
391+
392+
if (dnlibDef is TypeDef typeDef) {
393+
if (typeDef.DeclaringType != null) {
394+
var outerClassName = CompressTypeName(typeDef.DeclaringType.FullName, renameMode);
395+
return
396+
new DisplayNormalizedName(dnlibDef.FullName, $"{outerClassName.NormalizedName}/{dnlibDef.Name}");
397+
}
398+
399+
return new DisplayNormalizedName(dnlibDef.FullName, dnlibDef.FullName);
380400
}
381-
else {
382-
if (dnlibDef is MethodDef methodDef) {
383-
var resultBuilder = new StringBuilder();
384-
resultBuilder.Append(methodDef.DeclaringType2?.FullName);
385-
resultBuilder.Append("::");
386-
resultBuilder.Append(dnlibDef.Name);
387-
388-
resultBuilder.Append('(');
401+
402+
var displayNameBuilder = new StringBuilder();
403+
var normalizedNameBuilder = new StringBuilder();
404+
if (dnlibDef is IMemberDef memberDef) {
405+
var declaringTypeName = CompressTypeName(memberDef.DeclaringType?.FullName ?? "", renameMode);
406+
407+
displayNameBuilder.Append(declaringTypeName.DisplayName);
408+
displayNameBuilder.Append("::");
409+
displayNameBuilder.Append(dnlibDef.Name);
410+
411+
normalizedNameBuilder.Append(declaringTypeName.NormalizedName);
412+
normalizedNameBuilder.Append("::");
413+
normalizedNameBuilder.Append(dnlibDef.Name);
414+
415+
if (memberDef is MethodDef methodDef) {
416+
displayNameBuilder.Append('(');
417+
normalizedNameBuilder.Append('(');
389418
if (methodDef.Signature is MethodSig methodSig) {
390419
var methodParams = methodSig.Params;
391420
for (var index = 0; index < methodParams.Count; index++) {
392-
resultBuilder.Append(methodParams[index]);
421+
var parameterName = CompressTypeName(methodParams[index].ToString(), renameMode);
422+
displayNameBuilder.Append(parameterName.DisplayName);
423+
normalizedNameBuilder.Append(parameterName.NormalizedName);
424+
393425
if (index < methodParams.Count - 1) {
394-
resultBuilder.Append(',');
426+
displayNameBuilder.Append(',');
427+
normalizedNameBuilder.Append(',');
395428
}
396429
}
397430
}
398-
resultBuilder.Append(')');
399431

400-
result = resultBuilder.ToString();
432+
displayNameBuilder.Append(')');
433+
normalizedNameBuilder.Append(')');
401434
}
402-
else {
403-
result = dnlibDef.FullName;
435+
}
436+
437+
return new DisplayNormalizedName(displayNameBuilder.ToString(),
438+
shortNames ? dnlibDef.Name.ToString() : normalizedNameBuilder.ToString());
439+
}
440+
441+
DisplayNormalizedName CompressTypeName(string typeName, RenameMode renameMode)
442+
{
443+
if (renameMode == RenameMode.Reversible)
444+
{
445+
if (!_prefixesMap.TryGetValue(typeName, out string prefix))
446+
{
447+
IncrementNameId();
448+
prefix = Utils.EncodeString(nameId, alphaNumCharset);
449+
_prefixesMap.Add(typeName, prefix);
404450
}
451+
452+
return new DisplayNormalizedName(typeName, prefix);
405453
}
406454

407-
return result;
455+
return new DisplayNormalizedName(typeName, typeName);
408456
}
409457
}
410458
}

Confuser.Renamer/ReferenceUtilities.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ internal static StringBuilder AppendDescription(this StringBuilder builder, IDnl
88
return builder.AppendHashedIdentifier("Name", def.FullName);
99

1010
builder.Append("Original Name").Append(": ");
11-
builder.Append(nameService.GetOriginalFullName(def));
11+
builder.Append(nameService.GetDisplayName(def));
1212
builder.Append("; ");
1313
return builder.AppendHashedIdentifier("Name", def.FullName);
1414
}

0 commit comments

Comments
 (0)