2012-05-31 21:38:51 +08:00
|
|
|
|
/*
|
2013-01-02 00:03:16 +08:00
|
|
|
|
Copyright (C) 2011-2013 de4dot@gmail.com
|
2012-05-31 21:38: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;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Reflection.Emit;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace de4dot.code.deobfuscators.CodeFort {
|
2012-11-08 14:43:57 +08:00
|
|
|
|
interface ICFType {
|
2012-05-31 21:38:51 +08:00
|
|
|
|
Type get(SerializedTypes serializedTypes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static class ITypeCreator {
|
2012-11-08 14:43:57 +08:00
|
|
|
|
public static ICFType create(string name) {
|
2012-05-31 21:38:51 +08:00
|
|
|
|
return new StringType(name);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-08 14:43:57 +08:00
|
|
|
|
public static ICFType create(Type type) {
|
2012-05-31 21:38:51 +08:00
|
|
|
|
return new ExistingType(type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-08 14:43:57 +08:00
|
|
|
|
class StringType : ICFType {
|
2012-05-31 21:38:51 +08:00
|
|
|
|
readonly string name;
|
|
|
|
|
|
|
|
|
|
public StringType(string name) {
|
|
|
|
|
this.name = name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Type get(SerializedTypes serializedTypes) {
|
|
|
|
|
return serializedTypes.getBuilderType(name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString() {
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-08 14:43:57 +08:00
|
|
|
|
class ExistingType : ICFType {
|
2012-05-31 21:38:51 +08:00
|
|
|
|
readonly Type type;
|
|
|
|
|
|
|
|
|
|
public ExistingType(Type type) {
|
|
|
|
|
this.type = type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Type get(SerializedTypes serializedTypes) {
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString() {
|
|
|
|
|
return type.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-08 14:43:57 +08:00
|
|
|
|
class GenericType : ICFType {
|
|
|
|
|
ICFType type;
|
|
|
|
|
ICFType[] genericArgs;
|
2012-05-31 21:38:51 +08:00
|
|
|
|
|
2012-11-08 14:43:57 +08:00
|
|
|
|
public GenericType(string type, ICFType[] genericArgs)
|
2012-05-31 21:38:51 +08:00
|
|
|
|
: this(ITypeCreator.create(type), genericArgs) {
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-08 14:43:57 +08:00
|
|
|
|
public GenericType(Type type, ICFType[] genericArgs)
|
2012-05-31 21:38:51 +08:00
|
|
|
|
: this(ITypeCreator.create(type), genericArgs) {
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-08 14:43:57 +08:00
|
|
|
|
public GenericType(ICFType type, ICFType[] genericArgs) {
|
2012-05-31 21:38:51 +08:00
|
|
|
|
this.type = type;
|
|
|
|
|
this.genericArgs = genericArgs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Type get(SerializedTypes serializedTypes) {
|
|
|
|
|
var genericType = type.get(serializedTypes);
|
|
|
|
|
var types = new List<Type>(genericArgs.Length);
|
|
|
|
|
foreach (var ga in genericArgs)
|
|
|
|
|
types.Add(ga.get(serializedTypes));
|
|
|
|
|
return genericType.MakeGenericType(types.ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString() {
|
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
sb.Append(getTypeName());
|
|
|
|
|
if (genericArgs != null && genericArgs.Length > 0) {
|
|
|
|
|
sb.Append('<');
|
2012-06-01 18:05:01 +08:00
|
|
|
|
for (int i = 0; i < genericArgs.Length; i++) {
|
|
|
|
|
if (i != 0)
|
|
|
|
|
sb.Append(',');
|
|
|
|
|
sb.Append(genericArgs[i].ToString());
|
|
|
|
|
}
|
2012-05-31 21:38:51 +08:00
|
|
|
|
sb.Append('>');
|
|
|
|
|
}
|
|
|
|
|
return sb.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string getTypeName() {
|
|
|
|
|
var typeName = type.ToString();
|
|
|
|
|
int index = typeName.LastIndexOf('`');
|
|
|
|
|
if (index < 0)
|
|
|
|
|
return typeName;
|
|
|
|
|
return typeName.Substring(0, index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ListType : GenericType {
|
|
|
|
|
public ListType(string type)
|
|
|
|
|
: this(ITypeCreator.create(type)) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ListType(Type type)
|
|
|
|
|
: this(ITypeCreator.create(type)) {
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-08 14:43:57 +08:00
|
|
|
|
public ListType(ICFType type)
|
|
|
|
|
: base(typeof(List<>), new ICFType[] { type }) {
|
2012-05-31 21:38:51 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TypeInfoBase {
|
|
|
|
|
public readonly string name;
|
|
|
|
|
public readonly string dcNamespace;
|
|
|
|
|
public readonly string dcName;
|
|
|
|
|
|
|
|
|
|
protected TypeInfoBase(string name, string dcNamespace, string dcName) {
|
|
|
|
|
this.name = name;
|
|
|
|
|
this.dcNamespace = dcNamespace;
|
|
|
|
|
this.dcName = dcName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString() {
|
|
|
|
|
if (!string.IsNullOrEmpty(dcNamespace))
|
|
|
|
|
return string.Format("{0} - {1}.{2}", name, dcNamespace, dcName);
|
|
|
|
|
return string.Format("{0} - {1}", name, dcName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TypeInfo : TypeInfoBase {
|
2012-11-08 14:43:57 +08:00
|
|
|
|
public readonly ICFType baseType;
|
2012-05-31 21:38:51 +08:00
|
|
|
|
public readonly TypeFieldInfo[] fieldInfos;
|
|
|
|
|
|
|
|
|
|
public TypeInfo(string name, string dcName, TypeFieldInfo[] fieldInfos)
|
|
|
|
|
: this(name, "", dcName, fieldInfos) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public TypeInfo(string name, string dcNamespace, string dcName, TypeFieldInfo[] fieldInfos)
|
|
|
|
|
: this(ITypeCreator.create(typeof(object)), name, dcNamespace, dcName, fieldInfos) {
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-08 14:43:57 +08:00
|
|
|
|
public TypeInfo(ICFType baseType, string name, string dcName, TypeFieldInfo[] fieldInfos)
|
2012-05-31 21:38:51 +08:00
|
|
|
|
: this(baseType, name, "", dcName, fieldInfos) {
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-08 14:43:57 +08:00
|
|
|
|
public TypeInfo(ICFType baseType, string name, string dcNamespace, string dcName, TypeFieldInfo[] fieldInfos)
|
2012-05-31 21:38:51 +08:00
|
|
|
|
: base(name, dcNamespace, dcName) {
|
|
|
|
|
this.baseType = baseType;
|
|
|
|
|
this.fieldInfos = fieldInfos;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TypeFieldInfo {
|
2012-11-08 14:43:57 +08:00
|
|
|
|
public readonly ICFType type;
|
2012-05-31 21:38:51 +08:00
|
|
|
|
public readonly string name;
|
|
|
|
|
public readonly string dmName;
|
|
|
|
|
|
|
|
|
|
public TypeFieldInfo(string type, string name, string dmName)
|
|
|
|
|
: this(ITypeCreator.create(type), name, dmName) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public TypeFieldInfo(Type type, string name, string dmName)
|
|
|
|
|
: this(ITypeCreator.create(type), name, dmName) {
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-08 14:43:57 +08:00
|
|
|
|
public TypeFieldInfo(ICFType type, string name, string dmName) {
|
2012-05-31 21:38:51 +08:00
|
|
|
|
this.type = type;
|
|
|
|
|
this.name = name;
|
|
|
|
|
this.dmName = dmName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString() {
|
|
|
|
|
return string.Format("{0} {1} - {2}", type, name, dmName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class EnumInfo : TypeInfoBase {
|
|
|
|
|
public readonly EnumFieldInfo[] fieldInfos;
|
|
|
|
|
public readonly Type underlyingType = typeof(int);
|
|
|
|
|
|
|
|
|
|
public EnumInfo(string name, string dcName, EnumFieldInfo[] fieldInfos)
|
|
|
|
|
: this(name, "", dcName, fieldInfos) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public EnumInfo(string name, string dcNamespace, string dcName, EnumFieldInfo[] fieldInfos)
|
|
|
|
|
: base(name, dcNamespace, dcName) {
|
|
|
|
|
this.fieldInfos = fieldInfos;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class EnumFieldInfo {
|
|
|
|
|
public readonly int value;
|
|
|
|
|
public readonly string name;
|
|
|
|
|
public readonly string emValue;
|
|
|
|
|
|
|
|
|
|
public EnumFieldInfo(int value, string name, string emValue) {
|
|
|
|
|
this.value = value;
|
|
|
|
|
this.name = name;
|
|
|
|
|
this.emValue = emValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString() {
|
|
|
|
|
return string.Format("({0}) {1} - {2}", value, name, emValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SerializedTypes {
|
|
|
|
|
const string serializationAssemblyname = "System.Runtime.Serialization, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
|
|
|
|
|
|
|
|
|
|
static readonly EnumInfo[] enumInfos = new EnumInfo[] {
|
|
|
|
|
new EnumInfo("InstructionType", "a", new EnumFieldInfo[] {
|
|
|
|
|
new EnumFieldInfo(0, "BeginCatchBlock", "1"),
|
|
|
|
|
new EnumFieldInfo(1, "BeginExceptFilterBlock", "2"),
|
|
|
|
|
new EnumFieldInfo(2, "BeginExceptionBlock", "3"),
|
|
|
|
|
new EnumFieldInfo(3, "BeginFaultBlock", "4"),
|
|
|
|
|
new EnumFieldInfo(4, "BeginFinallyBlock", "5"),
|
|
|
|
|
new EnumFieldInfo(5, "BeginScope", "6"),
|
|
|
|
|
new EnumFieldInfo(6, "LocalVariable", "7"),
|
|
|
|
|
new EnumFieldInfo(7, "Label", "8"),
|
|
|
|
|
new EnumFieldInfo(8, "NoOperand", "A"),
|
|
|
|
|
new EnumFieldInfo(9, "ByteOperand", "B"),
|
|
|
|
|
new EnumFieldInfo(10, "ConstructorOperand", "C"),
|
|
|
|
|
new EnumFieldInfo(11, "DoubleOperand", "D"),
|
|
|
|
|
new EnumFieldInfo(12, "FieldOperand", "E"),
|
|
|
|
|
new EnumFieldInfo(13, "SingleOperand", "F"),
|
|
|
|
|
new EnumFieldInfo(14, "Int32Operand", "G"),
|
|
|
|
|
new EnumFieldInfo(15, "TargetOperand", "H"),
|
|
|
|
|
new EnumFieldInfo(16, "TargetsOperand", "I"),
|
|
|
|
|
new EnumFieldInfo(17, "LocalOperand", "J"),
|
|
|
|
|
new EnumFieldInfo(18, "Int64Operand", "K"),
|
|
|
|
|
new EnumFieldInfo(19, "MethodOperand", "L"),
|
|
|
|
|
new EnumFieldInfo(20, "SByteOperand", "M"),
|
|
|
|
|
new EnumFieldInfo(21, "Int16Operand", "N"),
|
|
|
|
|
new EnumFieldInfo(22, "StringOperand", "O"),
|
|
|
|
|
new EnumFieldInfo(23, "TypeOperand", "P"),
|
|
|
|
|
new EnumFieldInfo(24, "EndExceptionBlock", "b"),
|
|
|
|
|
new EnumFieldInfo(25, "EndScope", "c"),
|
|
|
|
|
new EnumFieldInfo(26, "MarkLabel", "d"),
|
|
|
|
|
new EnumFieldInfo(27, "NotImpl1", "e"),
|
|
|
|
|
new EnumFieldInfo(28, "ThrowException", "f"),
|
|
|
|
|
new EnumFieldInfo(29, "NotImpl2", "g"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new EnumInfo("MemberTypes1", "l", new EnumFieldInfo[] {
|
|
|
|
|
new EnumFieldInfo(0, "Constructor", "1"),
|
|
|
|
|
new EnumFieldInfo(1, "TypeInitializer", "7"),
|
|
|
|
|
new EnumFieldInfo(2, "Method", "2"),
|
|
|
|
|
new EnumFieldInfo(3, "Field", "3"),
|
|
|
|
|
new EnumFieldInfo(4, "Property", "4"),
|
|
|
|
|
new EnumFieldInfo(5, "Event", "5"),
|
|
|
|
|
new EnumFieldInfo(6, "NestedType", "6"),
|
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static readonly TypeInfo[] typeInfos = new TypeInfo[] {
|
|
|
|
|
new TypeInfo("AllTypes", "b", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo(new ListType("TypeDef"), "Types", "T"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo("Instruction", "c", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo(typeof(object), "Operand", "A"),
|
|
|
|
|
new TypeFieldInfo("InstructionType", "InstructionType", "K"),
|
|
|
|
|
new TypeFieldInfo(typeof(string), "OpCode", "O"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo("InstructionLabel", "d", new TypeFieldInfo[] {
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo("LocalVariable", "e", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo(typeof(bool), "IsPinned", "P"),
|
|
|
|
|
new TypeFieldInfo("TypeRef", "VariableType", "T"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo("TypeRef", "f", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo("AssemblyRef", "AssemblyRef", "A"),
|
|
|
|
|
new TypeFieldInfo(typeof(string), "ReflectionTypeFullName", "F"),
|
|
|
|
|
new TypeFieldInfo(new ListType("TypeRef"), "GenericArguments", "G"),
|
|
|
|
|
new TypeFieldInfo("TypeDef", "InternalBaseType", "I"),
|
|
|
|
|
new TypeFieldInfo(typeof(int?), "ArrayDimensions", "V"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo("AssemblyRef", "g", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo(typeof(string), "Name", "N"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo("MemberRef", "h", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo(typeof(int), "BindingFlags", "B"),
|
|
|
|
|
new TypeFieldInfo("TypeRef", "DeclaringType", "C"),
|
|
|
|
|
new TypeFieldInfo("MemberTypes1", "MemberTypes1", "K"),
|
|
|
|
|
new TypeFieldInfo("MemberDef", "MemberDef", "M"),
|
|
|
|
|
new TypeFieldInfo(typeof(string), "Name", "N"),
|
|
|
|
|
new TypeFieldInfo("TypeRef", "ReturnType", "T"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo(ITypeCreator.create("MemberRef"), "MethodRef", "i", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo(new ListType("ParameterRef"), "Parameters", "P"),
|
|
|
|
|
new TypeFieldInfo(typeof(int), "CallingConventions", "V"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo("ParameterRef", "j", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo("TypeRef", "TypeRef", "T"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo("TypeDef", "k", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo(typeof(int), "TypeAttributes", "A"),
|
|
|
|
|
new TypeFieldInfo("TypeRef", "BaseType", "B"),
|
|
|
|
|
new TypeFieldInfo(new ListType("TypeDef"), "NestedTypes", "E"),
|
|
|
|
|
new TypeFieldInfo(new ListType("MemberDef"), "Members", "M"),
|
|
|
|
|
new TypeFieldInfo(typeof(string), "Name", "N"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo("MemberDef", "m", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo(typeof(int), "Attributes", "B"),
|
|
|
|
|
new TypeFieldInfo("MemberTypes1", "MemberTypes1", "K"),
|
|
|
|
|
new TypeFieldInfo(typeof(string), "Name", "N"),
|
|
|
|
|
new TypeFieldInfo("TypeRef", "Type", "T"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo(ITypeCreator.create("MemberDef"), "PropertyDef", "n", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo("MethodDef", "GetMethod", "G"),
|
|
|
|
|
new TypeFieldInfo(new ListType("ParameterDef"), "ParameterTypes", "P"),
|
|
|
|
|
new TypeFieldInfo("MethodDef", "SetMethod", "S"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo(ITypeCreator.create("MemberDef"), "EventDef", "o", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo("MethodDef", "AddOnMethod", "A"),
|
|
|
|
|
new TypeFieldInfo("MethodDef", "RemoveOnMethod", "R"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo(ITypeCreator.create("MemberDef"), "MethodDef", "p", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo(new ListType("Instruction"), "Instructions", "A"),
|
|
|
|
|
new TypeFieldInfo(typeof(CallingConventions), "CallingConventions", "C"),
|
|
|
|
|
new TypeFieldInfo(typeof(MethodImplAttributes), "MethodImplAttributes", "I"),
|
|
|
|
|
new TypeFieldInfo(new ListType("ParameterDef"), "ParameterTypes", "P"),
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
new TypeInfo("ParameterDef", "q", new TypeFieldInfo[] {
|
|
|
|
|
new TypeFieldInfo(typeof(string), "Name", "N"),
|
|
|
|
|
new TypeFieldInfo("TypeRef", "TypeRef", "T"),
|
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class PropertyInfoCreator {
|
|
|
|
|
Type type;
|
|
|
|
|
List<PropertyInfo> properties = new List<PropertyInfo>();
|
|
|
|
|
List<object> values = new List<object>();
|
|
|
|
|
|
|
|
|
|
public PropertyInfo[] Properties {
|
|
|
|
|
get { return properties.ToArray(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public object[] Values {
|
|
|
|
|
get { return values.ToArray(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public PropertyInfoCreator(Type type) {
|
|
|
|
|
this.type = type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void add(string propertyName, object value) {
|
|
|
|
|
var prop = type.GetProperty(propertyName);
|
|
|
|
|
if (prop == null)
|
|
|
|
|
throw new ApplicationException(string.Format("Could not find property {0} (type {1})", propertyName, type));
|
|
|
|
|
properties.Add(prop);
|
|
|
|
|
values.Add(value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ModuleBuilder moduleBuilder;
|
|
|
|
|
Dictionary<string, EnumBuilder> enumBuilders = new Dictionary<string, EnumBuilder>(StringComparer.Ordinal);
|
|
|
|
|
Dictionary<string, TypeBuilder> typeBuilders = new Dictionary<string, TypeBuilder>(StringComparer.Ordinal);
|
|
|
|
|
Dictionary<string, Type> createdTypes = new Dictionary<string, Type>(StringComparer.Ordinal);
|
|
|
|
|
|
|
|
|
|
public SerializedTypes(ModuleBuilder moduleBuilder) {
|
|
|
|
|
this.moduleBuilder = moduleBuilder;
|
|
|
|
|
createTypeBuilders();
|
|
|
|
|
initializeEnums();
|
|
|
|
|
initializeTypes();
|
|
|
|
|
createTypes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void createTypeBuilders() {
|
|
|
|
|
foreach (var info in enumInfos)
|
|
|
|
|
add(info.name, moduleBuilder.DefineEnum(info.name, TypeAttributes.Public, info.underlyingType));
|
|
|
|
|
foreach (var info in typeInfos)
|
|
|
|
|
add(info.name, moduleBuilder.DefineType(info.name, TypeAttributes.Public, info.baseType.get(this)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CustomAttributeBuilder createDataContractAttribute(string ns, string name, bool isReference) {
|
|
|
|
|
var dcAttr = Type.GetType("System.Runtime.Serialization.DataContractAttribute," + serializationAssemblyname);
|
|
|
|
|
var ctor = dcAttr.GetConstructor(Type.EmptyTypes);
|
|
|
|
|
var propCreator = new PropertyInfoCreator(dcAttr);
|
|
|
|
|
propCreator.add("Namespace", ns);
|
|
|
|
|
propCreator.add("Name", name);
|
|
|
|
|
propCreator.add("IsReference", isReference);
|
|
|
|
|
return new CustomAttributeBuilder(ctor, new object[0], propCreator.Properties, propCreator.Values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CustomAttributeBuilder createEnumMemberAttribute(string value) {
|
|
|
|
|
var emAttr = Type.GetType("System.Runtime.Serialization.EnumMemberAttribute," + serializationAssemblyname);
|
|
|
|
|
var ctor = emAttr.GetConstructor(Type.EmptyTypes);
|
|
|
|
|
var propCreator = new PropertyInfoCreator(emAttr);
|
|
|
|
|
propCreator.add("Value", value);
|
|
|
|
|
return new CustomAttributeBuilder(ctor, new object[0], propCreator.Properties, propCreator.Values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CustomAttributeBuilder createDataMemberAttribute(string name, bool emitDefaultValue) {
|
|
|
|
|
var dmAttr = Type.GetType("System.Runtime.Serialization.DataMemberAttribute," + serializationAssemblyname);
|
|
|
|
|
var ctor = dmAttr.GetConstructor(Type.EmptyTypes);
|
|
|
|
|
var propCreator = new PropertyInfoCreator(dmAttr);
|
|
|
|
|
propCreator.add("Name", name);
|
|
|
|
|
propCreator.add("EmitDefaultValue", emitDefaultValue);
|
|
|
|
|
return new CustomAttributeBuilder(ctor, new object[0], propCreator.Properties, propCreator.Values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void add(string name, EnumBuilder builder) {
|
|
|
|
|
if (enumBuilders.ContainsKey(name))
|
|
|
|
|
throw new ApplicationException(string.Format("Enum {0} already exists", name));
|
|
|
|
|
enumBuilders[name] = builder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void add(string name, TypeBuilder builder) {
|
|
|
|
|
if (typeBuilders.ContainsKey(name))
|
|
|
|
|
throw new ApplicationException(string.Format("Type {0} already exists", name));
|
|
|
|
|
typeBuilders[name] = builder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void initializeEnums() {
|
|
|
|
|
foreach (var info in enumInfos) {
|
|
|
|
|
var builder = enumBuilders[info.name];
|
|
|
|
|
builder.SetCustomAttribute(createDataContractAttribute(info.dcNamespace, info.dcName, false));
|
|
|
|
|
foreach (var fieldInfo in info.fieldInfos) {
|
|
|
|
|
var fieldBuilder = builder.DefineLiteral(fieldInfo.name, fieldInfo.value);
|
|
|
|
|
fieldBuilder.SetCustomAttribute(createEnumMemberAttribute(fieldInfo.emValue));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void initializeTypes() {
|
|
|
|
|
foreach (var info in typeInfos) {
|
|
|
|
|
var builder = typeBuilders[info.name];
|
|
|
|
|
builder.SetCustomAttribute(createDataContractAttribute(info.dcNamespace, info.dcName, true));
|
|
|
|
|
foreach (var fieldInfo in info.fieldInfos) {
|
|
|
|
|
var fieldBuilder = builder.DefineField(fieldInfo.name, fieldInfo.type.get(this), FieldAttributes.Public);
|
|
|
|
|
fieldBuilder.SetCustomAttribute(createDataMemberAttribute(fieldInfo.dmName, false));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void createTypes() {
|
|
|
|
|
foreach (var info in enumInfos)
|
|
|
|
|
createdTypes[info.name] = enumBuilders[info.name].CreateType();
|
|
|
|
|
foreach (var info in typeInfos)
|
|
|
|
|
createdTypes[info.name] = typeBuilders[info.name].CreateType();
|
|
|
|
|
moduleBuilder = null;
|
|
|
|
|
enumBuilders = null;
|
|
|
|
|
typeBuilders = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Type getBuilderType(string name) {
|
|
|
|
|
EnumBuilder enumBuilder;
|
|
|
|
|
if (enumBuilders.TryGetValue(name, out enumBuilder))
|
|
|
|
|
return enumBuilder;
|
|
|
|
|
|
|
|
|
|
TypeBuilder typeBuilder;
|
|
|
|
|
if (typeBuilders.TryGetValue(name, out typeBuilder))
|
|
|
|
|
return typeBuilder;
|
|
|
|
|
|
|
|
|
|
throw new ApplicationException(string.Format("Could not find type {0}", name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Type getType(string name) {
|
|
|
|
|
return createdTypes[name];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public object deserialize(byte[] data) {
|
|
|
|
|
var serializerType = Type.GetType("System.Runtime.Serialization.DataContractSerializer," + serializationAssemblyname);
|
|
|
|
|
if (serializerType == null)
|
|
|
|
|
throw new ApplicationException("You need .NET 3.0 or later to decrypt the assembly");
|
|
|
|
|
var quotasType = Type.GetType("System.Xml.XmlDictionaryReaderQuotas," + serializationAssemblyname);
|
|
|
|
|
var serializerCtor = serializerType.GetConstructor(new Type[] { typeof(Type), typeof(IEnumerable<Type>) });
|
|
|
|
|
var serializer = serializerCtor.Invoke(new object[] { getType("AllTypes"), new Type[] {
|
|
|
|
|
getType("MemberTypes1"),
|
|
|
|
|
getType("Instruction"),
|
|
|
|
|
getType("InstructionType"),
|
|
|
|
|
getType("InstructionLabel"),
|
|
|
|
|
getType("LocalVariable"),
|
|
|
|
|
getType("ParameterDef"),
|
|
|
|
|
getType("TypeDef"),
|
|
|
|
|
getType("MemberDef"),
|
|
|
|
|
getType("MethodDef"),
|
|
|
|
|
getType("EventDef"),
|
|
|
|
|
getType("PropertyDef"),
|
|
|
|
|
getType("ParameterRef"),
|
|
|
|
|
getType("TypeRef"),
|
|
|
|
|
getType("MemberRef"),
|
|
|
|
|
getType("MethodRef"),
|
|
|
|
|
}});
|
|
|
|
|
|
|
|
|
|
var xmlReaderType = Type.GetType("System.Xml.XmlDictionaryReader," + serializationAssemblyname);
|
|
|
|
|
var createReaderMethod = xmlReaderType.GetMethod("CreateBinaryReader", new Type[] { typeof(Stream), quotasType });
|
|
|
|
|
var xmlReader = createReaderMethod.Invoke(null, new object[] {
|
|
|
|
|
new MemoryStream(data),
|
|
|
|
|
quotasType.InvokeMember("Max", BindingFlags.GetProperty, null, null, new object[0]),
|
|
|
|
|
});
|
|
|
|
|
using ((IDisposable)xmlReader) {
|
|
|
|
|
var readObjectMethod = serializerType.GetMethod("ReadObject", new Type[] { xmlReaderType });
|
|
|
|
|
return readObjectMethod.Invoke(serializer, new object[] { xmlReader });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|