diff --git a/de4dot.code/deobfuscators/Spices_Net/ResourceNamesRestorer.cs b/de4dot.code/deobfuscators/Spices_Net/ResourceNamesRestorer.cs
index 37553866..40846bca 100644
--- a/de4dot.code/deobfuscators/Spices_Net/ResourceNamesRestorer.cs
+++ b/de4dot.code/deobfuscators/Spices_Net/ResourceNamesRestorer.cs
@@ -17,6 +17,7 @@
along with de4dot. If not, see .
*/
+using System;
using System.Collections.Generic;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
@@ -83,12 +84,40 @@ namespace de4dot.code.deobfuscators.Spices_Net {
return true;
}
- public void RenameResources() {
- if (resourceManagerType == null && componentResourceManagerType == null)
- return;
+ class ResourceDictionary {
+ struct Key {
+ public readonly uint hash;
+ public readonly string ns;
+ public Key(uint hash, string ns) {
+ this.hash = hash;
+ this.ns = ns;
+ }
- var numToResource = new Dictionary(module.Resources.Count);
- foreach (var resource in module.Resources) {
+ public override int GetHashCode() {
+ return (int)(hash ^ ns.GetHashCode());
+ }
+
+ public override bool Equals(object obj) {
+ if (!(obj is Key))
+ return false;
+ var other = (Key)obj;
+ return hash == other.hash &&
+ ns == other.ns;
+ }
+
+ public override string ToString() {
+ if (ns == string.Empty)
+ return string.Format("{0}", hash);
+ return string.Format("{0}.{1}", ns, hash);
+ }
+ }
+ Dictionary resources = new Dictionary();
+
+ public int Count {
+ get { return resources.Count; }
+ }
+
+ public bool Add(Resource resource) {
var name = resource.Name.String;
int index = name.LastIndexOf('.');
string ext;
@@ -98,35 +127,55 @@ namespace de4dot.code.deobfuscators.Spices_Net {
ext = name.Substring(index + 1);
uint extNum;
if (!uint.TryParse(ext, out extNum))
- continue;
- numToResource[extNum] = resource;
+ return false;
+ var ns = index < 0 ? string.Empty : name.Substring(0, index);
+
+ resources.Add(new Key(extNum, ns), resource);
+ return true;
}
+ public Resource GetAndRemove(uint hash, string ns) {
+ var key = new Key(hash, ns);
+ Resource resource;
+ if (resources.TryGetValue(key, out resource))
+ resources.Remove(key);
+ return resource;
+ }
+ }
+
+ public void RenameResources() {
+ if (resourceManagerType == null && componentResourceManagerType == null)
+ return;
+
+ var rsrcDict = new ResourceDictionary();
+ foreach (var resource in module.Resources)
+ rsrcDict.Add(resource);
+
if (module.Assembly != null)
- Rename(numToResource, "", module.Assembly.Name + ".g");
+ Rename(rsrcDict, "", module.Assembly.Name + ".g");
foreach (var type in callsResourceManager.Keys)
- Rename(numToResource, type);
+ Rename(rsrcDict, type);
- if (numToResource.Count != 0) {
+ if (rsrcDict.Count != 0) {
foreach (var type in module.GetTypes()) {
- if (numToResource.Count == 0)
+ if (rsrcDict.Count == 0)
break;
if (!IsWinFormType(type))
continue;
- Rename(numToResource, type);
+ Rename(rsrcDict, type);
}
}
- if (numToResource.Count != 0) {
+ if (rsrcDict.Count != 0) {
foreach (var type in module.GetTypes()) {
- if (numToResource.Count == 0)
+ if (rsrcDict.Count == 0)
break;
- Rename(numToResource, type);
+ Rename(rsrcDict, type);
}
}
- if (numToResource.Count != 0)
+ if (rsrcDict.Count != 0)
Logger.e("Couldn't restore all renamed resource names");
}
@@ -151,18 +200,17 @@ namespace de4dot.code.deobfuscators.Spices_Net {
return false;
}
- static bool Rename(Dictionary numToResource, TypeDef type) {
- return Rename(numToResource, "", type.FullName) ||
- Rename(numToResource, "", type.FullName + ".g") ||
- Rename(numToResource, type.Namespace, type.Name) ||
- Rename(numToResource, type.Namespace, type.Name + ".g");
+ static bool Rename(ResourceDictionary rsrcDict, TypeDef type) {
+ if (!IsWinFormType(type) && Rename(rsrcDict, "", type.FullName))
+ return true;
+ return Rename(rsrcDict, type.Namespace, type.Name);
}
- static bool Rename(Dictionary numToResource, string ns, string name) {
+ static bool Rename(ResourceDictionary rsrcDict, string ns, string name) {
var resourceName = name + ".resources";
uint hash = GetResourceHash(resourceName);
- Resource resource;
- if (!numToResource.TryGetValue(hash, out resource))
+ var resource = rsrcDict.GetAndRemove(hash, ns);
+ if (resource == null)
return false;
int index = resource.Name.String.LastIndexOf('.');
@@ -176,13 +224,12 @@ namespace de4dot.code.deobfuscators.Spices_Net {
newName = resourceNamespace + "." + resourceName;
}
if (resourceNamespace != ns)
- return false;
+ throw new ApplicationException("Invalid resource namespace");
Logger.v("Restoring resource name: '{0}' => '{1}'",
Utils.RemoveNewlines(resource.Name),
Utils.RemoveNewlines(newName));
resource.Name = newName;
- numToResource.Remove(hash);
return true;
}