Decrypt main assembly and embedded assemblies
This commit is contained in:
parent
ddc270b963
commit
58b62ff914
|
@ -92,6 +92,9 @@
|
|||
<Compile Include="deobfuscators\CliSecure\vm\UnknownHandlerInfo.cs" />
|
||||
<Compile Include="deobfuscators\CliSecure\vm\VmOpCodeHandlerDetector.cs" />
|
||||
<Compile Include="deobfuscators\CliSecure\vm\VmOperands.cs" />
|
||||
<Compile Include="deobfuscators\CodeFort\PasswordFinder.cs" />
|
||||
<Compile Include="deobfuscators\CodeFort\AssemblyData.cs" />
|
||||
<Compile Include="deobfuscators\CodeFort\AssemblyDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\CodeFort\CfMethodCallInliner.cs" />
|
||||
<Compile Include="deobfuscators\CodeFort\Deobfuscator.cs" />
|
||||
<Compile Include="deobfuscators\CodeFort\ProxyCallFixer.cs" />
|
||||
|
|
534
de4dot.code/deobfuscators/CodeFort/AssemblyData.cs
Normal file
534
de4dot.code/deobfuscators/CodeFort/AssemblyData.cs
Normal file
|
@ -0,0 +1,534 @@
|
|||
/*
|
||||
Copyright (C) 2011-2012 de4dot@gmail.com
|
||||
|
||||
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 {
|
||||
interface IType {
|
||||
Type get(SerializedTypes serializedTypes);
|
||||
}
|
||||
|
||||
static class ITypeCreator {
|
||||
public static IType create(string name) {
|
||||
return new StringType(name);
|
||||
}
|
||||
|
||||
public static IType create(Type type) {
|
||||
return new ExistingType(type);
|
||||
}
|
||||
}
|
||||
|
||||
class StringType : IType {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
class ExistingType : IType {
|
||||
readonly Type type;
|
||||
|
||||
public ExistingType(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Type get(SerializedTypes serializedTypes) {
|
||||
return type;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return type.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
class GenericType : IType {
|
||||
IType type;
|
||||
IType[] genericArgs;
|
||||
|
||||
public GenericType(string type, IType[] genericArgs)
|
||||
: this(ITypeCreator.create(type), genericArgs) {
|
||||
}
|
||||
|
||||
public GenericType(Type type, IType[] genericArgs)
|
||||
: this(ITypeCreator.create(type), genericArgs) {
|
||||
}
|
||||
|
||||
public GenericType(IType type, IType[] genericArgs) {
|
||||
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('<');
|
||||
foreach (var ga in genericArgs)
|
||||
sb.Append(ga.ToString());
|
||||
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)) {
|
||||
}
|
||||
|
||||
public ListType(IType type)
|
||||
: base(typeof(List<>), new IType[] { type }) {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
public readonly IType baseType;
|
||||
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) {
|
||||
}
|
||||
|
||||
public TypeInfo(IType baseType, string name, string dcName, TypeFieldInfo[] fieldInfos)
|
||||
: this(baseType, name, "", dcName, fieldInfos) {
|
||||
}
|
||||
|
||||
public TypeInfo(IType baseType, string name, string dcNamespace, string dcName, TypeFieldInfo[] fieldInfos)
|
||||
: base(name, dcNamespace, dcName) {
|
||||
this.baseType = baseType;
|
||||
this.fieldInfos = fieldInfos;
|
||||
}
|
||||
}
|
||||
|
||||
class TypeFieldInfo {
|
||||
public readonly IType type;
|
||||
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) {
|
||||
}
|
||||
|
||||
public TypeFieldInfo(IType type, string name, string dmName) {
|
||||
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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
284
de4dot.code/deobfuscators/CodeFort/AssemblyDecrypter.cs
Normal file
284
de4dot.code/deobfuscators/CodeFort/AssemblyDecrypter.cs
Normal file
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
Copyright (C) 2011-2012 de4dot@gmail.com
|
||||
|
||||
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.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.CodeFort {
|
||||
class AssemblyDecrypter {
|
||||
ModuleDefinition module;
|
||||
EmbeddedResource assemblyEncryptedResource;
|
||||
PasswordInfo embedPassword;
|
||||
MethodDefinition embedInitMethod;
|
||||
MethodDefinition embedResolverMethod;
|
||||
|
||||
public class AssemblyInfo {
|
||||
public readonly byte[] data;
|
||||
public readonly EmbeddedResource resource;
|
||||
public readonly string asmFullName;
|
||||
public readonly string asmSimpleName;
|
||||
public readonly string extension;
|
||||
|
||||
public AssemblyInfo(byte[] data, EmbeddedResource resource, string asmFullName, string asmSimpleName, string extension) {
|
||||
this.data = data;
|
||||
this.resource = resource;
|
||||
this.asmFullName = asmFullName;
|
||||
this.asmSimpleName = asmSimpleName;
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return asmFullName;
|
||||
}
|
||||
}
|
||||
|
||||
public bool EncryptedDetected {
|
||||
get { return assemblyEncryptedResource != null; }
|
||||
}
|
||||
|
||||
public bool Detected {
|
||||
get { return EncryptedDetected || embedInitMethod != null; ; }
|
||||
}
|
||||
|
||||
public TypeDefinition Type {
|
||||
get { return embedInitMethod != null ? embedInitMethod.DeclaringType : null; }
|
||||
}
|
||||
|
||||
public MethodDefinition InitMethod {
|
||||
get { return embedInitMethod; }
|
||||
}
|
||||
|
||||
public AssemblyDecrypter(ModuleDefinition module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public AssemblyDecrypter(ModuleDefinition module, AssemblyDecrypter oldOne) {
|
||||
this.module = module;
|
||||
this.embedPassword = oldOne.embedPassword;
|
||||
}
|
||||
|
||||
public void find() {
|
||||
if (findEncrypted())
|
||||
return;
|
||||
findEmbedded();
|
||||
}
|
||||
|
||||
static readonly string[] encryptedRequiredLocals = new string[] {
|
||||
"System.Byte",
|
||||
"System.Byte[]",
|
||||
"System.Int32",
|
||||
"System.IO.BinaryReader",
|
||||
"System.IO.MemoryStream",
|
||||
"System.IO.Stream",
|
||||
"System.Object[]",
|
||||
"System.Reflection.Assembly",
|
||||
"System.Type[]",
|
||||
};
|
||||
bool findEncrypted() {
|
||||
var ep = module.EntryPoint;
|
||||
if (ep == null || ep.Body == null)
|
||||
return false;
|
||||
if (!DotNetUtils.isMethod(ep, "System.Void", "(System.String[])"))
|
||||
return false;
|
||||
var initMethod = checkCalledMethods(ep);
|
||||
if (initMethod == null || !new LocalTypes(initMethod).all(encryptedRequiredLocals))
|
||||
return false;
|
||||
var resource = getResource();
|
||||
if (resource == null)
|
||||
return false;
|
||||
|
||||
assemblyEncryptedResource = resource;
|
||||
return true;
|
||||
}
|
||||
|
||||
MethodDefinition checkCalledMethods(MethodDefinition method) {
|
||||
int calls = 0;
|
||||
TypeDefinition type = null;
|
||||
MethodDefinition initMethod = null;
|
||||
foreach (var calledMethod in DotNetUtils.getCalledMethods(module, method)) {
|
||||
calls++;
|
||||
if (type != null && calledMethod.DeclaringType != type)
|
||||
return null;
|
||||
type = calledMethod.DeclaringType;
|
||||
if (initMethod == null)
|
||||
initMethod = calledMethod;
|
||||
}
|
||||
if (calls != 2)
|
||||
return null;
|
||||
return initMethod;
|
||||
}
|
||||
|
||||
EmbeddedResource getResource() {
|
||||
return DotNetUtils.getResource(module, "_") as EmbeddedResource;
|
||||
}
|
||||
|
||||
bool findEmbedded() {
|
||||
foreach (var calledMethod in DotNetUtils.getCalledMethods(module, DotNetUtils.getModuleTypeCctor(module))) {
|
||||
var resolver = checkInitMethod(calledMethod);
|
||||
if (resolver == null)
|
||||
continue;
|
||||
if (!checkType(calledMethod.DeclaringType))
|
||||
continue;
|
||||
|
||||
embedInitMethod = calledMethod;
|
||||
embedResolverMethod = resolver;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MethodDefinition checkInitMethod(MethodDefinition method) {
|
||||
if (method == null || !method.IsStatic || method.Body == null)
|
||||
return null;
|
||||
if (!DotNetUtils.isMethod(method, "System.Void", "()"))
|
||||
return null;
|
||||
|
||||
var resolver = DeobUtils.getResolveMethod(method);
|
||||
if (resolver == null || resolver.DeclaringType != method.DeclaringType)
|
||||
return null;
|
||||
|
||||
return resolver;
|
||||
}
|
||||
|
||||
bool checkType(TypeDefinition type) {
|
||||
if (DotNetUtils.getMethod(type, "System.Byte[]", "(System.Byte[],System.String,System.String,System.Int32,System.String,System.Int32)") == null)
|
||||
return false;
|
||||
if (DotNetUtils.getMethod(type, "System.String", "(System.String)") == null)
|
||||
return false;
|
||||
if (DotNetUtils.getMethod(type, "System.Byte[]", "(System.Reflection.Assembly,System.String)") == null)
|
||||
return false;
|
||||
if (DotNetUtils.getMethod(type, "System.Void", "(System.IO.Stream,System.IO.Stream)") == null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public byte[] decrypt() {
|
||||
if (assemblyEncryptedResource == null)
|
||||
return null;
|
||||
|
||||
var reader = new BinaryReader(assemblyEncryptedResource.GetResourceStream());
|
||||
var encryptedData = DeobUtils.gunzip(reader.BaseStream, reader.ReadInt32());
|
||||
reader = new BinaryReader(new MemoryStream(encryptedData));
|
||||
var serializedData = reader.ReadBytes(reader.ReadInt32());
|
||||
for (int i = 0; i < serializedData.Length; i++)
|
||||
serializedData[i] ^= 0xAD;
|
||||
var encryptedAssembly = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
|
||||
|
||||
var passwordFinder = new PasswordFinder(serializedData);
|
||||
PasswordInfo mainAsmPassword;
|
||||
passwordFinder.find(out mainAsmPassword, out embedPassword);
|
||||
|
||||
return decrypt(mainAsmPassword, encryptedAssembly);
|
||||
}
|
||||
|
||||
static byte[] decrypt(PasswordInfo password, byte[] data) {
|
||||
const int iterations = 2;
|
||||
const int numBits = 0x100;
|
||||
var key = new Rfc2898DeriveBytes(password.passphrase, Encoding.UTF8.GetBytes(password.salt), iterations).GetBytes(numBits / 8);
|
||||
return DeobUtils.aesDecrypt(data, key, Encoding.UTF8.GetBytes(password.iv));
|
||||
}
|
||||
|
||||
static byte[] gunzip(byte[] data) {
|
||||
var reader = new BinaryReader(new MemoryStream(data));
|
||||
return DeobUtils.gunzip(reader.BaseStream, reader.ReadInt32());
|
||||
}
|
||||
|
||||
public List<AssemblyInfo> getAssemblyInfos(ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob) {
|
||||
var infos = new List<AssemblyInfo>();
|
||||
|
||||
if (embedResolverMethod != null) {
|
||||
simpleDeobfuscator.deobfuscate(embedResolverMethod);
|
||||
simpleDeobfuscator.decryptStrings(embedResolverMethod, deob);
|
||||
embedPassword = getEmbedPassword(embedResolverMethod);
|
||||
}
|
||||
|
||||
if (embedPassword == null)
|
||||
return infos;
|
||||
|
||||
foreach (var rsrc in module.Resources) {
|
||||
var resource = rsrc as EmbeddedResource;
|
||||
if (resource == null)
|
||||
continue;
|
||||
if (!Regex.IsMatch(resource.Name, "^cfd_([0-9a-f]{2})+_$"))
|
||||
continue;
|
||||
|
||||
var asmData = decrypt(embedPassword, gunzip(resource.GetResourceData()));
|
||||
var mod = ModuleDefinition.ReadModule(new MemoryStream(asmData));
|
||||
infos.Add(new AssemblyInfo(asmData, resource, mod.Assembly.FullName, mod.Assembly.Name.Name, DeobUtils.getExtension(mod.Kind)));
|
||||
}
|
||||
|
||||
return infos;
|
||||
}
|
||||
|
||||
static PasswordInfo getEmbedPassword(MethodDefinition method) {
|
||||
var instrs = method.Body.Instructions;
|
||||
for (int i = 0; i < instrs.Count - 3; i++) {
|
||||
int index = i;
|
||||
|
||||
var ldstr1 = instrs[index++];
|
||||
if (ldstr1.OpCode.Code != Code.Ldstr)
|
||||
continue;
|
||||
var passphrase = getString(ldstr1, instrs, ref index);
|
||||
|
||||
var ldstr2 = instrs[index++];
|
||||
if (ldstr2.OpCode.Code != Code.Ldstr)
|
||||
continue;
|
||||
var salt = getString(ldstr2, instrs, ref index);
|
||||
|
||||
var ldci4 = instrs[index++];
|
||||
if (!DotNetUtils.isLdcI4(ldci4))
|
||||
continue;
|
||||
|
||||
var ldstr3 = instrs[index++];
|
||||
if (ldstr3.OpCode.Code != Code.Ldstr)
|
||||
continue;
|
||||
var iv = getString(ldstr3, instrs, ref index);
|
||||
|
||||
return new PasswordInfo(passphrase, salt, iv);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static string getString(Instruction ldstr, IList<Instruction> instrs, ref int index) {
|
||||
var s = (string)ldstr.Operand;
|
||||
if (index >= instrs.Count)
|
||||
return s;
|
||||
var call = instrs[index];
|
||||
if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt)
|
||||
return s;
|
||||
index++;
|
||||
var calledMethod = call.Operand as MethodReference;
|
||||
if (calledMethod.Name == "ToUpper")
|
||||
return s.ToUpper();
|
||||
if (calledMethod.Name == "ToLower")
|
||||
return s.ToLower();
|
||||
throw new ApplicationException(string.Format("Unknown method {0}", calledMethod));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -58,6 +58,7 @@ namespace de4dot.code.deobfuscators.CodeFort {
|
|||
Options options;
|
||||
ProxyCallFixer proxyCallFixer;
|
||||
StringDecrypter stringDecrypter;
|
||||
AssemblyDecrypter assemblyDecrypter;
|
||||
|
||||
internal class Options : OptionsBase {
|
||||
}
|
||||
|
@ -83,7 +84,8 @@ namespace de4dot.code.deobfuscators.CodeFort {
|
|||
int val = 0;
|
||||
|
||||
int sum = toInt32(proxyCallFixer.Detected) +
|
||||
toInt32(stringDecrypter.Detected);
|
||||
toInt32(stringDecrypter.Detected) +
|
||||
toInt32(assemblyDecrypter.Detected);
|
||||
if (sum > 0)
|
||||
val += 100 + 10 * (sum - 1);
|
||||
|
||||
|
@ -95,6 +97,35 @@ namespace de4dot.code.deobfuscators.CodeFort {
|
|||
proxyCallFixer.findDelegateCreator();
|
||||
stringDecrypter = new StringDecrypter(module);
|
||||
stringDecrypter.find();
|
||||
assemblyDecrypter = new AssemblyDecrypter(module);
|
||||
assemblyDecrypter.find();
|
||||
}
|
||||
|
||||
public override bool getDecryptedModule(ref byte[] newFileData, ref DumpedMethods dumpedMethods) {
|
||||
if (!assemblyDecrypter.EncryptedDetected)
|
||||
return false;
|
||||
|
||||
newFileData = assemblyDecrypter.decrypt();
|
||||
return newFileData != null;
|
||||
}
|
||||
|
||||
public override IDeobfuscator moduleReloaded(ModuleDefinition module) {
|
||||
var newOne = new Deobfuscator(options);
|
||||
newOne.setModule(module);
|
||||
newOne.proxyCallFixer = new ProxyCallFixer(module);
|
||||
newOne.proxyCallFixer.findDelegateCreator();
|
||||
newOne.stringDecrypter = new StringDecrypter(module);
|
||||
newOne.stringDecrypter.find();
|
||||
newOne.assemblyDecrypter = new AssemblyDecrypter(module, assemblyDecrypter);
|
||||
newOne.assemblyDecrypter.find();
|
||||
return newOne;
|
||||
}
|
||||
|
||||
static List<TypeDefinition> lookup(ModuleDefinition module, List<TypeDefinition> types, string errorMsg) {
|
||||
var list = new List<TypeDefinition>(types.Count);
|
||||
foreach (var type in types)
|
||||
list.Add(DeobUtils.lookup(module, type, errorMsg));
|
||||
return list;
|
||||
}
|
||||
|
||||
public override void deobfuscateBegin() {
|
||||
|
@ -104,6 +135,18 @@ namespace de4dot.code.deobfuscators.CodeFort {
|
|||
DeobfuscatedFile.stringDecryptersAdded();
|
||||
|
||||
proxyCallFixer.find();
|
||||
|
||||
dumpEmbeddedAssemblies();
|
||||
}
|
||||
|
||||
void dumpEmbeddedAssemblies() {
|
||||
foreach (var info in assemblyDecrypter.getAssemblyInfos(DeobfuscatedFile, this)) {
|
||||
DeobfuscatedFile.createAssemblyFile(info.data, info.asmSimpleName, info.extension);
|
||||
addResourceToBeRemoved(info.resource, string.Format("Embedded assembly: {0}", info.asmFullName));
|
||||
}
|
||||
addCctorInitCallToBeRemoved(assemblyDecrypter.InitMethod);
|
||||
addCallToBeRemoved(module.EntryPoint, assemblyDecrypter.InitMethod);
|
||||
addTypeToBeRemoved(assemblyDecrypter.Type, "Assembly resolver type");
|
||||
}
|
||||
|
||||
public override void deobfuscateMethodEnd(Blocks blocks) {
|
||||
|
|
224
de4dot.code/deobfuscators/CodeFort/PasswordFinder.cs
Normal file
224
de4dot.code/deobfuscators/CodeFort/PasswordFinder.cs
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
Copyright (C) 2011-2012 de4dot@gmail.com
|
||||
|
||||
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 Mono.Cecil;
|
||||
|
||||
namespace de4dot.code.deobfuscators.CodeFort {
|
||||
class PasswordInfo {
|
||||
public string passphrase;
|
||||
public string salt;
|
||||
public string iv;
|
||||
|
||||
public PasswordInfo(string passphrase, string salt, string iv) {
|
||||
this.passphrase = passphrase;
|
||||
this.salt = salt;
|
||||
this.iv = iv;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return string.Format("P:{0}, S:{1}, I:{2}", passphrase, salt, iv);
|
||||
}
|
||||
}
|
||||
|
||||
class PasswordFinder {
|
||||
byte[] serializedData;
|
||||
System.Collections.IList asmTypes;
|
||||
|
||||
class Obj {
|
||||
object obj;
|
||||
|
||||
public Obj(object obj) {
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
public string Name {
|
||||
get { return (string)readField("Name"); }
|
||||
}
|
||||
|
||||
public List<Obj> Members {
|
||||
get { return getList("Members"); }
|
||||
}
|
||||
|
||||
public List<Obj> Instructions {
|
||||
get { return getList("Instructions"); }
|
||||
}
|
||||
|
||||
public object Operand {
|
||||
get { return readField("Operand"); }
|
||||
}
|
||||
|
||||
public string OpCode {
|
||||
get { return (string)readField("OpCode"); }
|
||||
}
|
||||
|
||||
public Obj MemberDef {
|
||||
get { return new Obj(readField("MemberDef")); }
|
||||
}
|
||||
|
||||
protected object readField(string name) {
|
||||
return PasswordFinder.readField(obj, name);
|
||||
}
|
||||
|
||||
public Obj findMethod(string name) {
|
||||
foreach (var member in Members) {
|
||||
if (member.obj.GetType().ToString() != "MethodDef")
|
||||
continue;
|
||||
if (member.Name != name)
|
||||
continue;
|
||||
|
||||
return member;
|
||||
}
|
||||
|
||||
throw new ApplicationException(string.Format("Could not find method {0}", name));
|
||||
}
|
||||
|
||||
List<Obj> getList(string name) {
|
||||
return convertList((System.Collections.IList)readField(name));
|
||||
}
|
||||
|
||||
static List<Obj> convertList(System.Collections.IList inList) {
|
||||
var outList = new List<Obj>(inList.Count);
|
||||
foreach (var e in inList)
|
||||
outList.Add(new Obj(e));
|
||||
return outList;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
public PasswordFinder(byte[] serializedData) {
|
||||
this.serializedData = serializedData;
|
||||
}
|
||||
|
||||
static object readField(object instance, string name) {
|
||||
return instance.GetType().GetField(name).GetValue(instance);
|
||||
}
|
||||
|
||||
static System.Collections.IList toList(object obj) {
|
||||
return (System.Collections.IList)obj;
|
||||
}
|
||||
|
||||
public void find(out PasswordInfo mainAsmPassword, out PasswordInfo embedPassword) {
|
||||
var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("asm"), AssemblyBuilderAccess.Run);
|
||||
var moduleBuilder = asmBuilder.DefineDynamicModule("mod");
|
||||
var serializedTypes = new SerializedTypes(moduleBuilder);
|
||||
var allTypes = serializedTypes.deserialize(serializedData);
|
||||
asmTypes = toList(readField(allTypes, "Types"));
|
||||
|
||||
mainAsmPassword = findMainAssemblyPassword();
|
||||
embedPassword = findEmbedPassword();
|
||||
}
|
||||
|
||||
Obj findType(string name) {
|
||||
foreach (var tmp in asmTypes) {
|
||||
var type = new Obj(tmp);
|
||||
if (type.Name == name)
|
||||
return type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
PasswordInfo findMainAssemblyPassword() {
|
||||
var type = findType("BootstrapDynArguments");
|
||||
var cctor = type.findMethod(".cctor");
|
||||
var instrs = cctor.Instructions;
|
||||
var passphrase = findStringStoreValue(instrs, "KeyPassphrase");
|
||||
var salt = findStringStoreValue(instrs, "KeySaltValue");
|
||||
var iv = findStringStoreValue(instrs, "KeyIV");
|
||||
return new PasswordInfo(passphrase, salt, iv);
|
||||
}
|
||||
|
||||
static string findStringStoreValue(List<Obj> instrs, string fieldName) {
|
||||
for (int i = 0; i < instrs.Count - 1; i++) {
|
||||
var ldstr = instrs[i];
|
||||
if (ldstr.OpCode != "ldstr")
|
||||
continue;
|
||||
var stsfld = instrs[i + 1];
|
||||
if (stsfld.OpCode != "stsfld")
|
||||
continue;
|
||||
var memberRef = new Obj(stsfld.Operand);
|
||||
if (memberRef.MemberDef == null)
|
||||
continue;
|
||||
if (memberRef.MemberDef.Name != fieldName)
|
||||
continue;
|
||||
|
||||
return (string)ldstr.Operand;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
PasswordInfo findEmbedPassword() {
|
||||
var type = findType("CilEmbeddingHelper");
|
||||
if (type == null)
|
||||
return null;
|
||||
var method = type.findMethod("CurrentDomain_AssemblyResolve");
|
||||
var instrs = method.Instructions;
|
||||
for (int i = 0; i < instrs.Count - 3; i++) {
|
||||
int index = i;
|
||||
|
||||
var ldstr1 = instrs[index++];
|
||||
if (ldstr1.OpCode != "ldstr")
|
||||
continue;
|
||||
var passphrase = getString(ldstr1, instrs, ref index);
|
||||
|
||||
var ldstr2 = instrs[index++];
|
||||
if (ldstr2.OpCode != "ldstr")
|
||||
continue;
|
||||
var salt = getString(ldstr2, instrs, ref index);
|
||||
|
||||
var ldc = instrs[index++];
|
||||
if (!ldc.OpCode.StartsWith("ldc.i4"))
|
||||
continue;
|
||||
|
||||
var ldstr3 = instrs[index++];
|
||||
if (ldstr3.OpCode != "ldstr")
|
||||
continue;
|
||||
var iv = getString(ldstr3, instrs, ref index);
|
||||
|
||||
return new PasswordInfo(passphrase, salt, iv);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static string getString(Obj ldstr, List<Obj> instrs, ref int index) {
|
||||
var s = (string)ldstr.Operand;
|
||||
if (index >= instrs.Count)
|
||||
return s;
|
||||
var call = instrs[index];
|
||||
if (call.OpCode != "call" && call.OpCode != "callvirt")
|
||||
return s;
|
||||
index++;
|
||||
var op = new Obj(call.Operand);
|
||||
if (op.Name == "ToUpper")
|
||||
return s.ToUpper();
|
||||
if (op.Name == "ToLower")
|
||||
return s.ToLower();
|
||||
throw new ApplicationException(string.Format("Unknown method {0}", op.Name));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
|
@ -154,6 +155,15 @@ namespace de4dot.code.deobfuscators {
|
|||
return memStream.ToArray();
|
||||
}
|
||||
|
||||
public static byte[] gunzip(Stream input, int decompressedSize) {
|
||||
using (var gzip = new GZipStream(input, CompressionMode.Decompress)) {
|
||||
var decompressed = new byte[decompressedSize];
|
||||
if (gzip.Read(decompressed, 0, decompressedSize) != decompressedSize)
|
||||
throw new ApplicationException("Could not gzip decompress");
|
||||
return decompressed;
|
||||
}
|
||||
}
|
||||
|
||||
public static EmbeddedResource getEmbeddedResourceFromCodeStrings(ModuleDefinition module, MethodDefinition method) {
|
||||
foreach (var s in DotNetUtils.getCodeStrings(method)) {
|
||||
var resource = DotNetUtils.getResource(module, s) as EmbeddedResource;
|
||||
|
|
Loading…
Reference in New Issue
Block a user