Fix a bug in Spices.Net resource renamer
This commit is contained in:
parent
897f6e3c1d
commit
68a8f27031
|
@ -17,6 +17,7 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
using dnlib.DotNet.Emit;
|
using dnlib.DotNet.Emit;
|
||||||
|
@ -83,12 +84,40 @@ namespace de4dot.code.deobfuscators.Spices_Net {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RenameResources() {
|
class ResourceDictionary {
|
||||||
if (resourceManagerType == null && componentResourceManagerType == null)
|
struct Key {
|
||||||
return;
|
public readonly uint hash;
|
||||||
|
public readonly string ns;
|
||||||
|
public Key(uint hash, string ns) {
|
||||||
|
this.hash = hash;
|
||||||
|
this.ns = ns;
|
||||||
|
}
|
||||||
|
|
||||||
var numToResource = new Dictionary<uint, Resource>(module.Resources.Count);
|
public override int GetHashCode() {
|
||||||
foreach (var resource in module.Resources) {
|
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<Key, Resource> resources = new Dictionary<Key, Resource>();
|
||||||
|
|
||||||
|
public int Count {
|
||||||
|
get { return resources.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Add(Resource resource) {
|
||||||
var name = resource.Name.String;
|
var name = resource.Name.String;
|
||||||
int index = name.LastIndexOf('.');
|
int index = name.LastIndexOf('.');
|
||||||
string ext;
|
string ext;
|
||||||
|
@ -98,35 +127,55 @@ namespace de4dot.code.deobfuscators.Spices_Net {
|
||||||
ext = name.Substring(index + 1);
|
ext = name.Substring(index + 1);
|
||||||
uint extNum;
|
uint extNum;
|
||||||
if (!uint.TryParse(ext, out extNum))
|
if (!uint.TryParse(ext, out extNum))
|
||||||
continue;
|
return false;
|
||||||
numToResource[extNum] = resource;
|
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)
|
if (module.Assembly != null)
|
||||||
Rename(numToResource, "", module.Assembly.Name + ".g");
|
Rename(rsrcDict, "", module.Assembly.Name + ".g");
|
||||||
|
|
||||||
foreach (var type in callsResourceManager.Keys)
|
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()) {
|
foreach (var type in module.GetTypes()) {
|
||||||
if (numToResource.Count == 0)
|
if (rsrcDict.Count == 0)
|
||||||
break;
|
break;
|
||||||
if (!IsWinFormType(type))
|
if (!IsWinFormType(type))
|
||||||
continue;
|
continue;
|
||||||
Rename(numToResource, type);
|
Rename(rsrcDict, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numToResource.Count != 0) {
|
if (rsrcDict.Count != 0) {
|
||||||
foreach (var type in module.GetTypes()) {
|
foreach (var type in module.GetTypes()) {
|
||||||
if (numToResource.Count == 0)
|
if (rsrcDict.Count == 0)
|
||||||
break;
|
break;
|
||||||
Rename(numToResource, type);
|
Rename(rsrcDict, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numToResource.Count != 0)
|
if (rsrcDict.Count != 0)
|
||||||
Logger.e("Couldn't restore all renamed resource names");
|
Logger.e("Couldn't restore all renamed resource names");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,18 +200,17 @@ namespace de4dot.code.deobfuscators.Spices_Net {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Rename(Dictionary<uint, Resource> numToResource, TypeDef type) {
|
static bool Rename(ResourceDictionary rsrcDict, TypeDef type) {
|
||||||
return Rename(numToResource, "", type.FullName) ||
|
if (!IsWinFormType(type) && Rename(rsrcDict, "", type.FullName))
|
||||||
Rename(numToResource, "", type.FullName + ".g") ||
|
return true;
|
||||||
Rename(numToResource, type.Namespace, type.Name) ||
|
return Rename(rsrcDict, type.Namespace, type.Name);
|
||||||
Rename(numToResource, type.Namespace, type.Name + ".g");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Rename(Dictionary<uint, Resource> numToResource, string ns, string name) {
|
static bool Rename(ResourceDictionary rsrcDict, string ns, string name) {
|
||||||
var resourceName = name + ".resources";
|
var resourceName = name + ".resources";
|
||||||
uint hash = GetResourceHash(resourceName);
|
uint hash = GetResourceHash(resourceName);
|
||||||
Resource resource;
|
var resource = rsrcDict.GetAndRemove(hash, ns);
|
||||||
if (!numToResource.TryGetValue(hash, out resource))
|
if (resource == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int index = resource.Name.String.LastIndexOf('.');
|
int index = resource.Name.String.LastIndexOf('.');
|
||||||
|
@ -176,13 +224,12 @@ namespace de4dot.code.deobfuscators.Spices_Net {
|
||||||
newName = resourceNamespace + "." + resourceName;
|
newName = resourceNamespace + "." + resourceName;
|
||||||
}
|
}
|
||||||
if (resourceNamespace != ns)
|
if (resourceNamespace != ns)
|
||||||
return false;
|
throw new ApplicationException("Invalid resource namespace");
|
||||||
|
|
||||||
Logger.v("Restoring resource name: '{0}' => '{1}'",
|
Logger.v("Restoring resource name: '{0}' => '{1}'",
|
||||||
Utils.RemoveNewlines(resource.Name),
|
Utils.RemoveNewlines(resource.Name),
|
||||||
Utils.RemoveNewlines(newName));
|
Utils.RemoveNewlines(newName));
|
||||||
resource.Name = newName;
|
resource.Name = newName;
|
||||||
numToResource.Remove(hash);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user