Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Debug readable obfuscation scheme #12

Open
wants to merge 1 commit into
base: ThreeShape.Obfuscar
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Obfuscar/Helpers/TypeReferenceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ public static string GetGenericName(this TypeReference type)
for (int i = 0; i < type.GenericParameters.Count; i++)
{
GenericParameter genericName = type.GenericParameters[i];
genericName.Name = nameMaker.UniqueName(i);
genericName.Name = nameMaker.UniqueName(i, null, genericName.Name);
}

type.GetElementType().Name = nameMaker.UniqueName(type.GenericParameters.Count);
type.GetElementType().Name = nameMaker.UniqueName(type.GenericParameters.Count, null, type.Name);
return type.Name;
}
}
Expand Down
8 changes: 4 additions & 4 deletions Obfuscar/NameGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ class NameGroup : IEnumerable<string>
{
HashSet<string> names = new HashSet<string>();

public string GetNext()
public string GetNext(string originalName)
{
int index = 0;
string name;
for (;;)
{
name = NameMaker.Instance.UniqueName(index++);
name = NameMaker.Instance.UniqueName(index++, null, originalName);
if (!names.Contains(name))
return name;
}
Expand Down Expand Up @@ -70,14 +70,14 @@ public void Remove(string name)
names.Remove(name);
}

public static string GetNext(IEnumerable<NameGroup> groups)
public static string GetNext(IEnumerable<NameGroup> groups, string originalName)
{
int index = 0;

string name;
for (;;)
{
name = NameMaker.Instance.UniqueName(index++);
name = NameMaker.Instance.UniqueName(index++, null, originalName);

bool contained = false;
foreach (NameGroup group in groups)
Expand Down
34 changes: 21 additions & 13 deletions Obfuscar/NameMaker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Obfuscar
Expand Down Expand Up @@ -74,6 +75,9 @@ internal NameMaker()
koreanChars = new string(chars.ToArray());

UseKoreanChars = false;

// inherit global debug model obfuscation settings
UseDebugVersionNames = Instance?.UseDebugVersionNames ?? false; // null possible when we create first Instance
}

private void ShuffleArray<T>(IList<T> list, Random rnd)
Expand Down Expand Up @@ -117,16 +121,20 @@ public bool UseKoreanChars
}
}

public string UniqueName(int index)
{
return UniqueName(index, null);
}
/// <summary>
/// Try to keep it readable for debug purposes (obfuscate/rename it but keep names similar to what was before obfuscation)
/// </summary>
public bool UseDebugVersionNames { get; set; }

public string UniqueName(int index, string sep)
public string UniqueName(int index, string sep, string originalName)
{
var postfix = string.IsNullOrEmpty(originalName) || !UseDebugVersionNames
? string.Empty
: "_" + originalName.Split('.', '>').Last();

// optimization for simple case
if (index < numUniqueChars)
return uniqueChars[index].ToString();
return uniqueChars[index].ToString() + postfix;

Stack<char> stack = new Stack<char>();

Expand All @@ -147,22 +155,22 @@ public string UniqueName(int index, string sep)
builder.Append(stack.Pop());
}

return builder.ToString();
return builder.ToString() + postfix;
}

public string UniqueNestedTypeName(int index)
public string UniqueNestedTypeName(int index, string originalName)
{
return UniqueName(index, null);
return UniqueName(index, null, originalName);
}

public string UniqueTypeName(int index)
public string UniqueTypeName(int index, string originalName)
{
return UniqueName(index % numUniqueChars, ".");
return UniqueName(index % numUniqueChars, ".", originalName);
}

public string UniqueNamespace(int index)
public string UniqueNamespace(int index, string originalName)
{
return UniqueName(index / numUniqueChars, ".");
return UniqueName(index / numUniqueChars, ".", originalName);
}
}
}
29 changes: 16 additions & 13 deletions Obfuscar/Obfuscator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ private void LoadFromReader(XDocument reader, string projectFileDirectory)
NameMaker.Instance.UseUnicodeChars = true;
if (Project.Settings.UseKoreanNames)
NameMaker.Instance.UseKoreanChars = true;
if (Project.Settings.UseDebugVersionNames)
NameMaker.Instance.UseDebugVersionNames = true;

LogOutput("Loading assemblies...");
LogOutput("Extra framework folders: ");
Expand Down Expand Up @@ -478,8 +480,8 @@ private void ProcessField(FieldDefinition field, TypeKey typeKey, Dictionary<str
}

var newName = Project.Settings.ReuseNames
? nameGroup.GetNext()
: NameMaker.Instance.UniqueName(_uniqueMemberNameIndex++);
? nameGroup.GetNext(field.Name)
: NameMaker.Instance.UniqueName(_uniqueMemberNameIndex++, null, field.Name);

RenameField(info, fieldKey, field, newName);
nameGroup.Add(newName);
Expand Down Expand Up @@ -539,7 +541,7 @@ public void RenameParams()

int index = 0;
foreach (GenericParameter param in type.GenericParameters)
param.Name = NameMaker.Instance.UniqueName(index++);
param.Name = NameMaker.Instance.UniqueName(index++, null, param.Name);
}
}
}
Expand All @@ -558,7 +560,7 @@ private void RenameParams(MethodDefinition method, AssemblyInfo info)
int index = 0;
foreach (GenericParameter param in method.GenericParameters)
if (param.CustomAttributes.Count == 0)
param.Name = NameMaker.Instance.UniqueName(index++);
param.Name = NameMaker.Instance.UniqueName(index++, null, param.Name);
}

/// <summary>
Expand Down Expand Up @@ -646,19 +648,19 @@ public void RenameTypes(HashSet<string> namesInXaml)
if (type.IsNested)
{
ns = "";
name = NameMaker.Instance.UniqueNestedTypeName(type.DeclaringType.NestedTypes.IndexOf(type));
name = NameMaker.Instance.UniqueNestedTypeName(type.DeclaringType.NestedTypes.IndexOf(type), type.Name);
}
else
{
if (Project.Settings.ReuseNames)
{
name = NameMaker.Instance.UniqueTypeName(typeIndex);
ns = NameMaker.Instance.UniqueNamespace(typeIndex);
name = NameMaker.Instance.UniqueTypeName(typeIndex, type.Name);
ns = NameMaker.Instance.UniqueNamespace(typeIndex, type.Name);
}
else
{
name = NameMaker.Instance.UniqueName(_uniqueTypeNameIndex);
ns = NameMaker.Instance.UniqueNamespace(_uniqueTypeNameIndex);
name = NameMaker.Instance.UniqueName(_uniqueTypeNameIndex, null, type.Name);
ns = NameMaker.Instance.UniqueNamespace(_uniqueTypeNameIndex, type.Name);
_uniqueTypeNameIndex++;
}
}
Expand Down Expand Up @@ -960,7 +962,8 @@ private int ProcessProperty(TypeKey typeKey, PropertyDefinition prop, AssemblyIn
else if (prop.CustomAttributes.Count > 0)
{
// If a property has custom attributes we don't remove the property but rename it instead.
var newName = NameMaker.Instance.UniqueName(Project.Settings.ReuseNames ? index++ : _uniqueMemberNameIndex++);
var newName = NameMaker.Instance.UniqueName(Project.Settings.ReuseNames ? index++ : _uniqueMemberNameIndex++,
null, prop.Name);
RenameProperty(info, propKey, prop, newName);
}
else
Expand Down Expand Up @@ -1259,7 +1262,7 @@ private void RenameVirtualMethod(Dictionary<TypeKey, Dictionary<ParamSig, NameGr
NameGroup[] nameGroups = GetNameGroups(baseSigNames, @group.Methods, sig);

// for an internal group, get next unused name
groupName = NameGroup.GetNext(nameGroups);
groupName = NameGroup.GetNext(nameGroups, method.Name);
@group.Name = groupName;

// set up methods to be renamed
Expand Down Expand Up @@ -1372,7 +1375,7 @@ private string GetNewName(Dictionary<ParamSig, NameGroup> sigNames, MethodDefini

NameGroup nameGroup = GetNameGroup(sigNames, sig);

string newName = nameGroup.GetNext();
string newName = nameGroup.GetNext(method.Name);

// make sure the name groups is updated
nameGroup.Add(newName);
Expand Down Expand Up @@ -1778,7 +1781,7 @@ public void ProcessStrings(MethodDefinition method,
MethodDefinition individualStringMethodDefinition;
if (!_methodByString.TryGetValue(str, out individualStringMethodDefinition))
{
string methodName = NameMaker.Instance.UniqueName(_nameIndex++);
string methodName = NameMaker.Instance.UniqueName(_nameIndex++, null, "StringReplacedWithCall");

// Add the string to the data array
byte[] stringBytes = Encoding.UTF8.GetBytes(str);
Expand Down
6 changes: 6 additions & 0 deletions Obfuscar/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public Settings(Variables vars)
ReuseNames = XmlConvert.ToBoolean(vars.GetValue("ReuseNames", "true"));
UseUnicodeNames = XmlConvert.ToBoolean(vars.GetValue("UseUnicodeNames", "false"));
UseKoreanNames = XmlConvert.ToBoolean(vars.GetValue("UseKoreanNames", "false"));
UseDebugVersionNames = XmlConvert.ToBoolean(vars.GetValue("UseDebugVersionNames", "false"));
HideStrings = XmlConvert.ToBoolean(vars.GetValue("HideStrings", "true"));
Optimize = XmlConvert.ToBoolean(vars.GetValue("OptimizeMethods", "true"));
SuppressIldasm = XmlConvert.ToBoolean(vars.GetValue("SuppressIldasm", "true"));
Expand Down Expand Up @@ -89,6 +90,11 @@ public Settings(Variables vars)

public bool UseKoreanNames { get; }

/// <summary>
/// Try to keep it readable for debug purposes (obfuscate/rename it but keep names similar to what was before obfuscation)
/// </summary>
public bool UseDebugVersionNames { get; }

public bool AbortOnInconsistentState { get; }
}
}