Skip to content

Commit 4cf3f68

Browse files
authored
Merge a9afcb3 into 949a998
2 parents 949a998 + a9afcb3 commit 4cf3f68

File tree

21 files changed

+665
-283
lines changed

21 files changed

+665
-283
lines changed

Confuser.Core/Utils.cs

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -145,47 +145,15 @@ public static string EncodeString(byte[] buff, char[] charset) {
145145
for (int i = 1; i < buff.Length; i++) {
146146
current = (current << 8) + buff[i];
147147
while (current >= charset.Length) {
148-
ret.Append(charset[current % charset.Length]);
149-
current /= charset.Length;
148+
current = Math.DivRem(current, charset.Length, out int remainder);
149+
ret.Append(charset[remainder]);
150150
}
151151
}
152152
if (current != 0)
153153
ret.Append(charset[current % charset.Length]);
154154
return ret.ToString();
155155
}
156156

157-
/// <summary>
158-
/// Returns a new string in which all occurrences of a specified string in
159-
/// <paramref name="str" /> are replaced with another specified string.
160-
/// </summary>
161-
/// <returns>
162-
/// A <see cref="string" /> equivalent to <paramref name="str" /> but with all instances of
163-
/// <paramref name="oldValue" />
164-
/// replaced with <paramref name="newValue" />.
165-
/// </returns>
166-
/// <param name="str">A string to do the replace in. </param>
167-
/// <param name="oldValue">A string to be replaced. </param>
168-
/// <param name="newValue">A string to replace all occurrences of <paramref name="oldValue" />. </param>
169-
/// <param name="comparison">One of the <see cref="StringComparison" /> values. </param>
170-
/// <remarks>Adopted from http://stackoverflow.com/a/244933 </remarks>
171-
public static string Replace(this string str, string oldValue, string newValue, StringComparison comparison) {
172-
StringBuilder sb = new StringBuilder();
173-
174-
int previousIndex = 0;
175-
int index = str.IndexOf(oldValue, comparison);
176-
while (index != -1) {
177-
sb.Append(str.Substring(previousIndex, index - previousIndex));
178-
sb.Append(newValue);
179-
index += oldValue.Length;
180-
previousIndex = index;
181-
index = str.IndexOf(oldValue, index, comparison);
182-
}
183-
sb.Append(str.Substring(previousIndex));
184-
185-
return sb.ToString();
186-
}
187-
188-
189157
/// <summary>
190158
/// Encode the buffer to a hexadecimal string.
191159
/// </summary>
@@ -208,12 +176,17 @@ public static string ToHexString(byte[] buff) {
208176
/// <param name="self">The list to remove from.</param>
209177
/// <param name="match">The predicate that defines the conditions of the elements to remove.</param>
210178
/// <returns><paramref name="self" /> for method chaining.</returns>
211-
public static IList<T> RemoveWhere<T>(this IList<T> self, Predicate<T> match) {
179+
public static void RemoveWhere<T>(this IList<T> self, Predicate<T> match) {
180+
if (self is List<T> list) {
181+
list.RemoveAll(match);
182+
return;
183+
}
184+
185+
// Switch to slow algorithm
212186
for (int i = self.Count - 1; i >= 0; i--) {
213187
if (match(self[i]))
214188
self.RemoveAt(i);
215189
}
216-
return self;
217190
}
218191

219192
/// <summary>

Confuser.Protections/AntiDebugProtection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ protected override void Execute(ConfuserContext context, ProtectionParameters pa
121121
}
122122
}
123123
if (ren) {
124-
member.Name = name.ObfuscateName(member.Name, RenameMode.Unicode);
124+
member.Name = name.ObfuscateName(member, RenameMode.Unicode);
125125
name.SetCanRename(member, false);
126126
}
127127
}

Confuser.Renamer/AnalyzePhase.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,15 @@ protected override void Execute(ConfuserContext context, ProtectionParameters pa
3434
foreach (IDnlibDef def in parameters.Targets.WithProgress(context.Logger)) {
3535
ParseParameters(def, context, service, parameters);
3636

37-
if (def is ModuleDef) {
38-
var module = (ModuleDef)def;
39-
foreach (Resource res in module.Resources)
40-
service.SetOriginalName(res, res.Name);
37+
if (def is ModuleDef module) {
38+
foreach (var res in module.Resources)
39+
service.AddReservedIdentifier(res.Name);
4140
}
4241
else
43-
service.SetOriginalName(def, def.Name);
42+
service.SetOriginalName(def);
4443

45-
if (def is TypeDef) {
46-
service.GetVTables().GetVTable((TypeDef)def);
47-
service.SetOriginalNamespace(def, ((TypeDef)def).Namespace);
44+
if (def is TypeDef typeDef) {
45+
service.GetVTables().GetVTable(typeDef);
4846
}
4947
context.CheckCancellation();
5048
}

Confuser.Renamer/Analyzers/VTableAnalyzer.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ public static void Analyze(INameService service, ICollection<ModuleDefMD> module
3333
// derived type. If the base type/interface is not in our control, we should
3434
// not rename the methods.
3535
bool baseUnderCtrl = modules.Contains(slot.MethodDef.DeclaringType.Module as ModuleDefMD);
36-
bool ifaceUnderCtrl = modules.Contains(slot.Overrides.MethodDef.DeclaringType.Module as ModuleDefMD);
37-
if ((!baseUnderCtrl && ifaceUnderCtrl) || !service.CanRename(slot.MethodDef)) {
36+
bool interfaceUnderCtrl = modules.Contains(slot.Overrides.MethodDef.DeclaringType.Module as ModuleDefMD);
37+
if (!baseUnderCtrl && interfaceUnderCtrl || !service.CanRename(slot.MethodDef)) {
3838
service.SetCanRename(slot.Overrides.MethodDef, false);
3939
}
40-
else if (baseUnderCtrl && !ifaceUnderCtrl || !service.CanRename(slot.Overrides.MethodDef)) {
40+
else if ((baseUnderCtrl && !interfaceUnderCtrl) || (!service.CanRename(slot.Overrides.MethodDef))) {
4141
service.SetCanRename(slot.MethodDef, false);
4242
}
4343

@@ -48,6 +48,17 @@ public static void Analyze(INameService service, ICollection<ModuleDefMD> module
4848
SetupOverwriteReferences(service, modules, slot, type);
4949
//CreateOverrideReference(service, slot.MethodDef, slot.Overrides.MethodDef);
5050
}
51+
52+
// For the case when method in base type implements an interface method for a derived type
53+
// do not consider method parameters to make method name the same in base type, derived type and interface
54+
var methodDef = slot.MethodDef;
55+
var typeDef = type.BaseType?.ResolveTypeDef();
56+
var baseMethod = typeDef?.FindMethod(methodDef.Name, methodDef.Signature as MethodSig);
57+
if (baseMethod != null) {
58+
string unifiedName = service.GetOriginalFullName(slot.Overrides.MethodDef);
59+
service.SetOriginalName(slot.MethodDef, unifiedName);
60+
service.SetOriginalName(baseMethod, unifiedName);
61+
}
5162
}
5263
}
5364
}
@@ -215,7 +226,7 @@ private static IEnumerable<MethodDef> FindBaseDeclarations(INameService service,
215226
unprocessed.Enqueue(slot.Overrides.MethodDef);
216227
slotsExists = true;
217228
}
218-
229+
219230
if (!slotsExists && method != currentMethod)
220231
yield return currentMethod;
221232
}
@@ -335,7 +346,7 @@ private static bool IsMatchingOverride(MethodOverride methodOverride, IMethodDef
335346

336347
var targetMethodSig = targetMethod.MethodSig;
337348
var overrideMethodSig = methodOverride.MethodDeclaration.MethodSig;
338-
349+
339350
targetMethodSig = ResolveGenericSignature(targetMethod, targetMethodSig);
340351
overrideMethodSig = ResolveGenericSignature(methodOverride.MethodDeclaration, overrideMethodSig);
341352

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Text.RegularExpressions;
5+
6+
namespace Confuser.Renamer {
7+
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,}");
10+
11+
readonly Dictionary<string, string> _symbolMap;
12+
readonly ReversibleRenamer _renamer;
13+
14+
public static MessageDeobfuscator Load(string symbolMapFileName) {
15+
if (symbolMapFileName is null)
16+
throw new ArgumentNullException(nameof(symbolMapFileName));
17+
18+
var symbolMap = new Dictionary<string, string>();
19+
using (var reader = new StreamReader(File.OpenRead(symbolMapFileName))) {
20+
var line = reader.ReadLine();
21+
while (line != null) {
22+
int tabIndex = line.IndexOf('\t');
23+
if (tabIndex == -1)
24+
throw new FileFormatException();
25+
symbolMap.Add(line.Substring(0, tabIndex), line.Substring(tabIndex + 1));
26+
line = reader.ReadLine();
27+
}
28+
}
29+
30+
return new MessageDeobfuscator(symbolMap);
31+
}
32+
33+
public MessageDeobfuscator(Dictionary<string, string> map) => _symbolMap = map ?? throw new ArgumentNullException(nameof(map));
34+
35+
public MessageDeobfuscator(string password) => _renamer = new ReversibleRenamer(password);
36+
37+
public string Deobfuscate(string obfuscatedMessage) {
38+
if (_symbolMap != null) {
39+
return MapSymbolMatcher.Replace(obfuscatedMessage, DecodeSymbolMap);
40+
}
41+
42+
return PasswordSymbolMatcher.Replace(obfuscatedMessage, DecodeSymbolPassword);
43+
}
44+
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+
}
51+
52+
string DecodeSymbolPassword(Match match) {
53+
var sym = match.Value;
54+
try {
55+
return ExtractShortName(_renamer.Decrypt(sym));
56+
}
57+
catch {
58+
return sym;
59+
}
60+
}
61+
62+
static string ExtractShortName(string fullName) {
63+
const string doubleParen = "::";
64+
int doubleParenIndex = fullName.IndexOf(doubleParen, StringComparison.Ordinal);
65+
if (doubleParenIndex != -1) {
66+
int resultStringStartIndex = doubleParenIndex + doubleParen.Length;
67+
int parenIndex = fullName.IndexOf('(', doubleParenIndex);
68+
return fullName.Substring(resultStringStartIndex,
69+
(parenIndex == -1 ? fullName.Length : parenIndex) - resultStringStartIndex);
70+
}
71+
72+
int slashIndex = fullName.IndexOf('/');
73+
if (slashIndex != -1) {
74+
return fullName.Substring(slashIndex + 1);
75+
}
76+
77+
return fullName;
78+
}
79+
}
80+
}

Confuser.Renamer/NameProtection.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ protected override void Execute(ConfuserContext context, ProtectionParameters pa
6666
if (!Directory.Exists(dir))
6767
Directory.CreateDirectory(dir);
6868

69-
using (var writer = new StreamWriter(File.OpenWrite(path))) {
69+
using (var writer = new StreamWriter(File.Create(path))) {
7070
foreach (var entry in map)
7171
writer.WriteLine("{0}\t{1}", entry.Key, entry.Value);
7272
}
7373
}
7474
}
7575
}
76-
}
76+
}

0 commit comments

Comments
 (0)