2011-11-15 21:26:51 +08:00
|
|
|
|
/*
|
2014-03-12 05:15:43 +08:00
|
|
|
|
Copyright (C) 2011-2014 de4dot@gmail.com
|
2011-11-15 21:26:51 +08:00
|
|
|
|
|
|
|
|
|
This file is part of de4dot.
|
|
|
|
|
|
|
|
|
|
de4dot is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
de4dot is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2012-12-20 09:06:09 +08:00
|
|
|
|
using dnlib.DotNet;
|
2011-11-15 21:26:51 +08:00
|
|
|
|
using de4dot.blocks;
|
|
|
|
|
|
2011-12-09 16:02:06 +08:00
|
|
|
|
namespace de4dot.code.renamer.asmmodules {
|
2015-05-17 19:29:48 +08:00
|
|
|
|
public class Module : IResolver {
|
2011-11-15 21:26:51 +08:00
|
|
|
|
IObfuscatedFile obfuscatedFile;
|
|
|
|
|
TypeDefDict types = new TypeDefDict();
|
|
|
|
|
MemberRefFinder memberRefFinder;
|
2012-11-03 03:10:34 +08:00
|
|
|
|
IList<RefToDef<TypeRef, TypeDef>> typeRefsToRename = new List<RefToDef<TypeRef, TypeDef>>();
|
|
|
|
|
IList<RefToDef<MemberRef, MethodDef>> methodRefsToRename = new List<RefToDef<MemberRef, MethodDef>>();
|
|
|
|
|
IList<RefToDef<MemberRef, FieldDef>> fieldRefsToRename = new List<RefToDef<MemberRef, FieldDef>>();
|
2012-11-22 16:14:51 +08:00
|
|
|
|
List<CustomAttributeRef> customAttributeFieldRefs = new List<CustomAttributeRef>();
|
|
|
|
|
List<CustomAttributeRef> customAttributePropertyRefs = new List<CustomAttributeRef>();
|
2012-11-02 22:57:11 +08:00
|
|
|
|
List<MethodDef> allMethods;
|
2011-11-15 21:26:51 +08:00
|
|
|
|
|
2012-11-22 16:14:51 +08:00
|
|
|
|
public class CustomAttributeRef {
|
2012-03-03 12:49:49 +08:00
|
|
|
|
public CustomAttribute cattr;
|
|
|
|
|
public int index;
|
2012-11-03 03:10:34 +08:00
|
|
|
|
public IMemberRef reference;
|
2012-11-22 16:14:51 +08:00
|
|
|
|
public CustomAttributeRef(CustomAttribute cattr, int index, IMemberRef reference) {
|
2012-03-03 12:49:49 +08:00
|
|
|
|
this.cattr = cattr;
|
|
|
|
|
this.index = index;
|
|
|
|
|
this.reference = reference;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-03 03:10:34 +08:00
|
|
|
|
public class RefToDef<R, D> where R : ICodedToken where D : ICodedToken {
|
2011-11-15 21:26:51 +08:00
|
|
|
|
public R reference;
|
|
|
|
|
public D definition;
|
|
|
|
|
public RefToDef(R reference, D definition) {
|
|
|
|
|
this.reference = reference;
|
|
|
|
|
this.definition = definition;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-03 03:10:34 +08:00
|
|
|
|
public IEnumerable<RefToDef<TypeRef, TypeDef>> TypeRefsToRename {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
get { return typeRefsToRename; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-03 03:10:34 +08:00
|
|
|
|
public IEnumerable<RefToDef<MemberRef, MethodDef>> MethodRefsToRename {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
get { return methodRefsToRename; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-03 03:10:34 +08:00
|
|
|
|
public IEnumerable<RefToDef<MemberRef, FieldDef>> FieldRefsToRename {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
get { return fieldRefsToRename; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-22 16:14:51 +08:00
|
|
|
|
public IEnumerable<CustomAttributeRef> CustomAttributeFieldRefs {
|
|
|
|
|
get { return customAttributeFieldRefs; }
|
2012-03-03 12:49:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-22 16:14:51 +08:00
|
|
|
|
public IEnumerable<CustomAttributeRef> CustomAttributePropertyRefs {
|
|
|
|
|
get { return customAttributePropertyRefs; }
|
2012-03-03 12:49:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
2011-11-17 11:17:03 +08:00
|
|
|
|
public IObfuscatedFile ObfuscatedFile {
|
|
|
|
|
get { return obfuscatedFile; }
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-15 21:26:51 +08:00
|
|
|
|
public string Filename {
|
|
|
|
|
get { return obfuscatedFile.Filename; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
public ModuleDefMD ModuleDefMD {
|
|
|
|
|
get { return obfuscatedFile.ModuleDefMD; }
|
2011-11-15 21:26:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Module(IObfuscatedFile obfuscatedFile) {
|
|
|
|
|
this.obfuscatedFile = obfuscatedFile;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public IEnumerable<MTypeDef> GetAllTypes() {
|
|
|
|
|
return types.GetValues();
|
2011-11-15 21:26:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public IEnumerable<MethodDef> GetAllMethods() {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
return allMethods;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public void FindAllMemberRefs(ref int typeIndex) {
|
2011-11-15 21:26:51 +08:00
|
|
|
|
memberRefFinder = new MemberRefFinder();
|
2013-01-19 20:03:57 +08:00
|
|
|
|
memberRefFinder.FindAll(ModuleDefMD);
|
2015-07-20 05:47:45 +08:00
|
|
|
|
allMethods = new List<MethodDef>(memberRefFinder.MethodDefs.Keys);
|
2011-11-15 21:26:51 +08:00
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
var allTypesList = new List<MTypeDef>();
|
2015-07-20 05:47:45 +08:00
|
|
|
|
foreach (var type in memberRefFinder.TypeDefs.Keys) {
|
2012-11-02 22:57:11 +08:00
|
|
|
|
var typeDef = new MTypeDef(type, this, typeIndex++);
|
2013-01-19 20:03:57 +08:00
|
|
|
|
types.Add(typeDef);
|
2011-11-15 21:26:51 +08:00
|
|
|
|
allTypesList.Add(typeDef);
|
2013-01-19 20:03:57 +08:00
|
|
|
|
typeDef.AddMembers();
|
2011-11-15 21:26:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
var allTypesCopy = new List<MTypeDef>(allTypesList);
|
|
|
|
|
var typeToIndex = new Dictionary<TypeDef, int>();
|
2011-11-15 21:26:51 +08:00
|
|
|
|
for (int i = 0; i < allTypesList.Count; i++)
|
2012-11-02 22:57:11 +08:00
|
|
|
|
typeToIndex[allTypesList[i].TypeDef] = i;
|
2011-11-15 21:26:51 +08:00
|
|
|
|
foreach (var typeDef in allTypesList) {
|
2012-11-02 22:57:11 +08:00
|
|
|
|
if (typeDef.TypeDef.NestedTypes == null)
|
2011-11-15 21:26:51 +08:00
|
|
|
|
continue;
|
2012-11-22 16:14:51 +08:00
|
|
|
|
foreach (var nestedTypeDef2 in typeDef.TypeDef.NestedTypes) {
|
|
|
|
|
int index = typeToIndex[nestedTypeDef2];
|
2011-11-15 21:26:51 +08:00
|
|
|
|
var nestedTypeDef = allTypesCopy[index];
|
|
|
|
|
allTypesCopy[index] = null;
|
|
|
|
|
if (nestedTypeDef == null) // Impossible
|
|
|
|
|
throw new ApplicationException("Nested type belongs to two or more types");
|
2013-01-19 20:03:57 +08:00
|
|
|
|
typeDef.Add(nestedTypeDef);
|
2011-11-15 21:26:51 +08:00
|
|
|
|
nestedTypeDef.NestingType = typeDef;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public void ResolveAllRefs(IResolver resolver) {
|
2015-07-20 05:47:45 +08:00
|
|
|
|
foreach (var typeRef in memberRefFinder.TypeRefs.Keys) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
var typeDef = resolver.ResolveType(typeRef);
|
2011-11-15 21:26:51 +08:00
|
|
|
|
if (typeDef != null)
|
2012-11-03 03:10:34 +08:00
|
|
|
|
typeRefsToRename.Add(new RefToDef<TypeRef, TypeDef>(typeRef, typeDef.TypeDef));
|
2011-11-15 21:26:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-20 05:47:45 +08:00
|
|
|
|
foreach (var memberRef in memberRefFinder.MemberRefs.Keys) {
|
2012-11-03 03:10:34 +08:00
|
|
|
|
if (memberRef.IsMethodRef) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
var methodDef = resolver.ResolveMethod(memberRef);
|
2012-11-03 03:10:34 +08:00
|
|
|
|
if (methodDef != null)
|
|
|
|
|
methodRefsToRename.Add(new RefToDef<MemberRef, MethodDef>(memberRef, methodDef.MethodDef));
|
|
|
|
|
}
|
|
|
|
|
else if (memberRef.IsFieldRef) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
var fieldDef = resolver.ResolveField(memberRef);
|
2012-11-03 03:10:34 +08:00
|
|
|
|
if (fieldDef != null)
|
|
|
|
|
fieldRefsToRename.Add(new RefToDef<MemberRef, FieldDef>(memberRef, fieldDef.FieldDef));
|
|
|
|
|
}
|
2011-11-15 21:26:51 +08:00
|
|
|
|
}
|
2012-03-03 12:49:49 +08:00
|
|
|
|
|
2015-07-20 05:47:45 +08:00
|
|
|
|
foreach (var cattr in memberRefFinder.CustomAttributes.Keys) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
var typeDef = resolver.ResolveType(cattr.AttributeType);
|
2012-11-03 03:10:34 +08:00
|
|
|
|
if (typeDef == null)
|
|
|
|
|
continue;
|
2012-11-06 07:17:58 +08:00
|
|
|
|
if (cattr.NamedArguments == null)
|
|
|
|
|
continue;
|
2012-03-03 12:49:49 +08:00
|
|
|
|
|
2012-11-03 03:10:34 +08:00
|
|
|
|
for (int i = 0; i < cattr.NamedArguments.Count; i++) {
|
|
|
|
|
var namedArg = cattr.NamedArguments[i];
|
|
|
|
|
if (namedArg.IsField) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
var fieldDef = FindField(typeDef, namedArg.Name, namedArg.Type);
|
2012-03-03 12:49:49 +08:00
|
|
|
|
if (fieldDef == null) {
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.w("Could not find field {0} in attribute {1} ({2:X8})",
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Utils.ToCsharpString(namedArg.Name),
|
|
|
|
|
Utils.ToCsharpString(typeDef.TypeDef.Name),
|
2012-11-02 22:57:11 +08:00
|
|
|
|
typeDef.TypeDef.MDToken.ToInt32());
|
2012-03-03 12:49:49 +08:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-22 16:14:51 +08:00
|
|
|
|
customAttributeFieldRefs.Add(new CustomAttributeRef(cattr, i, fieldDef.FieldDef));
|
2012-03-03 12:49:49 +08:00
|
|
|
|
}
|
2012-11-03 03:10:34 +08:00
|
|
|
|
else {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
var propDef = FindProperty(typeDef, namedArg.Name, namedArg.Type);
|
2012-03-03 12:49:49 +08:00
|
|
|
|
if (propDef == null) {
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.w("Could not find property {0} in attribute {1} ({2:X8})",
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Utils.ToCsharpString(namedArg.Name),
|
|
|
|
|
Utils.ToCsharpString(typeDef.TypeDef.Name),
|
2012-11-02 22:57:11 +08:00
|
|
|
|
typeDef.TypeDef.MDToken.ToInt32());
|
2012-03-03 12:49:49 +08:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-22 16:14:51 +08:00
|
|
|
|
customAttributePropertyRefs.Add(new CustomAttributeRef(cattr, i, propDef.PropertyDef));
|
2012-03-03 12:49:49 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
static MFieldDef FindField(MTypeDef typeDef, UTF8String name, TypeSig fieldType) {
|
2012-03-04 01:23:53 +08:00
|
|
|
|
while (typeDef != null) {
|
|
|
|
|
foreach (var fieldDef in typeDef.AllFields) {
|
2012-11-03 03:10:34 +08:00
|
|
|
|
if (fieldDef.FieldDef.Name != name)
|
|
|
|
|
continue;
|
2012-11-06 07:17:58 +08:00
|
|
|
|
if (new SigComparer().Equals(fieldDef.FieldDef.FieldSig.GetFieldType(), fieldType))
|
2012-03-04 01:23:53 +08:00
|
|
|
|
return fieldDef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeDef.baseType == null)
|
|
|
|
|
break;
|
|
|
|
|
typeDef = typeDef.baseType.typeDef;
|
2012-03-03 12:49:49 +08:00
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
static MPropertyDef FindProperty(MTypeDef typeDef, UTF8String name, TypeSig propType) {
|
2012-03-04 01:23:53 +08:00
|
|
|
|
while (typeDef != null) {
|
|
|
|
|
foreach (var propDef in typeDef.AllProperties) {
|
2012-11-03 03:10:34 +08:00
|
|
|
|
if (propDef.PropertyDef.Name != name)
|
|
|
|
|
continue;
|
2012-11-06 07:17:58 +08:00
|
|
|
|
if (new SigComparer().Equals(propDef.PropertyDef.PropertySig.GetRetType(), propType))
|
2012-03-04 01:23:53 +08:00
|
|
|
|
return propDef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeDef.baseType == null)
|
|
|
|
|
break;
|
|
|
|
|
typeDef = typeDef.baseType.typeDef;
|
2012-03-03 12:49:49 +08:00
|
|
|
|
}
|
|
|
|
|
return null;
|
2011-11-15 21:26:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public void OnTypesRenamed() {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
var newTypes = new TypeDefDict();
|
2013-01-19 20:03:57 +08:00
|
|
|
|
foreach (var typeDef in types.GetValues()) {
|
|
|
|
|
typeDef.OnTypesRenamed();
|
|
|
|
|
newTypes.Add(typeDef);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
types = newTypes;
|
2012-11-05 05:41:45 +08:00
|
|
|
|
|
2013-09-26 22:32:45 +08:00
|
|
|
|
ModuleDefMD.ResetTypeDefFindCache();
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
static ITypeDefOrRef GetNonGenericTypeRef(ITypeDefOrRef typeRef) {
|
2012-11-03 03:10:34 +08:00
|
|
|
|
var ts = typeRef as TypeSpec;
|
|
|
|
|
if (ts == null)
|
|
|
|
|
return typeRef;
|
2012-12-20 01:14:47 +08:00
|
|
|
|
var gis = ts.TryGetGenericInstSig();
|
2012-11-03 03:10:34 +08:00
|
|
|
|
if (gis == null || gis.GenericType == null)
|
|
|
|
|
return typeRef;
|
|
|
|
|
return gis.GenericType.TypeDefOrRef;
|
2011-11-15 21:26:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public MTypeDef ResolveType(ITypeDefOrRef typeRef) {
|
|
|
|
|
return this.types.Find(GetNonGenericTypeRef(typeRef));
|
2011-11-15 21:26:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public MMethodDef ResolveMethod(IMethodDefOrRef methodRef) {
|
|
|
|
|
var typeDef = this.types.Find(GetNonGenericTypeRef(methodRef.DeclaringType));
|
2011-11-15 21:26:51 +08:00
|
|
|
|
if (typeDef == null)
|
|
|
|
|
return null;
|
2013-01-19 20:03:57 +08:00
|
|
|
|
return typeDef.FindMethod(methodRef);
|
2011-11-15 21:26:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public MFieldDef ResolveField(MemberRef fieldRef) {
|
|
|
|
|
var typeDef = this.types.Find(GetNonGenericTypeRef(fieldRef.DeclaringType));
|
2011-11-15 21:26:51 +08:00
|
|
|
|
if (typeDef == null)
|
|
|
|
|
return null;
|
2013-01-19 20:03:57 +08:00
|
|
|
|
return typeDef.FindField(fieldRef);
|
2011-11-15 21:26:51 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|