Skip to content
Open
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
16 changes: 11 additions & 5 deletions Confuser.Renamer/Analyzers/WPFAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,14 @@
var decodedName = HttpUtility.UrlDecode(doc.DocumentName);
var encodedName = doc.DocumentName;
if (bamlRefs.TryGetValue(decodedName, out var references)) {
var decodedDirectory = decodedName.Substring(0, decodedName.LastIndexOf('/') + 1);
var encodedDirectory = encodedName.Substring(0, encodedName.LastIndexOf('/') + 1);
var decodedLastSlash = decodedName.LastIndexOf('/') + 1;
var encodedLastSlash = encodedName.LastIndexOf('/') + 1;

var decodedDirectory = decodedName.Substring(0, decodedLastSlash);
var encodedDirectory = encodedName.Substring(0, encodedLastSlash);

var decodedFileName = decodedName.Substring(decodedLastSlash);
var encodedFileName = encodedName.Substring(encodedLastSlash);

var fileName = service.RandomName(renameMode).ToLowerInvariant();
if (decodedName.EndsWith(".BAML", StringComparison.OrdinalIgnoreCase))
Expand All @@ -78,8 +84,8 @@

if (renameOk) {
foreach (var bamlRef in references) {
bamlRef.Rename(module, decodedName, decodedNewName);
bamlRef.Rename(module, encodedName, encodedNewName);
bamlRef.Rename(module, decodedFileName, fileName);
bamlRef.Rename(module, encodedFileName, fileName);
}
doc.DocumentName = encodedNewName;
}
Expand Down Expand Up @@ -138,180 +144,180 @@
}
}

void AnalyzeMethod(ConfuserContext context, INameService service, MethodDef method) {
var dpRegInstrs = new List<Tuple<bool, Instruction>>();
var routedEvtRegInstrs = new List<Instruction>();
for (int i = 0; i < method.Body.Instructions.Count; i++) {
Instruction instr = method.Body.Instructions[i];
if ((instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt)) {
var regMethod = (IMethod)instr.Operand;

if (regMethod.DeclaringType.FullName == "System.Windows.DependencyProperty" &&
regMethod.Name.String.StartsWith("Register")) {
dpRegInstrs.Add(Tuple.Create(regMethod.Name.String.StartsWith("RegisterAttached"), instr));
}
else if (regMethod.DeclaringType.FullName == "System.Windows.EventManager" &&
regMethod.Name.String == "RegisterRoutedEvent") {
routedEvtRegInstrs.Add(instr);
}
}
else if (instr.OpCode.Code == Code.Newobj) {
var methodRef = (IMethod)instr.Operand;

if (methodRef.DeclaringType.FullName == "System.Windows.Data.PropertyGroupDescription" &&
methodRef.Name == ".ctor" && i - 1 >= 0 && method.Body.Instructions[i - 1].OpCode.Code == Code.Ldstr) {
foreach (var property in analyzer.LookupProperty((string)method.Body.Instructions[i - 1].Operand))
service.SetCanRename(property, false);
}
}
else if (instr.OpCode == OpCodes.Ldstr) {
var operand = ((string)instr.Operand).ToUpperInvariant();
if (operand.EndsWith(".BAML") || operand.EndsWith(".XAML")) {
var match = UriPattern.Match(operand);
var refModule = method.Module;
if (match.Success) {
var resourceAssemblyName = match.Groups[1].Success ? match.Groups[1].Value : string.Empty;
// Check if the expression contains a resource name (group 1)
// If it does, check if it is this assembly.
if (!string.IsNullOrWhiteSpace(resourceAssemblyName) &&
!resourceAssemblyName.Equals(method.Module.Assembly.Name.String, StringComparison.OrdinalIgnoreCase)) {
// Let's see if we can find this assembly.
refModule = context.Modules.FirstOrDefault(m =>
resourceAssemblyName.Equals(m.Assembly.Name.String,
StringComparison.OrdinalIgnoreCase));

if (refModule == null) {
// This resource points to an assembly that is not part of the obfuscation.
// Leave it alone!
return;
}
}
operand = match.Groups[2].Value;
}
else if (operand.Contains("/"))
context.Logger.WarnFormat("Fail to extract XAML name from '{0}'.", instr.Operand);

var reference = new BAMLStringReference(refModule, instr);
operand = WebUtility.UrlDecode(operand.TrimStart('/'));
var baml = operand.Substring(0, operand.Length - 5) + ".BAML";
var xaml = operand.Substring(0, operand.Length - 5) + ".XAML";
bamlRefs.AddListEntry(baml, reference);
bamlRefs.AddListEntry(xaml, reference);
}
}
}

if (dpRegInstrs.Count == 0)
return;

var traceSrv = context.Registry.GetService<ITraceService>();
MethodTrace trace = traceSrv.Trace(method);

bool erred = false;
foreach (var instrInfo in dpRegInstrs) {
int[] args = trace.TraceArguments(instrInfo.Item2);
if (args == null) {
if (!erred)
context.Logger.WarnFormat("Failed to extract dependency property name in '{0}'.", method.FullName);
erred = true;
continue;
}
Instruction ldstr = method.Body.Instructions[args[0]];
if (ldstr.OpCode.Code != Code.Ldstr) {
if (!erred)
context.Logger.WarnFormat("Failed to extract dependency property name in '{0}'.", method.FullName);
erred = true;
continue;
}

var name = (string)ldstr.Operand;
TypeDef declType = method.DeclaringType;
bool found = false;
if (instrInfo.Item1) // Attached DP
{
MethodDef accessor;
if ((accessor = declType.FindMethod("Get" + name)) != null && accessor.IsStatic) {
service.SetCanRename(accessor, false);
found = true;
}
if ((accessor = declType.FindMethod("Set" + name)) != null && accessor.IsStatic) {
service.SetCanRename(accessor, false);
found = true;
}
}

// Normal DP
// Find CLR property for attached DP as well, because it seems attached DP can be use as normal DP as well.
PropertyDef property = null;
if ((property = declType.FindProperty(name)) != null) {
service.SetCanRename(property, false);

found = true;
if (property.GetMethod != null)
service.SetCanRename(property.GetMethod, false);

if (property.SetMethod != null)
service.SetCanRename(property.SetMethod, false);

if (property.HasOtherMethods) {
foreach (MethodDef accessor in property.OtherMethods)
service.SetCanRename(accessor, false);
}
}
if (!found) {
if (instrInfo.Item1)
context.Logger.WarnFormat("Failed to find the accessors of attached dependency property '{0}' in type '{1}'.",
name, declType.FullName);
else
context.Logger.WarnFormat("Failed to find the CLR property of normal dependency property '{0}' in type '{1}'.",
name, declType.FullName);
}
}

erred = false;
foreach (Instruction instr in routedEvtRegInstrs) {
int[] args = trace.TraceArguments(instr);
if (args == null) {
if (!erred)
context.Logger.WarnFormat("Failed to extract routed event name in '{0}'.", method.FullName);
erred = true;
continue;
}
Instruction ldstr = method.Body.Instructions[args[0]];
if (ldstr.OpCode.Code != Code.Ldstr) {
if (!erred)
context.Logger.WarnFormat("Failed to extract routed event name in '{0}'.", method.FullName);
erred = true;
continue;
}

var name = (string)ldstr.Operand;
TypeDef declType = method.DeclaringType;

EventDef eventDef = null;
if ((eventDef = declType.FindEvent(name)) == null) {
context.Logger.WarnFormat("Failed to find the CLR event of routed event '{0}' in type '{1}'.",
name, declType.FullName);
continue;
}
service.SetCanRename(eventDef, false);

if (eventDef.AddMethod != null)
service.SetCanRename(eventDef.AddMethod, false);

if (eventDef.RemoveMethod != null)
service.SetCanRename(eventDef.RemoveMethod, false);

if (eventDef.InvokeMethod != null)
service.SetCanRename(eventDef.InvokeMethod, false);

if (eventDef.HasOtherMethods) {
foreach (MethodDef accessor in eventDef.OtherMethods)
service.SetCanRename(accessor, false);
}
}
}

Check notice on line 320 in Confuser.Renamer/Analyzers/WPFAnalyzer.cs

View check run for this annotation

codefactor.io / CodeFactor

Confuser.Renamer/Analyzers/WPFAnalyzer.cs#L147-L320

Complex Method
void AnalyzeResources(ConfuserContext context, INameService service, ModuleDefMD module) {
if (analyzer == null) {
analyzer = new BAMLAnalyzer(context, service);
Expand Down Expand Up @@ -349,4 +355,4 @@
context.Annotations.Set(module, BAMLKey, wpfResInfo);
}
}
}
}