Merge branch 'port' into confuser
This commit is contained in:
commit
c3608908c5
|
@ -34,7 +34,7 @@ using ROpCodes = System.Reflection.Emit.OpCodes;
|
||||||
|
|
||||||
namespace AssemblyData.methodsrewriter {
|
namespace AssemblyData.methodsrewriter {
|
||||||
class CodeGenerator {
|
class CodeGenerator {
|
||||||
static Dictionary<OpCode, ROpCode> cecilToReflection = new Dictionary<OpCode, ROpCode>();
|
static Dictionary<OpCode, ROpCode> dot10ToReflection = new Dictionary<OpCode, ROpCode>();
|
||||||
static CodeGenerator() {
|
static CodeGenerator() {
|
||||||
var refDict = new Dictionary<short, ROpCode>(0x100);
|
var refDict = new Dictionary<short, ROpCode>(0x100);
|
||||||
foreach (var f in typeof(ROpCodes).GetFields(BindingFlags.Static | BindingFlags.Public)) {
|
foreach (var f in typeof(ROpCodes).GetFields(BindingFlags.Static | BindingFlags.Public)) {
|
||||||
|
@ -51,7 +51,7 @@ namespace AssemblyData.methodsrewriter {
|
||||||
ROpCode ropcode;
|
ROpCode ropcode;
|
||||||
if (!refDict.TryGetValue(opcode.Value, out ropcode))
|
if (!refDict.TryGetValue(opcode.Value, out ropcode))
|
||||||
continue;
|
continue;
|
||||||
cecilToReflection[opcode] = ropcode;
|
dot10ToReflection[opcode] = ropcode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,7 +332,7 @@ namespace AssemblyData.methodsrewriter {
|
||||||
|
|
||||||
ROpCode convertOpCode(OpCode opcode) {
|
ROpCode convertOpCode(OpCode opcode) {
|
||||||
ROpCode ropcode;
|
ROpCode ropcode;
|
||||||
if (cecilToReflection.TryGetValue(opcode, out ropcode))
|
if (dot10ToReflection.TryGetValue(opcode, out ropcode))
|
||||||
return ropcode;
|
return ropcode;
|
||||||
return ROpCodes.Nop;
|
return ROpCodes.Nop;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,9 @@ namespace AssemblyData.methodsrewriter {
|
||||||
class MMethod {
|
class MMethod {
|
||||||
public MethodBase methodBase;
|
public MethodBase methodBase;
|
||||||
public MethodDef methodDef;
|
public MethodDef methodDef;
|
||||||
public MMethod(MethodBase methodBase, MethodDef methodDefinition) {
|
public MMethod(MethodBase methodBase, MethodDef methodDef) {
|
||||||
this.methodBase = methodBase;
|
this.methodBase = methodBase;
|
||||||
this.methodDef = methodDefinition;
|
this.methodDef = methodDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool hasInstructions() {
|
public bool hasInstructions() {
|
||||||
|
|
|
@ -27,15 +27,15 @@ namespace AssemblyData.methodsrewriter {
|
||||||
class MModule {
|
class MModule {
|
||||||
public Module module;
|
public Module module;
|
||||||
public ModuleDefMD moduleDef;
|
public ModuleDefMD moduleDef;
|
||||||
TypeDefinitionDict<MType> typeReferenceToType = new TypeDefinitionDict<MType>();
|
TypeDefDict<MType> typeRefToType = new TypeDefDict<MType>();
|
||||||
Dictionary<int, MType> tokenToType = new Dictionary<int, MType>();
|
Dictionary<int, MType> tokenToType = new Dictionary<int, MType>();
|
||||||
Dictionary<int, MMethod> tokenToGlobalMethod;
|
Dictionary<int, MMethod> tokenToGlobalMethod;
|
||||||
Dictionary<int, MField> tokenToGlobalField;
|
Dictionary<int, MField> tokenToGlobalField;
|
||||||
TypeDef moduleType;
|
TypeDef moduleType;
|
||||||
|
|
||||||
public MModule(Module module, ModuleDefMD moduleDefinition) {
|
public MModule(Module module, ModuleDefMD moduleDef) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.moduleDef = moduleDefinition;
|
this.moduleDef = moduleDef;
|
||||||
initTokenToType();
|
initTokenToType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,17 +49,17 @@ namespace AssemblyData.methodsrewriter {
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
tokenToType[token] = null;
|
tokenToType[token] = null;
|
||||||
typeReferenceToType.add(typeDef, null);
|
typeRefToType.add(typeDef, null);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var mtype = new MType(type, typeDef);
|
var mtype = new MType(type, typeDef);
|
||||||
tokenToType[token] = mtype;
|
tokenToType[token] = mtype;
|
||||||
typeReferenceToType.add(typeDef, mtype);
|
typeRefToType.add(typeDef, mtype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MType getType(IType typeRef) {
|
public MType getType(IType typeRef) {
|
||||||
return typeReferenceToType.find(typeRef);
|
return typeRefToType.find(typeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MMethod getMethod(IMethod methodRef) {
|
public MMethod getMethod(IMethod methodRef) {
|
||||||
|
|
|
@ -28,23 +28,23 @@ namespace AssemblyData.methodsrewriter {
|
||||||
public Type type;
|
public Type type;
|
||||||
public TypeDef typeDef;
|
public TypeDef typeDef;
|
||||||
Dictionary<int, MMethod> tokenToMethod;
|
Dictionary<int, MMethod> tokenToMethod;
|
||||||
MethodDefinitionDict<MMethod> methodReferenceToMethod;
|
MethodDefDict<MMethod> methodRefToMethod;
|
||||||
Dictionary<int, MField> tokenToField;
|
Dictionary<int, MField> tokenToField;
|
||||||
FieldDefinitionDict<MField> fieldReferenceToField;
|
FieldDefDict<MField> fieldRefToField;
|
||||||
|
|
||||||
public MType(Type type, TypeDef typeDefinition) {
|
public MType(Type type, TypeDef typeDef) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.typeDef = typeDefinition;
|
this.typeDef = typeDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MMethod getMethod(IMethod methodRef) {
|
public MMethod getMethod(IMethod methodRef) {
|
||||||
initMethods();
|
initMethods();
|
||||||
return methodReferenceToMethod.find(methodRef);
|
return methodRefToMethod.find(methodRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MField getField(IField fieldRef) {
|
public MField getField(IField fieldRef) {
|
||||||
initFields();
|
initFields();
|
||||||
return fieldReferenceToField.find(fieldRef);
|
return fieldRefToField.find(fieldRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MMethod getMethod(int token) {
|
public MMethod getMethod(int token) {
|
||||||
|
@ -61,7 +61,7 @@ namespace AssemblyData.methodsrewriter {
|
||||||
if (tokenToMethod != null)
|
if (tokenToMethod != null)
|
||||||
return;
|
return;
|
||||||
tokenToMethod = new Dictionary<int, MMethod>(typeDef.Methods.Count);
|
tokenToMethod = new Dictionary<int, MMethod>(typeDef.Methods.Count);
|
||||||
methodReferenceToMethod = new MethodDefinitionDict<MMethod>();
|
methodRefToMethod = new MethodDefDict<MMethod>();
|
||||||
|
|
||||||
var tmpTokenToMethod = new Dictionary<int, MethodBase>();
|
var tmpTokenToMethod = new Dictionary<int, MethodBase>();
|
||||||
var flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
|
var flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
|
@ -71,7 +71,7 @@ namespace AssemblyData.methodsrewriter {
|
||||||
var token = (int)m.MDToken.Raw;
|
var token = (int)m.MDToken.Raw;
|
||||||
var method = new MMethod(tmpTokenToMethod[token], m);
|
var method = new MMethod(tmpTokenToMethod[token], m);
|
||||||
tokenToMethod[token] = method;
|
tokenToMethod[token] = method;
|
||||||
methodReferenceToMethod.add(method.methodDef, method);
|
methodRefToMethod.add(method.methodDef, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ namespace AssemblyData.methodsrewriter {
|
||||||
if (tokenToField != null)
|
if (tokenToField != null)
|
||||||
return;
|
return;
|
||||||
tokenToField = new Dictionary<int, MField>(typeDef.Fields.Count);
|
tokenToField = new Dictionary<int, MField>(typeDef.Fields.Count);
|
||||||
fieldReferenceToField = new FieldDefinitionDict<MField>();
|
fieldRefToField = new FieldDefDict<MField>();
|
||||||
|
|
||||||
var tmpTokenToField = new Dictionary<int, FieldInfo>();
|
var tmpTokenToField = new Dictionary<int, FieldInfo>();
|
||||||
var flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
|
var flags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
|
@ -89,7 +89,7 @@ namespace AssemblyData.methodsrewriter {
|
||||||
var token = (int)f.MDToken.Raw;
|
var token = (int)f.MDToken.Raw;
|
||||||
var field = new MField(tmpTokenToField[token], f);
|
var field = new MField(tmpTokenToField[token], f);
|
||||||
tokenToField[token] = field;
|
tokenToField[token] = field;
|
||||||
fieldReferenceToField.add(field.fieldDef, field);
|
fieldRefToField.add(field.fieldDef, field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,21 +73,21 @@ namespace AssemblyData.methodsrewriter {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MMethod getMethod(IMethod methodReference) {
|
public static MMethod getMethod(IMethod methodRef) {
|
||||||
if (methodReference == null)
|
if (methodRef == null)
|
||||||
return null;
|
return null;
|
||||||
var module = getModule(methodReference.DeclaringType.Scope);
|
var module = getModule(methodRef.DeclaringType.Scope);
|
||||||
if (module != null)
|
if (module != null)
|
||||||
return module.getMethod(methodReference);
|
return module.getMethod(methodRef);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MField getField(IField fieldReference) {
|
public static MField getField(IField fieldRef) {
|
||||||
if (fieldReference == null)
|
if (fieldRef == null)
|
||||||
return null;
|
return null;
|
||||||
var module = getModule(fieldReference.DeclaringType.Scope);
|
var module = getModule(fieldRef.DeclaringType.Scope);
|
||||||
if (module != null)
|
if (module != null)
|
||||||
return module.getField(fieldReference);
|
return module.getField(fieldRef);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ namespace AssemblyData.methodsrewriter {
|
||||||
if (method != null && method.MethodSig != null)
|
if (method != null && method.MethodSig != null)
|
||||||
return getRtMethod(method);
|
return getRtMethod(method);
|
||||||
|
|
||||||
throw new ApplicationException(string.Format("Unknown MemberReference: {0}", memberRef));
|
throw new ApplicationException(string.Format("Unknown MemberRef: {0}", memberRef));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type getRtType(IType typeRef) {
|
public static Type getRtType(IType typeRef) {
|
||||||
|
|
9
AssemblyServer-CLR20-x64/App.config
Normal file
9
AssemblyServer-CLR20-x64/App.config
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v2.0.50727"/>
|
||||||
|
</startup>
|
||||||
|
<runtime>
|
||||||
|
<loadFromRemoteSources enabled="true"/>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
65
AssemblyServer-CLR20-x64/AssemblyServer-CLR20-x64.csproj
Normal file
65
AssemblyServer-CLR20-x64/AssemblyServer-CLR20-x64.csproj
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{9F84607D-3662-4CF2-BA40-8BDB11935643}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>AssemblyServer_CLR20_x64</RootNamespace>
|
||||||
|
<AssemblyName>AssemblyServer-CLR20-x64</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<SignAssembly>true</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>..\de4dot.snk</AssemblyOriginatorKeyFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>..\Debug\bin\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>..\Release\bin\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- Fix a warning that the referenced mscorlib is not 64-bit... -->
|
||||||
|
<Reference Include="$(Windir)\Microsoft.NET\Framework64\v2.0.50727\mscorlib.dll" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AssemblyData\AssemblyData.csproj">
|
||||||
|
<Project>{FBD84077-9D35-41FE-89DF-8D79EFE0B595}</Project>
|
||||||
|
<Name>AssemblyData</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
|
@ -17,20 +17,10 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.IO;
|
namespace AssemblyServer_CLR20_x64 {
|
||||||
|
class Program {
|
||||||
namespace de4dot.PE {
|
static int Main(string[] args) {
|
||||||
public struct DataDirectory {
|
return AssemblyServer.Start.main(args);
|
||||||
public uint virtualAddress;
|
|
||||||
public uint size;
|
|
||||||
|
|
||||||
public void read(BinaryReader reader) {
|
|
||||||
virtualAddress = reader.ReadUInt32();
|
|
||||||
size = reader.ReadUInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return string.Format("{0:X8} {1:X8}", virtualAddress, size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
33
AssemblyServer-CLR20-x64/Properties/AssemblyInfo.cs
Normal file
33
AssemblyServer-CLR20-x64/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
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.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
[assembly: AssemblyTitle("AssemblyServer-CLR20-x64")]
|
||||||
|
[assembly: AssemblyDescription("Assembly Server - CLR v2.0 - x64")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("AssemblyServer-CLR20-x64")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright (C) 2011-2012 de4dot@gmail.com")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||||
|
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
9
AssemblyServer-CLR20/App.config
Normal file
9
AssemblyServer-CLR20/App.config
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v2.0.50727"/>
|
||||||
|
</startup>
|
||||||
|
<runtime>
|
||||||
|
<loadFromRemoteSources enabled="true"/>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
59
AssemblyServer-CLR20/AssemblyServer-CLR20.csproj
Normal file
59
AssemblyServer-CLR20/AssemblyServer-CLR20.csproj
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{C72DC899-1760-432B-B429-3CD88B669A6A}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>AssemblyServer_CLR20</RootNamespace>
|
||||||
|
<AssemblyName>AssemblyServer-CLR20</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<SignAssembly>true</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>..\de4dot.snk</AssemblyOriginatorKeyFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>..\Debug\bin\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>..\Release\bin\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AssemblyData\AssemblyData.csproj">
|
||||||
|
<Project>{FBD84077-9D35-41FE-89DF-8D79EFE0B595}</Project>
|
||||||
|
<Name>AssemblyData</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
|
@ -17,9 +17,10 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace de4dot.PE {
|
namespace AssemblyServer_CLR20 {
|
||||||
public interface IFileLocation {
|
class Program {
|
||||||
uint Offset { get; }
|
static int Main(string[] args) {
|
||||||
uint Length { get; }
|
return AssemblyServer.Start.main(args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
33
AssemblyServer-CLR20/Properties/AssemblyInfo.cs
Normal file
33
AssemblyServer-CLR20/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
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.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
[assembly: AssemblyTitle("AssemblyServer-CLR20")]
|
||||||
|
[assembly: AssemblyDescription("Assembly Server - CLR v2.0 - x86")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("AssemblyServer-CLR20")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright (C) 2011-2012 de4dot@gmail.com")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||||
|
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
9
AssemblyServer-CLR40-x64/App.config
Normal file
9
AssemblyServer-CLR40-x64/App.config
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0"/>
|
||||||
|
</startup>
|
||||||
|
<runtime>
|
||||||
|
<loadFromRemoteSources enabled="true"/>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
67
AssemblyServer-CLR40-x64/AssemblyServer-CLR40-x64.csproj
Normal file
67
AssemblyServer-CLR40-x64/AssemblyServer-CLR40-x64.csproj
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{A0F58B9F-BB56-4D9B-B04A-726F9E7961EB}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>AssemblyServer_CLR40_x64</RootNamespace>
|
||||||
|
<AssemblyName>AssemblyServer-CLR40-x64</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<SignAssembly>true</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>..\de4dot.snk</AssemblyOriginatorKeyFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>..\Debug\bin\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoWarn>1685</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>..\Release\bin\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoWarn>1685</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- Fix a warning that the referenced mscorlib is not 64-bit... -->
|
||||||
|
<Reference Include="$(Windir)\Microsoft.NET\Framework64\v4.0.30319\mscorlib.dll" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AssemblyData\AssemblyData.csproj">
|
||||||
|
<Project>{FBD84077-9D35-41FE-89DF-8D79EFE0B595}</Project>
|
||||||
|
<Name>AssemblyData</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
|
@ -17,30 +17,10 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.IO;
|
namespace AssemblyServer_CLR40_x64 {
|
||||||
|
class Program {
|
||||||
namespace de4dot.PE {
|
static int Main(string[] args) {
|
||||||
public class DotNetStream : IFileLocation {
|
return AssemblyServer.Start.main(args);
|
||||||
public string name;
|
|
||||||
public uint fileOffset;
|
|
||||||
public uint length;
|
|
||||||
|
|
||||||
public uint Offset {
|
|
||||||
get { return fileOffset; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Length {
|
|
||||||
get { return length; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public DotNetStream(string name, uint fileOffset, uint length) {
|
|
||||||
this.name = name;
|
|
||||||
this.fileOffset = fileOffset;
|
|
||||||
this.length = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return string.Format("{0:X8} {1:X8} {2}", fileOffset, length, name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
33
AssemblyServer-CLR40-x64/Properties/AssemblyInfo.cs
Normal file
33
AssemblyServer-CLR40-x64/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
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.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
[assembly: AssemblyTitle("AssemblyServer-CLR40-x64")]
|
||||||
|
[assembly: AssemblyDescription("Assembly Server - CLR v4.0 - x64")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("AssemblyServer-CLR40-x64")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright (C) 2011-2012 de4dot@gmail.com")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||||
|
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
9
AssemblyServer-CLR40/App.config
Normal file
9
AssemblyServer-CLR40/App.config
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0"/>
|
||||||
|
</startup>
|
||||||
|
<runtime>
|
||||||
|
<loadFromRemoteSources enabled="true"/>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
59
AssemblyServer-CLR40/AssemblyServer-CLR40.csproj
Normal file
59
AssemblyServer-CLR40/AssemblyServer-CLR40.csproj
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{B8FF4ADD-BAD8-47FD-B126-63234E2BB0B3}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>AssemblyServer_CLR40</RootNamespace>
|
||||||
|
<AssemblyName>AssemblyServer-CLR40</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<SignAssembly>true</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>..\de4dot.snk</AssemblyOriginatorKeyFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>..\Debug\bin\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>..\Release\bin\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AssemblyData\AssemblyData.csproj">
|
||||||
|
<Project>{FBD84077-9D35-41FE-89DF-8D79EFE0B595}</Project>
|
||||||
|
<Name>AssemblyData</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
|
@ -17,33 +17,10 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace de4dot.PE {
|
namespace AssemblyServer_CLR40 {
|
||||||
public class ResourceData : ResourceDirectoryEntry {
|
class Program {
|
||||||
uint rva;
|
static int Main(string[] args) {
|
||||||
uint size;
|
return AssemblyServer.Start.main(args);
|
||||||
|
|
||||||
public uint RVA {
|
|
||||||
get { return rva; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Size {
|
|
||||||
get { return size; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceData(int id, uint rva, uint size)
|
|
||||||
: base(id) {
|
|
||||||
this.rva = rva;
|
|
||||||
this.size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceData(string name, uint dataOffset, uint dataSize)
|
|
||||||
: base(name) {
|
|
||||||
this.rva = dataOffset;
|
|
||||||
this.size = dataSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return string.Format("RVA: {0:X8} SIZE: {1:X8}, NAME: {2}", rva, size, getName());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
33
AssemblyServer-CLR40/Properties/AssemblyInfo.cs
Normal file
33
AssemblyServer-CLR40/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
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.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
[assembly: AssemblyTitle("AssemblyServer-CLR40")]
|
||||||
|
[assembly: AssemblyDescription("Assembly Server - CLR v4.0 - x86")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("AssemblyServer-CLR40")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright (C) 2011-2012 de4dot@gmail.com")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||||
|
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
|
@ -21,7 +21,7 @@ using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
[assembly: AssemblyTitle("AssemblyServer-x64")]
|
[assembly: AssemblyTitle("AssemblyServer-x64")]
|
||||||
[assembly: AssemblyDescription("Assembly Server - x64")]
|
[assembly: AssemblyDescription("Assembly Server - CLR any version - x64")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct("AssemblyServer-x64")]
|
[assembly: AssemblyProduct("AssemblyServer-x64")]
|
||||||
|
|
|
@ -21,7 +21,7 @@ using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
[assembly: AssemblyTitle("AssemblyServer")]
|
[assembly: AssemblyTitle("AssemblyServer")]
|
||||||
[assembly: AssemblyDescription("Assembly Server - AnyCpu")]
|
[assembly: AssemblyDescription("Assembly Server - CLR any version - x86")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct("AssemblyServer")]
|
[assembly: AssemblyProduct("AssemblyServer")]
|
||||||
|
|
|
@ -91,10 +91,10 @@ namespace de4dot.blocks {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FieldDef findFieldType(TypeDef typeDefinition, string typeName, bool isStatic) {
|
public static FieldDef findFieldType(TypeDef typeDef, string typeName, bool isStatic) {
|
||||||
if (typeDefinition == null)
|
if (typeDef == null)
|
||||||
return null;
|
return null;
|
||||||
foreach (var field in typeDefinition.Fields) {
|
foreach (var field in typeDef.Fields) {
|
||||||
if (field.IsStatic == isStatic && field.FieldSig.GetFieldType().GetFullName() == typeName)
|
if (field.IsStatic == isStatic && field.FieldSig.GetFieldType().GetFullName() == typeName)
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
@ -274,12 +274,12 @@ namespace de4dot.blocks {
|
||||||
return getField(getType(module, field.DeclaringType), field);
|
return getField(getType(module, field.DeclaringType), field);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FieldDef getField(TypeDef type, IField fieldReference) {
|
public static FieldDef getField(TypeDef type, IField fieldRef) {
|
||||||
if (type == null || fieldReference == null)
|
if (type == null || fieldRef == null)
|
||||||
return null;
|
return null;
|
||||||
if (fieldReference is FieldDef)
|
if (fieldRef is FieldDef)
|
||||||
return (FieldDef)fieldReference;
|
return (FieldDef)fieldRef;
|
||||||
return type.FindField(fieldReference.Name, fieldReference.FieldSig);
|
return type.FindField(fieldRef.Name, fieldRef.FieldSig);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FieldDef getField(TypeDef type, string typeFullName) {
|
public static FieldDef getField(TypeDef type, string typeFullName) {
|
||||||
|
@ -596,7 +596,7 @@ namespace de4dot.blocks {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeDefOrRefSig findOrCreateTypeReference(ModuleDef module, AssemblyRef asmRef, string ns, string name, bool isValueType) {
|
public static TypeDefOrRefSig findOrCreateTypeRef(ModuleDef module, AssemblyRef asmRef, string ns, string name, bool isValueType) {
|
||||||
var typeRef = module.UpdateRowId(new TypeRefUser(module, ns, name, asmRef));
|
var typeRef = module.UpdateRowId(new TypeRefUser(module, ns, name, asmRef));
|
||||||
if (isValueType)
|
if (isValueType)
|
||||||
return new ValueTypeSig(typeRef);
|
return new ValueTypeSig(typeRef);
|
||||||
|
|
|
@ -23,7 +23,7 @@ using System.Collections.Generic;
|
||||||
namespace de4dot.blocks {
|
namespace de4dot.blocks {
|
||||||
// This class makes sure that each block that is entered with a non-empty stack has at
|
// This class makes sure that each block that is entered with a non-empty stack has at
|
||||||
// least one of its source blocks sorted before itself. This is to make sure peverify
|
// least one of its source blocks sorted before itself. This is to make sure peverify
|
||||||
// doesn't complain AND also to make sure Mono.Cecil sets the correct maxstack.
|
// doesn't complain AND also to make sure dot10 sets the correct maxstack.
|
||||||
class ForwardScanOrder {
|
class ForwardScanOrder {
|
||||||
ScopeBlock scopeBlock;
|
ScopeBlock scopeBlock;
|
||||||
IList<BaseBlock> sorted;
|
IList<BaseBlock> sorted;
|
||||||
|
|
|
@ -22,7 +22,7 @@ using System.Collections.Generic;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
|
|
||||||
namespace de4dot.blocks {
|
namespace de4dot.blocks {
|
||||||
public class TypeDefinitionDict<TValue> {
|
public class TypeDefDict<TValue> {
|
||||||
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
|
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
|
||||||
Dictionary<ScopeAndTokenKey, TypeDef> tokenToKey = new Dictionary<ScopeAndTokenKey, TypeDef>();
|
Dictionary<ScopeAndTokenKey, TypeDef> tokenToKey = new Dictionary<ScopeAndTokenKey, TypeDef>();
|
||||||
Dictionary<IType, TValue> refToValue = new Dictionary<IType, TValue>(TypeEqualityComparer.Instance);
|
Dictionary<IType, TValue> refToValue = new Dictionary<IType, TValue>(TypeEqualityComparer.Instance);
|
||||||
|
@ -101,11 +101,11 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class FieldDefinitionDictBase<TValue> {
|
public abstract class FieldDefDictBase<TValue> {
|
||||||
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
|
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
|
||||||
Dictionary<ScopeAndTokenKey, FieldDef> tokenToKey = new Dictionary<ScopeAndTokenKey, FieldDef>();
|
Dictionary<ScopeAndTokenKey, FieldDef> tokenToKey = new Dictionary<ScopeAndTokenKey, FieldDef>();
|
||||||
Dictionary<IFieldReferenceKey, TValue> refToValue = new Dictionary<IFieldReferenceKey, TValue>();
|
Dictionary<IFieldRefKey, TValue> refToValue = new Dictionary<IFieldRefKey, TValue>();
|
||||||
Dictionary<IFieldReferenceKey, FieldDef> refToKey = new Dictionary<IFieldReferenceKey, FieldDef>();
|
Dictionary<IFieldRefKey, FieldDef> refToKey = new Dictionary<IFieldRefKey, FieldDef>();
|
||||||
|
|
||||||
public int Count {
|
public int Count {
|
||||||
get { return tokenToValue.Count; }
|
get { return tokenToValue.Count; }
|
||||||
|
@ -123,7 +123,7 @@ namespace de4dot.blocks {
|
||||||
return new ScopeAndTokenKey(fieldDef);
|
return new ScopeAndTokenKey(fieldDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract IFieldReferenceKey getReferenceKey(IField fieldRef);
|
internal abstract IFieldRefKey getRefKey(IField fieldRef);
|
||||||
|
|
||||||
public TValue find(IField fieldRef) {
|
public TValue find(IField fieldRef) {
|
||||||
TValue value;
|
TValue value;
|
||||||
|
@ -131,7 +131,7 @@ namespace de4dot.blocks {
|
||||||
if (fieldDef != null)
|
if (fieldDef != null)
|
||||||
tokenToValue.TryGetValue(getTokenKey(fieldDef), out value);
|
tokenToValue.TryGetValue(getTokenKey(fieldDef), out value);
|
||||||
else
|
else
|
||||||
refToValue.TryGetValue(getReferenceKey(fieldRef), out value);
|
refToValue.TryGetValue(getRefKey(fieldRef), out value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ namespace de4dot.blocks {
|
||||||
if (fieldDef != null && tokenToValue.TryGetValue(getTokenKey(fieldDef), out value))
|
if (fieldDef != null && tokenToValue.TryGetValue(getTokenKey(fieldDef), out value))
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
refToValue.TryGetValue(getReferenceKey(fieldRef), out value);
|
refToValue.TryGetValue(getRefKey(fieldRef), out value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ namespace de4dot.blocks {
|
||||||
tokenToValue[tokenKey] = value;
|
tokenToValue[tokenKey] = value;
|
||||||
tokenToKey[tokenKey] = fieldDef;
|
tokenToKey[tokenKey] = fieldDef;
|
||||||
|
|
||||||
var refKey = getReferenceKey(fieldDef);
|
var refKey = getRefKey(fieldDef);
|
||||||
if (!refToValue.ContainsKey(refKey) ||
|
if (!refToValue.ContainsKey(refKey) ||
|
||||||
getAccessibilityOrder(fieldDef) < getAccessibilityOrder(refToKey[refKey])) {
|
getAccessibilityOrder(fieldDef) < getAccessibilityOrder(refToKey[refKey])) {
|
||||||
refToKey[refKey] = fieldDef;
|
refToKey[refKey] = fieldDef;
|
||||||
|
@ -169,35 +169,35 @@ namespace de4dot.blocks {
|
||||||
0, // Public
|
0, // Public
|
||||||
70, // <reserved>
|
70, // <reserved>
|
||||||
};
|
};
|
||||||
static int getAccessibilityOrder(FieldDef fieldDefinition) {
|
static int getAccessibilityOrder(FieldDef fieldDef) {
|
||||||
return accessibilityOrder[(int)fieldDefinition.Attributes & 7];
|
return accessibilityOrder[(int)fieldDef.Attributes & 7];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onTypesRenamed() {
|
public void onTypesRenamed() {
|
||||||
var newFieldRefToDef = new Dictionary<IFieldReferenceKey, TValue>(refToValue.Count);
|
var newFieldRefToDef = new Dictionary<IFieldRefKey, TValue>(refToValue.Count);
|
||||||
foreach (var kvp in refToValue)
|
foreach (var kvp in refToValue)
|
||||||
newFieldRefToDef[getReferenceKey((FieldDef)kvp.Key.FieldReference)] = kvp.Value;
|
newFieldRefToDef[getRefKey((FieldDef)kvp.Key.FieldRef)] = kvp.Value;
|
||||||
refToValue = newFieldRefToDef;
|
refToValue = newFieldRefToDef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FieldDefinitionDict<TValue> : FieldDefinitionDictBase<TValue> {
|
public class FieldDefDict<TValue> : FieldDefDictBase<TValue> {
|
||||||
internal override IFieldReferenceKey getReferenceKey(IField fieldRef) {
|
internal override IFieldRefKey getRefKey(IField fieldRef) {
|
||||||
return new FieldReferenceKey(fieldRef);
|
return new FieldRefKey(fieldRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FieldDefinitionAndDeclaringTypeDict<TValue> : FieldDefinitionDictBase<TValue> {
|
public class FieldDefAndDeclaringTypeDict<TValue> : FieldDefDictBase<TValue> {
|
||||||
internal override IFieldReferenceKey getReferenceKey(IField fieldRef) {
|
internal override IFieldRefKey getRefKey(IField fieldRef) {
|
||||||
return new FieldReferenceAndDeclaringTypeKey(fieldRef);
|
return new FieldRefAndDeclaringTypeKey(fieldRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class MethodDefinitionDictBase<TValue> {
|
public abstract class MethodDefDictBase<TValue> {
|
||||||
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
|
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
|
||||||
Dictionary<ScopeAndTokenKey, MethodDef> tokenToKey = new Dictionary<ScopeAndTokenKey, MethodDef>();
|
Dictionary<ScopeAndTokenKey, MethodDef> tokenToKey = new Dictionary<ScopeAndTokenKey, MethodDef>();
|
||||||
Dictionary<IMethodReferenceKey, TValue> refToValue = new Dictionary<IMethodReferenceKey, TValue>();
|
Dictionary<IMethodRefKey, TValue> refToValue = new Dictionary<IMethodRefKey, TValue>();
|
||||||
Dictionary<IMethodReferenceKey, MethodDef> refToKey = new Dictionary<IMethodReferenceKey, MethodDef>();
|
Dictionary<IMethodRefKey, MethodDef> refToKey = new Dictionary<IMethodRefKey, MethodDef>();
|
||||||
|
|
||||||
public int Count {
|
public int Count {
|
||||||
get { return tokenToValue.Count; }
|
get { return tokenToValue.Count; }
|
||||||
|
@ -215,7 +215,7 @@ namespace de4dot.blocks {
|
||||||
return new ScopeAndTokenKey(methodDef);
|
return new ScopeAndTokenKey(methodDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract IMethodReferenceKey getReferenceKey(IMethod methodRef);
|
internal abstract IMethodRefKey getRefKey(IMethod methodRef);
|
||||||
|
|
||||||
public TValue find(IMethod methodRef) {
|
public TValue find(IMethod methodRef) {
|
||||||
TValue value;
|
TValue value;
|
||||||
|
@ -223,7 +223,7 @@ namespace de4dot.blocks {
|
||||||
if (methodDef != null)
|
if (methodDef != null)
|
||||||
tokenToValue.TryGetValue(getTokenKey(methodDef), out value);
|
tokenToValue.TryGetValue(getTokenKey(methodDef), out value);
|
||||||
else
|
else
|
||||||
refToValue.TryGetValue(getReferenceKey(methodRef), out value);
|
refToValue.TryGetValue(getRefKey(methodRef), out value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ namespace de4dot.blocks {
|
||||||
if (methodDef != null && tokenToValue.TryGetValue(getTokenKey(methodDef), out value))
|
if (methodDef != null && tokenToValue.TryGetValue(getTokenKey(methodDef), out value))
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
refToValue.TryGetValue(getReferenceKey(methodRef), out value);
|
refToValue.TryGetValue(getRefKey(methodRef), out value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ namespace de4dot.blocks {
|
||||||
tokenToValue[tokenKey] = value;
|
tokenToValue[tokenKey] = value;
|
||||||
tokenToKey[tokenKey] = methodDef;
|
tokenToKey[tokenKey] = methodDef;
|
||||||
|
|
||||||
var refKey = getReferenceKey(methodDef);
|
var refKey = getRefKey(methodDef);
|
||||||
if (!refToValue.ContainsKey(refKey) ||
|
if (!refToValue.ContainsKey(refKey) ||
|
||||||
getAccessibilityOrder(methodDef) < getAccessibilityOrder(refToKey[refKey])) {
|
getAccessibilityOrder(methodDef) < getAccessibilityOrder(refToKey[refKey])) {
|
||||||
refToKey[refKey] = methodDef;
|
refToKey[refKey] = methodDef;
|
||||||
|
@ -261,34 +261,34 @@ namespace de4dot.blocks {
|
||||||
0, // Public
|
0, // Public
|
||||||
70, // <reserved>
|
70, // <reserved>
|
||||||
};
|
};
|
||||||
static int getAccessibilityOrder(MethodDef methodDefinition) {
|
static int getAccessibilityOrder(MethodDef methodDef) {
|
||||||
return accessibilityOrder[(int)methodDefinition.Attributes & 7];
|
return accessibilityOrder[(int)methodDef.Attributes & 7];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onTypesRenamed() {
|
public void onTypesRenamed() {
|
||||||
var newFieldRefToDef = new Dictionary<IMethodReferenceKey, TValue>(refToValue.Count);
|
var newFieldRefToDef = new Dictionary<IMethodRefKey, TValue>(refToValue.Count);
|
||||||
foreach (var kvp in refToValue)
|
foreach (var kvp in refToValue)
|
||||||
newFieldRefToDef[getReferenceKey((MethodDef)kvp.Key.MethodReference)] = kvp.Value;
|
newFieldRefToDef[getRefKey((MethodDef)kvp.Key.MethodRef)] = kvp.Value;
|
||||||
refToValue = newFieldRefToDef;
|
refToValue = newFieldRefToDef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MethodDefinitionDict<TValue> : MethodDefinitionDictBase<TValue> {
|
public class MethodDefDict<TValue> : MethodDefDictBase<TValue> {
|
||||||
internal override IMethodReferenceKey getReferenceKey(IMethod methodRef) {
|
internal override IMethodRefKey getRefKey(IMethod methodRef) {
|
||||||
return new MethodReferenceKey(methodRef);
|
return new MethodRefKey(methodRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MethodDefinitionAndDeclaringTypeDict<TValue> : MethodDefinitionDictBase<TValue> {
|
public class MethodDefAndDeclaringTypeDict<TValue> : MethodDefDictBase<TValue> {
|
||||||
internal override IMethodReferenceKey getReferenceKey(IMethod methodRef) {
|
internal override IMethodRefKey getRefKey(IMethod methodRef) {
|
||||||
return new MethodReferenceAndDeclaringTypeKey(methodRef);
|
return new MethodRefAndDeclaringTypeKey(methodRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class EventDefinitionDictBase<TValue> {
|
public abstract class EventDefDictBase<TValue> {
|
||||||
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
|
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
|
||||||
Dictionary<ScopeAndTokenKey, EventDef> tokenToKey = new Dictionary<ScopeAndTokenKey, EventDef>();
|
Dictionary<ScopeAndTokenKey, EventDef> tokenToKey = new Dictionary<ScopeAndTokenKey, EventDef>();
|
||||||
Dictionary<IEventReferenceKey, TValue> refToValue = new Dictionary<IEventReferenceKey, TValue>();
|
Dictionary<IEventRefKey, TValue> refToValue = new Dictionary<IEventRefKey, TValue>();
|
||||||
|
|
||||||
public int Count {
|
public int Count {
|
||||||
get { return tokenToValue.Count; }
|
get { return tokenToValue.Count; }
|
||||||
|
@ -302,11 +302,11 @@ namespace de4dot.blocks {
|
||||||
return tokenToValue.Values;
|
return tokenToValue.Values;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopeAndTokenKey getTokenKey(EventDef eventReference) {
|
ScopeAndTokenKey getTokenKey(EventDef eventRef) {
|
||||||
return new ScopeAndTokenKey(eventReference);
|
return new ScopeAndTokenKey(eventRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract IEventReferenceKey getReferenceKey(EventDef eventRef);
|
internal abstract IEventRefKey getRefKey(EventDef eventRef);
|
||||||
|
|
||||||
public TValue find(EventDef eventRef) {
|
public TValue find(EventDef eventRef) {
|
||||||
TValue value;
|
TValue value;
|
||||||
|
@ -319,7 +319,7 @@ namespace de4dot.blocks {
|
||||||
if (tokenToValue.TryGetValue(getTokenKey(eventRef), out value))
|
if (tokenToValue.TryGetValue(getTokenKey(eventRef), out value))
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
refToValue.TryGetValue(getReferenceKey(eventRef), out value);
|
refToValue.TryGetValue(getRefKey(eventRef), out value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,33 +328,33 @@ namespace de4dot.blocks {
|
||||||
tokenToValue[tokenKey] = value;
|
tokenToValue[tokenKey] = value;
|
||||||
tokenToKey[tokenKey] = eventDef;
|
tokenToKey[tokenKey] = eventDef;
|
||||||
|
|
||||||
refToValue[getReferenceKey(eventDef)] = value;
|
refToValue[getRefKey(eventDef)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onTypesRenamed() {
|
public void onTypesRenamed() {
|
||||||
var newFieldRefToDef = new Dictionary<IEventReferenceKey, TValue>(refToValue.Count);
|
var newFieldRefToDef = new Dictionary<IEventRefKey, TValue>(refToValue.Count);
|
||||||
foreach (var kvp in refToValue)
|
foreach (var kvp in refToValue)
|
||||||
newFieldRefToDef[getReferenceKey((EventDef)kvp.Key.EventDef)] = kvp.Value;
|
newFieldRefToDef[getRefKey((EventDef)kvp.Key.EventDef)] = kvp.Value;
|
||||||
refToValue = newFieldRefToDef;
|
refToValue = newFieldRefToDef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EventDefinitionDict<TValue> : EventDefinitionDictBase<TValue> {
|
public class EventDefDict<TValue> : EventDefDictBase<TValue> {
|
||||||
internal override IEventReferenceKey getReferenceKey(EventDef eventRef) {
|
internal override IEventRefKey getRefKey(EventDef eventRef) {
|
||||||
return new EventReferenceKey(eventRef);
|
return new EventRefKey(eventRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class EventDefinitionAndDeclaringTypeDict<TValue> : EventDefinitionDictBase<TValue> {
|
public class EventDefAndDeclaringTypeDict<TValue> : EventDefDictBase<TValue> {
|
||||||
internal override IEventReferenceKey getReferenceKey(EventDef eventRef) {
|
internal override IEventRefKey getRefKey(EventDef eventRef) {
|
||||||
return new EventReferenceAndDeclaringTypeKey(eventRef);
|
return new EventRefAndDeclaringTypeKey(eventRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class PropertyDefinitionDictBase<TValue> {
|
public abstract class PropertyDefDictBase<TValue> {
|
||||||
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
|
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
|
||||||
Dictionary<ScopeAndTokenKey, PropertyDef> tokenToKey = new Dictionary<ScopeAndTokenKey, PropertyDef>();
|
Dictionary<ScopeAndTokenKey, PropertyDef> tokenToKey = new Dictionary<ScopeAndTokenKey, PropertyDef>();
|
||||||
Dictionary<IPropertyReferenceKey, TValue> refToValue = new Dictionary<IPropertyReferenceKey, TValue>();
|
Dictionary<IPropertyRefKey, TValue> refToValue = new Dictionary<IPropertyRefKey, TValue>();
|
||||||
|
|
||||||
public int Count {
|
public int Count {
|
||||||
get { return tokenToValue.Count; }
|
get { return tokenToValue.Count; }
|
||||||
|
@ -368,11 +368,11 @@ namespace de4dot.blocks {
|
||||||
return tokenToValue.Values;
|
return tokenToValue.Values;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopeAndTokenKey getTokenKey(PropertyDef propertyReference) {
|
ScopeAndTokenKey getTokenKey(PropertyDef propertyRef) {
|
||||||
return new ScopeAndTokenKey(propertyReference);
|
return new ScopeAndTokenKey(propertyRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract IPropertyReferenceKey getReferenceKey(PropertyDef propertyReference);
|
internal abstract IPropertyRefKey getRefKey(PropertyDef propertyRef);
|
||||||
|
|
||||||
public TValue find(PropertyDef propRef) {
|
public TValue find(PropertyDef propRef) {
|
||||||
TValue value;
|
TValue value;
|
||||||
|
@ -385,7 +385,7 @@ namespace de4dot.blocks {
|
||||||
if (tokenToValue.TryGetValue(getTokenKey(propRef), out value))
|
if (tokenToValue.TryGetValue(getTokenKey(propRef), out value))
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
refToValue.TryGetValue(getReferenceKey(propRef), out value);
|
refToValue.TryGetValue(getRefKey(propRef), out value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,26 +394,26 @@ namespace de4dot.blocks {
|
||||||
tokenToValue[tokenKey] = value;
|
tokenToValue[tokenKey] = value;
|
||||||
tokenToKey[tokenKey] = propDef;
|
tokenToKey[tokenKey] = propDef;
|
||||||
|
|
||||||
refToValue[getReferenceKey(propDef)] = value;
|
refToValue[getRefKey(propDef)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onTypesRenamed() {
|
public void onTypesRenamed() {
|
||||||
var newFieldRefToDef = new Dictionary<IPropertyReferenceKey, TValue>(refToValue.Count);
|
var newFieldRefToDef = new Dictionary<IPropertyRefKey, TValue>(refToValue.Count);
|
||||||
foreach (var kvp in refToValue)
|
foreach (var kvp in refToValue)
|
||||||
newFieldRefToDef[getReferenceKey((PropertyDef)kvp.Key.PropertyDef)] = kvp.Value;
|
newFieldRefToDef[getRefKey((PropertyDef)kvp.Key.PropertyDef)] = kvp.Value;
|
||||||
refToValue = newFieldRefToDef;
|
refToValue = newFieldRefToDef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropertyDefinitionDict<TValue> : PropertyDefinitionDictBase<TValue> {
|
public class PropertyDefDict<TValue> : PropertyDefDictBase<TValue> {
|
||||||
internal override IPropertyReferenceKey getReferenceKey(PropertyDef propRef) {
|
internal override IPropertyRefKey getRefKey(PropertyDef propRef) {
|
||||||
return new PropertyReferenceKey(propRef);
|
return new PropertyRefKey(propRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PropertyDefinitionAndDeclaringTypeDict<TValue> : PropertyDefinitionDictBase<TValue> {
|
public class PropertyDefAndDeclaringTypeDict<TValue> : PropertyDefDictBase<TValue> {
|
||||||
internal override IPropertyReferenceKey getReferenceKey(PropertyDef propRef) {
|
internal override IPropertyRefKey getRefKey(PropertyDef propRef) {
|
||||||
return new PropertyReferenceAndDeclaringTypeKey(propRef);
|
return new PropertyRefAndDeclaringTypeKey(propRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,30 +502,30 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IFieldReferenceKey {
|
interface IFieldRefKey {
|
||||||
IField FieldReference { get; }
|
IField FieldRef { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMethodReferenceKey {
|
interface IMethodRefKey {
|
||||||
IMethod MethodReference { get; }
|
IMethod MethodRef { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IEventReferenceKey {
|
interface IEventRefKey {
|
||||||
EventDef EventDef { get; }
|
EventDef EventDef { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IPropertyReferenceKey {
|
interface IPropertyRefKey {
|
||||||
PropertyDef PropertyDef { get; }
|
PropertyDef PropertyDef { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class FieldReferenceKey : IFieldReferenceKey {
|
sealed class FieldRefKey : IFieldRefKey {
|
||||||
readonly IField fieldRef;
|
readonly IField fieldRef;
|
||||||
|
|
||||||
public IField FieldReference {
|
public IField FieldRef {
|
||||||
get { return fieldRef; }
|
get { return fieldRef; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldReferenceKey(IField fieldRef) {
|
public FieldRefKey(IField fieldRef) {
|
||||||
this.fieldRef = fieldRef;
|
this.fieldRef = fieldRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +534,7 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object obj) {
|
||||||
var other = obj as FieldReferenceKey;
|
var other = obj as FieldRefKey;
|
||||||
if (other == null)
|
if (other == null)
|
||||||
return false;
|
return false;
|
||||||
return new SigComparer().Equals(fieldRef, other.fieldRef);
|
return new SigComparer().Equals(fieldRef, other.fieldRef);
|
||||||
|
@ -545,14 +545,14 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class MethodReferenceKey : IMethodReferenceKey {
|
sealed class MethodRefKey : IMethodRefKey {
|
||||||
readonly IMethod methodRef;
|
readonly IMethod methodRef;
|
||||||
|
|
||||||
public IMethod MethodReference {
|
public IMethod MethodRef {
|
||||||
get { return methodRef; }
|
get { return methodRef; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReferenceKey(IMethod methodRef) {
|
public MethodRefKey(IMethod methodRef) {
|
||||||
this.methodRef = methodRef;
|
this.methodRef = methodRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,7 +561,7 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object obj) {
|
||||||
var other = obj as MethodReferenceKey;
|
var other = obj as MethodRefKey;
|
||||||
if (other == null)
|
if (other == null)
|
||||||
return false;
|
return false;
|
||||||
return new SigComparer().Equals(methodRef, other.methodRef);
|
return new SigComparer().Equals(methodRef, other.methodRef);
|
||||||
|
@ -572,14 +572,14 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class FieldReferenceAndDeclaringTypeKey : IFieldReferenceKey {
|
sealed class FieldRefAndDeclaringTypeKey : IFieldRefKey {
|
||||||
readonly IField fieldRef;
|
readonly IField fieldRef;
|
||||||
|
|
||||||
public IField FieldReference {
|
public IField FieldRef {
|
||||||
get { return fieldRef; }
|
get { return fieldRef; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldReferenceAndDeclaringTypeKey(IField fieldRef) {
|
public FieldRefAndDeclaringTypeKey(IField fieldRef) {
|
||||||
this.fieldRef = fieldRef;
|
this.fieldRef = fieldRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,7 +588,7 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object obj) {
|
||||||
var other = obj as FieldReferenceAndDeclaringTypeKey;
|
var other = obj as FieldRefAndDeclaringTypeKey;
|
||||||
if (other == null)
|
if (other == null)
|
||||||
return false;
|
return false;
|
||||||
return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).Equals(fieldRef, other.fieldRef);
|
return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).Equals(fieldRef, other.fieldRef);
|
||||||
|
@ -599,14 +599,14 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class MethodReferenceAndDeclaringTypeKey : IMethodReferenceKey {
|
sealed class MethodRefAndDeclaringTypeKey : IMethodRefKey {
|
||||||
readonly IMethod methodRef;
|
readonly IMethod methodRef;
|
||||||
|
|
||||||
public IMethod MethodReference {
|
public IMethod MethodRef {
|
||||||
get { return methodRef; }
|
get { return methodRef; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReferenceAndDeclaringTypeKey(IMethod methodRef) {
|
public MethodRefAndDeclaringTypeKey(IMethod methodRef) {
|
||||||
this.methodRef = methodRef;
|
this.methodRef = methodRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,7 +615,7 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object obj) {
|
||||||
var other = obj as MethodReferenceAndDeclaringTypeKey;
|
var other = obj as MethodRefAndDeclaringTypeKey;
|
||||||
if (other == null)
|
if (other == null)
|
||||||
return false;
|
return false;
|
||||||
return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).Equals(methodRef, other.methodRef);
|
return new SigComparer(SigComparerOptions.CompareMethodFieldDeclaringType).Equals(methodRef, other.methodRef);
|
||||||
|
@ -626,14 +626,14 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class EventReferenceKey : IEventReferenceKey {
|
sealed class EventRefKey : IEventRefKey {
|
||||||
readonly EventDef eventRef;
|
readonly EventDef eventRef;
|
||||||
|
|
||||||
public EventDef EventDef {
|
public EventDef EventDef {
|
||||||
get { return eventRef; }
|
get { return eventRef; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventReferenceKey(EventDef eventRef) {
|
public EventRefKey(EventDef eventRef) {
|
||||||
this.eventRef = eventRef;
|
this.eventRef = eventRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +642,7 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object obj) {
|
||||||
var other = obj as EventReferenceKey;
|
var other = obj as EventRefKey;
|
||||||
if (other == null)
|
if (other == null)
|
||||||
return false;
|
return false;
|
||||||
return new SigComparer().Equals(eventRef, other.eventRef);
|
return new SigComparer().Equals(eventRef, other.eventRef);
|
||||||
|
@ -653,14 +653,14 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class EventReferenceAndDeclaringTypeKey : IEventReferenceKey {
|
sealed class EventRefAndDeclaringTypeKey : IEventRefKey {
|
||||||
readonly EventDef eventRef;
|
readonly EventDef eventRef;
|
||||||
|
|
||||||
public EventDef EventDef {
|
public EventDef EventDef {
|
||||||
get { return eventRef; }
|
get { return eventRef; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventReferenceAndDeclaringTypeKey(EventDef eventRef) {
|
public EventRefAndDeclaringTypeKey(EventDef eventRef) {
|
||||||
this.eventRef = eventRef;
|
this.eventRef = eventRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,7 +669,7 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object obj) {
|
||||||
var other = obj as EventReferenceAndDeclaringTypeKey;
|
var other = obj as EventRefAndDeclaringTypeKey;
|
||||||
if (other == null)
|
if (other == null)
|
||||||
return false;
|
return false;
|
||||||
return new SigComparer(SigComparerOptions.CompareEventDeclaringType).Equals(eventRef, other.eventRef);
|
return new SigComparer(SigComparerOptions.CompareEventDeclaringType).Equals(eventRef, other.eventRef);
|
||||||
|
@ -680,14 +680,14 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class PropertyReferenceKey : IPropertyReferenceKey {
|
sealed class PropertyRefKey : IPropertyRefKey {
|
||||||
readonly PropertyDef propRef;
|
readonly PropertyDef propRef;
|
||||||
|
|
||||||
public PropertyDef PropertyDef {
|
public PropertyDef PropertyDef {
|
||||||
get { return propRef; }
|
get { return propRef; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyReferenceKey(PropertyDef propRef) {
|
public PropertyRefKey(PropertyDef propRef) {
|
||||||
this.propRef = propRef;
|
this.propRef = propRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,7 +696,7 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object obj) {
|
||||||
var other = obj as PropertyReferenceKey;
|
var other = obj as PropertyRefKey;
|
||||||
if (other == null)
|
if (other == null)
|
||||||
return false;
|
return false;
|
||||||
return new SigComparer().Equals(propRef, other.propRef);
|
return new SigComparer().Equals(propRef, other.propRef);
|
||||||
|
@ -707,14 +707,14 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class PropertyReferenceAndDeclaringTypeKey : IPropertyReferenceKey {
|
sealed class PropertyRefAndDeclaringTypeKey : IPropertyRefKey {
|
||||||
readonly PropertyDef propRef;
|
readonly PropertyDef propRef;
|
||||||
|
|
||||||
public PropertyDef PropertyDef {
|
public PropertyDef PropertyDef {
|
||||||
get { return propRef; }
|
get { return propRef; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyReferenceAndDeclaringTypeKey(PropertyDef propRef) {
|
public PropertyRefAndDeclaringTypeKey(PropertyDef propRef) {
|
||||||
this.propRef = propRef;
|
this.propRef = propRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,7 +723,7 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj) {
|
public override bool Equals(object obj) {
|
||||||
var other = obj as PropertyReferenceAndDeclaringTypeKey;
|
var other = obj as PropertyRefAndDeclaringTypeKey;
|
||||||
if (other == null)
|
if (other == null)
|
||||||
return false;
|
return false;
|
||||||
return new SigComparer(SigComparerOptions.ComparePropertyDeclaringType).Equals(propRef, other.propRef);
|
return new SigComparer(SigComparerOptions.ComparePropertyDeclaringType).Equals(propRef, other.propRef);
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
/*
|
|
||||||
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.IO;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
public class Cor20Header : IFileLocation {
|
|
||||||
public uint cb;
|
|
||||||
public ushort majorRuntimeVersion;
|
|
||||||
public ushort minorRuntimeVersion;
|
|
||||||
public DataDirectory metadataDirectory;
|
|
||||||
public uint flags;
|
|
||||||
public uint entryPointToken;
|
|
||||||
public DataDirectory resources;
|
|
||||||
public DataDirectory strongNameSignature;
|
|
||||||
public DataDirectory codeManagerTable;
|
|
||||||
public DataDirectory vtableFixups;
|
|
||||||
public DataDirectory exportAddressTableJumps;
|
|
||||||
public DataDirectory managedNativeHeader;
|
|
||||||
public Metadata metadata;
|
|
||||||
BinaryReader reader;
|
|
||||||
|
|
||||||
public uint MetadataOffset {
|
|
||||||
get { return metadata.Offset; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint MetadataHeaderLength {
|
|
||||||
get { return metadata.HeaderLength; }
|
|
||||||
}
|
|
||||||
|
|
||||||
uint offset;
|
|
||||||
public uint Offset {
|
|
||||||
get { return offset; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Length {
|
|
||||||
get { return 18 * 4; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cor20Header(BinaryReader reader) {
|
|
||||||
this.reader = reader;
|
|
||||||
offset = (uint)reader.BaseStream.Position;
|
|
||||||
cb = reader.ReadUInt32();
|
|
||||||
majorRuntimeVersion = reader.ReadUInt16();
|
|
||||||
minorRuntimeVersion = reader.ReadUInt16();
|
|
||||||
metadataDirectory.read(reader);
|
|
||||||
flags = reader.ReadUInt32();
|
|
||||||
entryPointToken = reader.ReadUInt32();
|
|
||||||
resources.read(reader);
|
|
||||||
strongNameSignature.read(reader);
|
|
||||||
codeManagerTable.read(reader);
|
|
||||||
vtableFixups.read(reader);
|
|
||||||
exportAddressTableJumps.read(reader);
|
|
||||||
managedNativeHeader.read(reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void initMetadataTable() {
|
|
||||||
metadata = new Metadata(reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MetadataTables createMetadataTables() {
|
|
||||||
return new MetadataTables(reader, metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
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.IO;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
public enum Machine : ushort {
|
|
||||||
i386 = 0x14C,
|
|
||||||
ia64 = 0x200,
|
|
||||||
amd64 = 0x8664,
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FileHeader : IFileLocation {
|
|
||||||
public Machine machine;
|
|
||||||
public ushort numberOfSections;
|
|
||||||
public uint timeDateStamp;
|
|
||||||
public uint pointerToSymbolTable;
|
|
||||||
public uint numberOfSymbols;
|
|
||||||
public ushort sizeOfOptionalHeader;
|
|
||||||
public ushort characteristics;
|
|
||||||
|
|
||||||
uint offset;
|
|
||||||
public uint Offset {
|
|
||||||
get { return offset; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Length {
|
|
||||||
get { return 5 * 4; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileHeader(BinaryReader reader) {
|
|
||||||
offset = (uint)reader.BaseStream.Position;
|
|
||||||
machine = (Machine)reader.ReadUInt16();
|
|
||||||
numberOfSections = reader.ReadUInt16();
|
|
||||||
timeDateStamp = reader.ReadUInt32();
|
|
||||||
pointerToSymbolTable = reader.ReadUInt32();
|
|
||||||
numberOfSymbols = reader.ReadUInt32();
|
|
||||||
sizeOfOptionalHeader = reader.ReadUInt16();
|
|
||||||
characteristics = reader.ReadUInt16();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,114 +0,0 @@
|
||||||
/*
|
|
||||||
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.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
public class Metadata : IFileLocation {
|
|
||||||
uint magic;
|
|
||||||
ushort majorVersion, minorVersion;
|
|
||||||
uint reserved;
|
|
||||||
string versionString;
|
|
||||||
ushort flags;
|
|
||||||
DotNetStream[] streams;
|
|
||||||
|
|
||||||
uint offset, headerLength, length;
|
|
||||||
|
|
||||||
public DotNetStream[] Streams {
|
|
||||||
get { return streams; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Offset {
|
|
||||||
get { return offset; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Length {
|
|
||||||
get { return length; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint HeaderLength {
|
|
||||||
get { return headerLength; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint HeaderEnd {
|
|
||||||
get { return offset + headerLength; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Metadata(BinaryReader reader) {
|
|
||||||
magic = reader.ReadUInt32();
|
|
||||||
if (magic != 0x424A5342)
|
|
||||||
return;
|
|
||||||
|
|
||||||
offset = (uint)reader.BaseStream.Position - 4;
|
|
||||||
majorVersion = reader.ReadUInt16();
|
|
||||||
minorVersion = reader.ReadUInt16();
|
|
||||||
reserved = reader.ReadUInt32();
|
|
||||||
versionString = readString(reader, reader.ReadInt32());
|
|
||||||
flags = reader.ReadUInt16();
|
|
||||||
int numStreams = reader.ReadUInt16();
|
|
||||||
streams = new DotNetStream[numStreams];
|
|
||||||
uint lastOffset = offset;
|
|
||||||
for (int i = 0; i < numStreams; i++) {
|
|
||||||
uint fileOffset = offset + reader.ReadUInt32();
|
|
||||||
uint size = reader.ReadUInt32();
|
|
||||||
string name = readAsciizString(reader);
|
|
||||||
streams[i] = new DotNetStream(name, fileOffset, size);
|
|
||||||
lastOffset = Math.Max(lastOffset, fileOffset + size);
|
|
||||||
}
|
|
||||||
lastOffset = Math.Max(lastOffset, (uint)reader.BaseStream.Position);
|
|
||||||
length = lastOffset - offset;
|
|
||||||
headerLength = (uint)reader.BaseStream.Position - offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DotNetStream getStream(string name) {
|
|
||||||
foreach (var stream in streams) {
|
|
||||||
if (stream.name == name)
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
string readString(BinaryReader reader, int len) {
|
|
||||||
var sb = new StringBuilder(len);
|
|
||||||
var nextPos = reader.BaseStream.Position + len;
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
byte b = reader.ReadByte();
|
|
||||||
if (b == 0)
|
|
||||||
break;
|
|
||||||
sb.Append((char)b);
|
|
||||||
}
|
|
||||||
reader.BaseStream.Position = nextPos;
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
string readAsciizString(BinaryReader reader) {
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
while (true) {
|
|
||||||
byte b = reader.ReadByte();
|
|
||||||
if (b == 0)
|
|
||||||
break;
|
|
||||||
sb.Append((char)b);
|
|
||||||
}
|
|
||||||
reader.BaseStream.Position = (reader.BaseStream.Position + 3) & ~3;
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,152 +0,0 @@
|
||||||
/*
|
|
||||||
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.IO;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
using MVT = MetadataVarType;
|
|
||||||
|
|
||||||
public class MetadataTables {
|
|
||||||
BinaryReader reader;
|
|
||||||
Metadata metadata;
|
|
||||||
byte heapOffsetSizes;
|
|
||||||
MetadataType[] metadataTypes = new MetadataType[64];
|
|
||||||
|
|
||||||
public MetadataTables(BinaryReader reader, Metadata metadata) {
|
|
||||||
this.reader = reader;
|
|
||||||
this.metadata = metadata;
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MetadataType getMetadataType(MetadataIndex index) {
|
|
||||||
return metadataTypes[(int)index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void seek(uint fileOffset) {
|
|
||||||
reader.BaseStream.Position = fileOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This table needs to be updated to support the other metadata tables.
|
|
||||||
static MetadataVarType[] metadataVarType = new MetadataVarType[] {
|
|
||||||
MVT.byte2, MVT.stringIndex, MVT.guidIndex, MVT.guidIndex, MVT.guidIndex, MVT.end, // 0
|
|
||||||
MVT.resolutionScope, MVT.stringIndex, MVT.stringIndex, MVT.end, // 1
|
|
||||||
MVT.byte4, MVT.stringIndex, MVT.stringIndex, MVT.typeDefOrRef, MVT.fieldIndex, MVT.methodDefIndex, MVT.end, // 2
|
|
||||||
MVT.end, // 3
|
|
||||||
MVT.byte2, MVT.stringIndex, MVT.blobIndex, MVT.end, // 4
|
|
||||||
MVT.methodDefIndex, MVT.end, // 5
|
|
||||||
MVT.byte4, MVT.byte2, MVT.byte2, MVT.stringIndex, MVT.blobIndex, MVT.paramIndex, MVT.end, // 6
|
|
||||||
MVT.end, // 7
|
|
||||||
MVT.byte2, MVT.byte2, MVT.stringIndex, MVT.end, // 8
|
|
||||||
MVT.typeDefIndex, MVT.typeDefOrRef, MVT.end, // 9
|
|
||||||
MVT.memberRefParent, MVT.stringIndex, MVT.blobIndex, MVT.end, // 10
|
|
||||||
MVT.byte1, MVT.byte1, MVT.hasConstant, MVT.blobIndex, MVT.end, // 11
|
|
||||||
MVT.hasCustomAttribute, MVT.customAttributeType, MVT.blobIndex, MVT.end,// 12
|
|
||||||
MVT.hasFieldMarshal, MVT.blobIndex, MVT.end, // 13
|
|
||||||
MVT.byte2, MVT.hasDeclSecurity, MVT.blobIndex, MVT.end, // 14
|
|
||||||
MVT.byte2, MVT.byte4, MVT.typeDefIndex, MVT.end, // 15
|
|
||||||
MVT.byte4, MVT.fieldIndex, MVT.end, // 16
|
|
||||||
MVT.blobIndex, MVT.end, // 17
|
|
||||||
MVT.typeDefIndex, MVT.eventIndex, MVT.end, // 18
|
|
||||||
MVT.end, // 19
|
|
||||||
MVT.byte2, MVT.stringIndex, MVT.typeDefOrRef, MVT.end, // 20
|
|
||||||
MVT.typeDefIndex, MVT.propertyIndex, MVT.end, // 21
|
|
||||||
MVT.end, // 22
|
|
||||||
MVT.byte2, MVT.stringIndex, MVT.blobIndex, MVT.end, // 23
|
|
||||||
MVT.byte2, MVT.methodDefIndex, MVT.hasSemantics, MVT.end, // 24
|
|
||||||
MVT.typeDefIndex, MVT.methodDefOrRef, MVT.methodDefOrRef, MVT.end, // 25
|
|
||||||
MVT.stringIndex, MVT.end, // 26
|
|
||||||
MVT.blobIndex, MVT.end, // 27
|
|
||||||
MVT.byte2, MVT.memberForwarded, MVT.stringIndex, MVT.moduleRefIndex, MVT.end, // 28
|
|
||||||
MVT.byte4, MVT.fieldIndex, MVT.end, // 29
|
|
||||||
MVT.end, // 30
|
|
||||||
MVT.end, // 31
|
|
||||||
MVT.byte4, MVT.byte2, MVT.byte2, MVT.byte2, MVT.byte2, MVT.byte4, MVT.blobIndex, MVT.stringIndex, MVT.stringIndex, MVT.end, // 32
|
|
||||||
MVT.byte4, MVT.end, // 33
|
|
||||||
MVT.byte4, MVT.byte4, MVT.byte4, MVT.end, // 34
|
|
||||||
MVT.byte2, MVT.byte2, MVT.byte2, MVT.byte2, MVT.byte4, MVT.blobIndex, MVT.stringIndex, MVT.stringIndex, MVT.blobIndex, MVT.end, // 35
|
|
||||||
MVT.byte4, MVT.assemblyRefIndex, MVT.end, // 36
|
|
||||||
MVT.byte4, MVT.byte4, MVT.byte4, MVT.assemblyRefIndex, MVT.end, // 37
|
|
||||||
MVT.byte4, MVT.stringIndex, MVT.blobIndex, MVT.end, // 38
|
|
||||||
MVT.byte4, MVT.byte4, MVT.stringIndex, MVT.stringIndex, MVT.implementation, MVT.end,// 39
|
|
||||||
MVT.byte4, MVT.byte4, MVT.stringIndex, MVT.implementation, MVT.end, // 40
|
|
||||||
MVT.typeDefIndex, MVT.typeDefIndex, MVT.end, // 41
|
|
||||||
MVT.byte2, MVT.byte2, MVT.typeOrMethodDef, MVT.stringIndex, MVT.end, // 42
|
|
||||||
MVT.end, // 43
|
|
||||||
MVT.genericParamIndex, MVT.typeDefOrRef, MVT.end, // 44
|
|
||||||
MVT.end, // 45
|
|
||||||
MVT.end, // 46
|
|
||||||
MVT.end, // 47
|
|
||||||
MVT.end, // 48
|
|
||||||
MVT.end, // 49
|
|
||||||
MVT.end, // 50
|
|
||||||
MVT.end, // 51
|
|
||||||
MVT.end, // 52
|
|
||||||
MVT.end, // 53
|
|
||||||
MVT.end, // 54
|
|
||||||
MVT.end, // 55
|
|
||||||
MVT.end, // 56
|
|
||||||
MVT.end, // 57
|
|
||||||
MVT.end, // 58
|
|
||||||
MVT.end, // 59
|
|
||||||
MVT.end, // 60
|
|
||||||
MVT.end, // 61
|
|
||||||
MVT.end, // 62
|
|
||||||
MVT.end, // 63
|
|
||||||
|
|
||||||
MVT.stop
|
|
||||||
};
|
|
||||||
|
|
||||||
void init() {
|
|
||||||
var streamTable = metadata.getStream("#~") ?? metadata.getStream("#-");
|
|
||||||
if (streamTable == null)
|
|
||||||
throw new ApplicationException("Could not find #~ stream");
|
|
||||||
|
|
||||||
seek(streamTable.Offset);
|
|
||||||
reader.ReadUInt32(); // reserved
|
|
||||||
reader.ReadUInt16(); // major + minor version
|
|
||||||
heapOffsetSizes = reader.ReadByte();
|
|
||||||
reader.ReadByte(); // always 1
|
|
||||||
ulong validMask = reader.ReadUInt64();
|
|
||||||
reader.ReadUInt64(); // sorted
|
|
||||||
|
|
||||||
var numRows = new uint[64];
|
|
||||||
for (int i = 0; validMask != 0; i++, validMask >>= 1) {
|
|
||||||
if ((validMask & 1) != 0)
|
|
||||||
numRows[i] = reader.ReadUInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
var builder = new MetadataTypeBuilder(heapOffsetSizes, numRows);
|
|
||||||
uint fileOffset = (uint)reader.BaseStream.Position;
|
|
||||||
for (int i = 0, j = 0; ; i++) {
|
|
||||||
if (metadataVarType[i] == MVT.end) {
|
|
||||||
var mdType = builder.create();
|
|
||||||
mdType.rows = numRows[j];
|
|
||||||
mdType.fileOffset = fileOffset;
|
|
||||||
fileOffset += mdType.rows * mdType.totalSize;
|
|
||||||
metadataTypes[j++] = mdType;
|
|
||||||
}
|
|
||||||
else if (metadataVarType[i] == MVT.stop)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
builder.field(metadataVarType[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
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.Collections.Generic;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
public enum MetadataIndex {
|
|
||||||
iModule = 0,
|
|
||||||
iTypeRef = 1,
|
|
||||||
iTypeDef = 2,
|
|
||||||
iField = 4,
|
|
||||||
iMethodDef = 6,
|
|
||||||
iParam = 8,
|
|
||||||
iInterfaceImpl = 9,
|
|
||||||
iMemberRef = 10,
|
|
||||||
iConstant = 11,
|
|
||||||
iCustomAttribute = 12,
|
|
||||||
iFieldMarshal = 13,
|
|
||||||
iDeclSecurity = 14,
|
|
||||||
iClassLayout = 15,
|
|
||||||
iFieldLayout = 16,
|
|
||||||
iStandAloneSig = 17,
|
|
||||||
iEventMap = 18,
|
|
||||||
iEvent = 20,
|
|
||||||
iPropertyMap = 21,
|
|
||||||
iProperty = 23,
|
|
||||||
iMethodSemantics = 24,
|
|
||||||
iMethodImpl = 25,
|
|
||||||
iModuleRef = 26,
|
|
||||||
iTypeSpec = 27,
|
|
||||||
iImplMap = 28,
|
|
||||||
iFieldRVA = 29,
|
|
||||||
iAssembly = 32,
|
|
||||||
iAssemblyProcessor = 33,
|
|
||||||
iAssemblyOS = 34,
|
|
||||||
iAssemblyRef = 35,
|
|
||||||
iAssemblyRefProcessor = 36,
|
|
||||||
iAssemblyRefOS = 37,
|
|
||||||
iFile = 38,
|
|
||||||
iExportedType = 39,
|
|
||||||
iManifestResource = 40,
|
|
||||||
iNestedClass = 41,
|
|
||||||
iGenericParam = 42,
|
|
||||||
iGenericParamConstraint = 44,
|
|
||||||
};
|
|
||||||
|
|
||||||
public class MetadataType {
|
|
||||||
public uint fileOffset;
|
|
||||||
public uint rows;
|
|
||||||
public uint totalSize;
|
|
||||||
public List<MetadataField> fields;
|
|
||||||
|
|
||||||
public MetadataType(List<MetadataField> fields) {
|
|
||||||
this.fields = fields;
|
|
||||||
totalSize = 0;
|
|
||||||
foreach (var field in fields)
|
|
||||||
totalSize += (uint)field.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return string.Format("MDType: {0:X8}, {1} rows, {2} bytes, {3} fields", fileOffset, rows, totalSize, fields.Count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct MetadataField {
|
|
||||||
public int offset;
|
|
||||||
public int size;
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return string.Format("offset: {0}, size {1}", offset, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,203 +0,0 @@
|
||||||
/*
|
|
||||||
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;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
enum MetadataVarType {
|
|
||||||
end,
|
|
||||||
stop,
|
|
||||||
byte1,
|
|
||||||
byte2,
|
|
||||||
byte4,
|
|
||||||
stringIndex, // index into #String heap
|
|
||||||
guidIndex, // index into #GUID heap
|
|
||||||
blobIndex, // index into #Blob heap
|
|
||||||
resolutionScope,
|
|
||||||
typeDefOrRef,
|
|
||||||
fieldIndex,
|
|
||||||
methodDefIndex,
|
|
||||||
paramIndex,
|
|
||||||
typeDefIndex,
|
|
||||||
eventIndex,
|
|
||||||
propertyIndex,
|
|
||||||
moduleRefIndex,
|
|
||||||
assemblyRefIndex,
|
|
||||||
genericParamIndex,
|
|
||||||
memberRefParent,
|
|
||||||
hasConstant,
|
|
||||||
hasCustomAttribute,
|
|
||||||
customAttributeType,
|
|
||||||
hasFieldMarshal,
|
|
||||||
hasDeclSecurity,
|
|
||||||
hasSemantics,
|
|
||||||
methodDefOrRef,
|
|
||||||
memberForwarded,
|
|
||||||
implementation,
|
|
||||||
typeOrMethodDef,
|
|
||||||
};
|
|
||||||
|
|
||||||
class MetadataTypeBuilder {
|
|
||||||
byte heapOffsetSizes;
|
|
||||||
uint[] numRows;
|
|
||||||
List<MetadataField> fields;
|
|
||||||
int offset;
|
|
||||||
|
|
||||||
public MetadataTypeBuilder(byte heapOffsetSizes, uint[] numRows) {
|
|
||||||
this.heapOffsetSizes = heapOffsetSizes;
|
|
||||||
this.numRows = numRows;
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
offset = 0;
|
|
||||||
fields = new List<MetadataField>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MetadataType create() {
|
|
||||||
var type = new MetadataType(fields);
|
|
||||||
reset();
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void field(MetadataVarType type) {
|
|
||||||
int size;
|
|
||||||
switch (type) {
|
|
||||||
case MetadataVarType.byte1:
|
|
||||||
size = 1;
|
|
||||||
break;
|
|
||||||
case MetadataVarType.byte2:
|
|
||||||
size = 2;
|
|
||||||
break;
|
|
||||||
case MetadataVarType.byte4:
|
|
||||||
size = 4;
|
|
||||||
break;
|
|
||||||
case MetadataVarType.stringIndex:
|
|
||||||
size = (heapOffsetSizes & 1) != 0 ? 4 : 2;
|
|
||||||
break;
|
|
||||||
case MetadataVarType.guidIndex:
|
|
||||||
size = (heapOffsetSizes & 2) != 0 ? 4 : 2;
|
|
||||||
break;
|
|
||||||
case MetadataVarType.blobIndex:
|
|
||||||
size = (heapOffsetSizes & 4) != 0 ? 4 : 2;
|
|
||||||
break;
|
|
||||||
case MetadataVarType.resolutionScope:
|
|
||||||
size = getSize(14, new MetadataIndex[] { MetadataIndex.iModule, MetadataIndex.iModuleRef, MetadataIndex.iAssemblyRef, MetadataIndex.iTypeRef });
|
|
||||||
break;
|
|
||||||
case MetadataVarType.typeDefOrRef:
|
|
||||||
size = getSize(14, new MetadataIndex[] { MetadataIndex.iTypeDef, MetadataIndex.iTypeRef, MetadataIndex.iTypeSpec });
|
|
||||||
break;
|
|
||||||
case MetadataVarType.memberRefParent:
|
|
||||||
size = getSize(13, new MetadataIndex[] { MetadataIndex.iTypeDef, MetadataIndex.iTypeRef, MetadataIndex.iModuleRef, MetadataIndex.iMethodDef, MetadataIndex.iTypeSpec });
|
|
||||||
break;
|
|
||||||
case MetadataVarType.hasConstant:
|
|
||||||
size = getSize(14, new MetadataIndex[] { MetadataIndex.iField, MetadataIndex.iParam, MetadataIndex.iProperty });
|
|
||||||
break;
|
|
||||||
case MetadataVarType.hasCustomAttribute:
|
|
||||||
size = getSize(11, new MetadataIndex[] {
|
|
||||||
MetadataIndex.iMethodDef, MetadataIndex.iField, MetadataIndex.iTypeRef,
|
|
||||||
MetadataIndex.iTypeDef, MetadataIndex.iParam, MetadataIndex.iInterfaceImpl,
|
|
||||||
MetadataIndex.iMemberRef, MetadataIndex.iModule /*TODO:, MetadataIndex.iPermission*/,
|
|
||||||
MetadataIndex.iProperty, MetadataIndex.iEvent, MetadataIndex.iStandAloneSig,
|
|
||||||
MetadataIndex.iModuleRef, MetadataIndex.iTypeSpec, MetadataIndex.iAssembly,
|
|
||||||
MetadataIndex.iAssemblyRef, MetadataIndex.iFile, MetadataIndex.iExportedType,
|
|
||||||
MetadataIndex.iManifestResource,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case MetadataVarType.customAttributeType:
|
|
||||||
size = getSize(13, new MetadataIndex[] { MetadataIndex.iMethodDef, MetadataIndex.iMemberRef }); // others aren't used
|
|
||||||
break;
|
|
||||||
case MetadataVarType.hasFieldMarshal:
|
|
||||||
size = getSize(15, new MetadataIndex[] { MetadataIndex.iField, MetadataIndex.iParam });
|
|
||||||
break;
|
|
||||||
case MetadataVarType.hasDeclSecurity:
|
|
||||||
size = getSize(14, new MetadataIndex[] { MetadataIndex.iTypeDef, MetadataIndex.iMethodDef, MetadataIndex.iAssembly });
|
|
||||||
break;
|
|
||||||
case MetadataVarType.hasSemantics:
|
|
||||||
size = getSize(15, new MetadataIndex[] { MetadataIndex.iEvent, MetadataIndex.iProperty });
|
|
||||||
break;
|
|
||||||
case MetadataVarType.methodDefOrRef:
|
|
||||||
size = getSize(15, new MetadataIndex[] { MetadataIndex.iMethodDef, MetadataIndex.iMemberRef });
|
|
||||||
break;
|
|
||||||
case MetadataVarType.memberForwarded:
|
|
||||||
size = getSize(15, new MetadataIndex[] { MetadataIndex.iField, MetadataIndex.iMethodDef });
|
|
||||||
break;
|
|
||||||
case MetadataVarType.implementation:
|
|
||||||
size = getSize(14, new MetadataIndex[] { MetadataIndex.iFile, MetadataIndex.iAssemblyRef, MetadataIndex.iExportedType });
|
|
||||||
break;
|
|
||||||
case MetadataVarType.typeOrMethodDef:
|
|
||||||
size = getSize(15, new MetadataIndex[] { MetadataIndex.iTypeDef, MetadataIndex.iMethodDef });
|
|
||||||
break;
|
|
||||||
case MetadataVarType.fieldIndex:
|
|
||||||
size = getSize(MetadataIndex.iField);
|
|
||||||
break;
|
|
||||||
case MetadataVarType.methodDefIndex:
|
|
||||||
size = getSize(MetadataIndex.iMethodDef);
|
|
||||||
break;
|
|
||||||
case MetadataVarType.paramIndex:
|
|
||||||
size = getSize(MetadataIndex.iParam);
|
|
||||||
break;
|
|
||||||
case MetadataVarType.typeDefIndex:
|
|
||||||
size = getSize(MetadataIndex.iTypeDef);
|
|
||||||
break;
|
|
||||||
case MetadataVarType.eventIndex:
|
|
||||||
size = getSize(MetadataIndex.iEvent);
|
|
||||||
break;
|
|
||||||
case MetadataVarType.propertyIndex:
|
|
||||||
size = getSize(MetadataIndex.iProperty);
|
|
||||||
break;
|
|
||||||
case MetadataVarType.moduleRefIndex:
|
|
||||||
size = getSize(MetadataIndex.iModuleRef);
|
|
||||||
break;
|
|
||||||
case MetadataVarType.assemblyRefIndex:
|
|
||||||
size = getSize(MetadataIndex.iAssemblyRef);
|
|
||||||
break;
|
|
||||||
case MetadataVarType.genericParamIndex:
|
|
||||||
size = getSize(MetadataIndex.iGenericParam);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ApplicationException("Unknown type");
|
|
||||||
}
|
|
||||||
|
|
||||||
var field = new MetadataField();
|
|
||||||
field.offset = offset;
|
|
||||||
field.size = size;
|
|
||||||
fields.Add(field);
|
|
||||||
offset += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint getMaxRows(MetadataIndex[] indexes) {
|
|
||||||
uint maxRows = 0;
|
|
||||||
for (int i = 0; i < indexes.Length; i++)
|
|
||||||
maxRows = Math.Max(maxRows, numRows[(int)indexes[i]]);
|
|
||||||
return maxRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getSize(int bits, MetadataIndex[] indexes) {
|
|
||||||
uint maxNum = 1U << bits;
|
|
||||||
uint maxRows = getMaxRows(indexes);
|
|
||||||
return maxRows <= maxNum ? 2 : 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getSize(MetadataIndex index) {
|
|
||||||
return getSize(16, new MetadataIndex[] { index });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
/*
|
|
||||||
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.IO;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
public class OptionalHeader : IFileLocation {
|
|
||||||
public ushort magic;
|
|
||||||
public byte majorLinkerVersion;
|
|
||||||
public byte minorLinkerVersion;
|
|
||||||
public uint sizeOfCode;
|
|
||||||
public uint sizeOfInitializedData;
|
|
||||||
public uint sizeOfUninitializedData;
|
|
||||||
public uint addressOfEntryPoint;
|
|
||||||
public uint baseOfCode;
|
|
||||||
public uint baseOfData; // 32-bit only
|
|
||||||
public ulong imageBase;
|
|
||||||
public uint sectionAlignment;
|
|
||||||
public uint fileAlignment;
|
|
||||||
public ushort majorOperatingSystemVersion;
|
|
||||||
public ushort minorOperatingSystemVersion;
|
|
||||||
public ushort majorImageVersion;
|
|
||||||
public ushort minorImageVersion;
|
|
||||||
public ushort majorSubsystemVersion;
|
|
||||||
public ushort minorSubsystemVersion;
|
|
||||||
public uint win32VersionValue;
|
|
||||||
public uint sizeOfImage;
|
|
||||||
public uint sizeOfHeaders;
|
|
||||||
public uint checkSum;
|
|
||||||
public ushort subsystem;
|
|
||||||
public ushort dllCharacteristics;
|
|
||||||
public ulong sizeOfStackReserve;
|
|
||||||
public ulong sizeOfStackCommit;
|
|
||||||
public ulong sizeOfHeapReserve;
|
|
||||||
public ulong sizeOfHeapCommit;
|
|
||||||
public uint loaderFlags;
|
|
||||||
public uint numberOfRvaAndSizes;
|
|
||||||
public DataDirectory[] dataDirectories;
|
|
||||||
|
|
||||||
uint offset, length;
|
|
||||||
public uint Offset {
|
|
||||||
get { return offset; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Length {
|
|
||||||
get { return length; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public OptionalHeader(BinaryReader reader) {
|
|
||||||
offset = (uint)reader.BaseStream.Position;
|
|
||||||
magic = reader.ReadUInt16();
|
|
||||||
majorLinkerVersion = reader.ReadByte();
|
|
||||||
minorLinkerVersion = reader.ReadByte();
|
|
||||||
sizeOfCode = reader.ReadUInt32();
|
|
||||||
sizeOfInitializedData = reader.ReadUInt32();
|
|
||||||
sizeOfUninitializedData = reader.ReadUInt32();
|
|
||||||
addressOfEntryPoint = reader.ReadUInt32();
|
|
||||||
baseOfCode = reader.ReadUInt32();
|
|
||||||
if (is32bit())
|
|
||||||
baseOfData = reader.ReadUInt32();
|
|
||||||
imageBase = read4Or8(reader);
|
|
||||||
sectionAlignment = reader.ReadUInt32();
|
|
||||||
fileAlignment = reader.ReadUInt32();
|
|
||||||
majorOperatingSystemVersion = reader.ReadUInt16();
|
|
||||||
minorOperatingSystemVersion = reader.ReadUInt16();
|
|
||||||
majorImageVersion = reader.ReadUInt16();
|
|
||||||
minorImageVersion = reader.ReadUInt16();
|
|
||||||
majorSubsystemVersion = reader.ReadUInt16();
|
|
||||||
minorSubsystemVersion = reader.ReadUInt16();
|
|
||||||
win32VersionValue = reader.ReadUInt32();
|
|
||||||
sizeOfImage = reader.ReadUInt32();
|
|
||||||
sizeOfHeaders = reader.ReadUInt32();
|
|
||||||
checkSum = reader.ReadUInt32();
|
|
||||||
subsystem = reader.ReadUInt16();
|
|
||||||
dllCharacteristics = reader.ReadUInt16();
|
|
||||||
sizeOfStackReserve = read4Or8(reader);
|
|
||||||
sizeOfStackCommit = read4Or8(reader);
|
|
||||||
sizeOfHeapReserve = read4Or8(reader);
|
|
||||||
sizeOfHeapCommit = read4Or8(reader);
|
|
||||||
loaderFlags = reader.ReadUInt32();
|
|
||||||
numberOfRvaAndSizes = reader.ReadUInt32();
|
|
||||||
|
|
||||||
dataDirectories = new DataDirectory[16];
|
|
||||||
for (int i = 0; i < dataDirectories.Length; i++)
|
|
||||||
dataDirectories[i].read(reader);
|
|
||||||
length = (uint)reader.BaseStream.Position - offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint offsetOfDataDirectory(int n) {
|
|
||||||
return offset + length - (uint)(16 - n) * 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong read4Or8(BinaryReader reader) {
|
|
||||||
if (is32bit())
|
|
||||||
return reader.ReadUInt32();
|
|
||||||
return reader.ReadUInt64();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool is32bit() {
|
|
||||||
return magic != 0x20B;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,285 +0,0 @@
|
||||||
/*
|
|
||||||
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.IO;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
public class PeImage {
|
|
||||||
BinaryReader reader;
|
|
||||||
BinaryWriter writer;
|
|
||||||
FileHeader fileHeader;
|
|
||||||
OptionalHeader optionalHeader;
|
|
||||||
SectionHeader[] sectionHeaders;
|
|
||||||
Cor20Header cor20Header;
|
|
||||||
SectionHeader dotNetSection;
|
|
||||||
Resources resources;
|
|
||||||
|
|
||||||
public BinaryReader Reader {
|
|
||||||
get { return reader; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint ImageLength {
|
|
||||||
get { return (uint)reader.BaseStream.Length; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cor20Header Cor20Header {
|
|
||||||
get { return cor20Header; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Resources Resources {
|
|
||||||
get { return resources; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileHeader FileHeader {
|
|
||||||
get { return fileHeader; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public OptionalHeader OptionalHeader {
|
|
||||||
get { return optionalHeader; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public SectionHeader[] Sections {
|
|
||||||
get { return sectionHeaders; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint FileHeaderOffset {
|
|
||||||
get { return fileHeader.Offset; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public PeImage(byte[] data)
|
|
||||||
: this(new MemoryStream(data)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public PeImage(Stream stream) {
|
|
||||||
reader = new BinaryReader(stream);
|
|
||||||
if (stream.CanWrite)
|
|
||||||
writer = new BinaryWriter(stream);
|
|
||||||
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SectionHeader findSection(string displayName) {
|
|
||||||
foreach (var section in sectionHeaders) {
|
|
||||||
if (section.displayName == displayName)
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void seek(uint position) {
|
|
||||||
reader.BaseStream.Position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
void seekRva(uint rva) {
|
|
||||||
seek(rvaToOffset(rva));
|
|
||||||
}
|
|
||||||
|
|
||||||
void skip(int bytes) {
|
|
||||||
reader.BaseStream.Position += bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init() {
|
|
||||||
seek(0);
|
|
||||||
if (reader.ReadUInt16() != 0x5A4D)
|
|
||||||
throw new BadImageFormatException("Not a PE file");
|
|
||||||
skip(29 * 2);
|
|
||||||
seek(reader.ReadUInt32());
|
|
||||||
|
|
||||||
if (reader.ReadUInt32() != 0x4550)
|
|
||||||
throw new BadImageFormatException("Not a PE file");
|
|
||||||
fileHeader = new FileHeader(reader);
|
|
||||||
optionalHeader = new OptionalHeader(reader);
|
|
||||||
|
|
||||||
sectionHeaders = new SectionHeader[fileHeader.numberOfSections];
|
|
||||||
for (int i = 0; i < sectionHeaders.Length; i++)
|
|
||||||
sectionHeaders[i] = new SectionHeader(reader);
|
|
||||||
|
|
||||||
uint netRva = optionalHeader.dataDirectories[14].virtualAddress;
|
|
||||||
if (netRva != 0) {
|
|
||||||
seekRva(netRva);
|
|
||||||
cor20Header = new Cor20Header(reader);
|
|
||||||
dotNetSection = getSectionHeaderRva(netRva);
|
|
||||||
seekRva(cor20Header.metadataDirectory.virtualAddress);
|
|
||||||
cor20Header.initMetadataTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint resourceRva = optionalHeader.dataDirectories[2].virtualAddress;
|
|
||||||
uint resourceOffset = 0;
|
|
||||||
if (resourceRva != 0)
|
|
||||||
resourceOffset = rvaToOffset(resourceRva);
|
|
||||||
resources = new Resources(reader, resourceOffset, optionalHeader.dataDirectories[2].size);
|
|
||||||
}
|
|
||||||
|
|
||||||
SectionHeader getSectionHeaderRva(uint rva) {
|
|
||||||
for (int i = 0; i < sectionHeaders.Length; i++) {
|
|
||||||
var section = sectionHeaders[i];
|
|
||||||
if (section.virtualAddress <= rva && rva < section.virtualAddress + Math.Max(section.virtualSize, section.sizeOfRawData))
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
SectionHeader getSectionHeaderOffset(uint offset) {
|
|
||||||
for (int i = 0; i < sectionHeaders.Length; i++) {
|
|
||||||
var section = sectionHeaders[i];
|
|
||||||
if (section.pointerToRawData <= offset && offset < section.pointerToRawData + section.sizeOfRawData)
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint rvaToOffset(uint rva) {
|
|
||||||
var section = getSectionHeaderRva(rva);
|
|
||||||
if (section == null)
|
|
||||||
throw new ApplicationException(string.Format("Invalid RVA {0:X8}", rva));
|
|
||||||
return rva - section.virtualAddress + section.pointerToRawData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint offsetToRva(uint offset) {
|
|
||||||
var section = getSectionHeaderOffset(offset);
|
|
||||||
if (section == null)
|
|
||||||
throw new ApplicationException(string.Format("Invalid offset {0:X8}", offset));
|
|
||||||
return offset - section.pointerToRawData + section.virtualAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool intersect(uint offset1, uint length1, uint offset2, uint length2) {
|
|
||||||
return !(offset1 + length1 <= offset2 || offset2 + length2 <= offset1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool intersect(uint offset, uint length, IFileLocation location) {
|
|
||||||
return intersect(offset, length, location.Offset, location.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool dotNetSafeWriteOffset(uint offset, byte[] data) {
|
|
||||||
if (cor20Header != null) {
|
|
||||||
uint length = (uint)data.Length;
|
|
||||||
|
|
||||||
if (!dotNetSection.isInside(offset, length))
|
|
||||||
return false;
|
|
||||||
if (intersect(offset, length, cor20Header))
|
|
||||||
return false;
|
|
||||||
if (intersect(offset, length, cor20Header.MetadataOffset, cor20Header.MetadataHeaderLength))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
offsetWrite(offset, data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool dotNetSafeWrite(uint rva, byte[] data) {
|
|
||||||
return dotNetSafeWriteOffset(rvaToOffset(rva), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(uint rva, byte[] data) {
|
|
||||||
seekRva(rva);
|
|
||||||
writer.Write(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeUInt16(uint rva, ushort data) {
|
|
||||||
seekRva(rva);
|
|
||||||
writer.Write(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeUInt32(uint rva, uint data) {
|
|
||||||
seekRva(rva);
|
|
||||||
writer.Write(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte readByte(uint rva) {
|
|
||||||
seekRva(rva);
|
|
||||||
return reader.ReadByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ushort readUInt16(uint rva) {
|
|
||||||
seekRva(rva);
|
|
||||||
return reader.ReadUInt16();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint readUInt32(uint rva) {
|
|
||||||
seekRva(rva);
|
|
||||||
return reader.ReadUInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readInt32(uint rva) {
|
|
||||||
seekRva(rva);
|
|
||||||
return reader.ReadInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] readBytes(uint rva, int size) {
|
|
||||||
seekRva(rva);
|
|
||||||
return reader.ReadBytes(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void offsetWrite(uint offset, byte[] data) {
|
|
||||||
seek(offset);
|
|
||||||
writer.Write(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] offsetReadBytes(uint offset, int size) {
|
|
||||||
seek(offset);
|
|
||||||
return reader.ReadBytes(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint offsetRead(uint offset, int size) {
|
|
||||||
if (size == 2) return offsetReadUInt16(offset);
|
|
||||||
if (size == 4) return offsetReadUInt32(offset);
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte offsetReadByte(uint offset) {
|
|
||||||
seek(offset);
|
|
||||||
return reader.ReadByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ushort offsetReadUInt16(uint offset) {
|
|
||||||
seek(offset);
|
|
||||||
return reader.ReadUInt16();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint offsetReadUInt32(uint offset) {
|
|
||||||
seek(offset);
|
|
||||||
return reader.ReadUInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void offsetWrite(uint offset, uint data, int size) {
|
|
||||||
if (size == 2)
|
|
||||||
offsetWriteUInt16(offset, (ushort)data);
|
|
||||||
else if (size == 4)
|
|
||||||
offsetWriteUInt32(offset, data);
|
|
||||||
else
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void offsetWriteUInt16(uint offset, ushort data) {
|
|
||||||
seek(offset);
|
|
||||||
writer.Write(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void offsetWriteUInt32(uint offset, uint data) {
|
|
||||||
seek(offset);
|
|
||||||
writer.Write(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] readAllBytes() {
|
|
||||||
seek(0);
|
|
||||||
return reader.ReadBytes((int)reader.BaseStream.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,124 +0,0 @@
|
||||||
/*
|
|
||||||
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.Collections.Generic;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
public class ResourceDirectory : ResourceDirectoryEntry {
|
|
||||||
Resources resources;
|
|
||||||
int offset;
|
|
||||||
List<ResourceData> resourceDataList = new List<ResourceData>();
|
|
||||||
List<ResourceDirectory> resourceDirectoryList = new List<ResourceDirectory>();
|
|
||||||
|
|
||||||
public List<ResourceData> Data {
|
|
||||||
get { return resourceDataList; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ResourceDirectory> Directories {
|
|
||||||
get { return resourceDirectoryList; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceDirectory(int id, Resources resources, int offset)
|
|
||||||
: base(id) {
|
|
||||||
init(resources, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceDirectory(string name, Resources resources, int offset)
|
|
||||||
: base(name) {
|
|
||||||
init(resources, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(Resources resources, int offset) {
|
|
||||||
this.resources = resources;
|
|
||||||
this.offset = offset;
|
|
||||||
initializeEntries();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceDirectory getDirectory(int id) {
|
|
||||||
return find(resourceDirectoryList, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceDirectory getDirectory(string name) {
|
|
||||||
return find(resourceDirectoryList, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceData getData(int id) {
|
|
||||||
return find(resourceDataList, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceData getData(string name) {
|
|
||||||
return find(resourceDataList, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void initializeEntries() {
|
|
||||||
if (offset < 0)
|
|
||||||
return;
|
|
||||||
if (!resources.isSizeAvailable(offset, 16))
|
|
||||||
return;
|
|
||||||
if (!resources.seek(offset + 12))
|
|
||||||
return;
|
|
||||||
|
|
||||||
int named = resources.readUInt16();
|
|
||||||
int ids = resources.readUInt16();
|
|
||||||
int total = named + ids;
|
|
||||||
if (!resources.isSizeAvailable(total * 8))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 0, entryOffset = offset + 16; i < total; i++, entryOffset += 8) {
|
|
||||||
resources.seek(entryOffset);
|
|
||||||
uint nameOrId = resources.readUInt32();
|
|
||||||
uint dataOrDirectory = resources.readUInt32();
|
|
||||||
|
|
||||||
string name = null;
|
|
||||||
int id = -1;
|
|
||||||
if ((nameOrId & 0x80000000) != 0) {
|
|
||||||
name = resources.readString((int)(nameOrId & 0x7FFFFFFF));
|
|
||||||
if (name == null)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
id = (int)nameOrId;
|
|
||||||
|
|
||||||
if ((dataOrDirectory & 0x80000000) == 0) {
|
|
||||||
if (!resources.seek((int)dataOrDirectory))
|
|
||||||
break;
|
|
||||||
if (!resources.isSizeAvailable(16))
|
|
||||||
break;
|
|
||||||
uint dataRva = resources.readUInt32();
|
|
||||||
uint dataSize = resources.readUInt32();
|
|
||||||
if (name == null)
|
|
||||||
resourceDataList.Add(new ResourceData(id, dataRva, dataSize));
|
|
||||||
else
|
|
||||||
resourceDataList.Add(new ResourceData(name, dataRva, dataSize));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int directoryOffset = (int)(dataOrDirectory & 0x7FFFFFFF);
|
|
||||||
if (name == null)
|
|
||||||
resourceDirectoryList.Add(new ResourceDirectory(id, resources, directoryOffset));
|
|
||||||
else
|
|
||||||
resourceDirectoryList.Add(new ResourceDirectory(name, resources, directoryOffset));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return string.Format("OFS: {0:X8}, NAME: {1}", offset, getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
/*
|
|
||||||
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.Collections.Generic;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
public abstract class ResourceDirectoryEntry {
|
|
||||||
protected readonly string name;
|
|
||||||
protected readonly int id;
|
|
||||||
|
|
||||||
public bool HasStringName {
|
|
||||||
get { return name != null; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasId {
|
|
||||||
get { return !HasStringName; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name {
|
|
||||||
get { return name; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Id {
|
|
||||||
get { return id; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceDirectoryEntry(int id) {
|
|
||||||
this.name = null;
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceDirectoryEntry(string name) {
|
|
||||||
this.name = name;
|
|
||||||
this.id = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected string getName() {
|
|
||||||
return HasStringName ? name : id.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static T find<T>(IEnumerable<T> list, int id) where T : ResourceDirectoryEntry {
|
|
||||||
foreach (var dirEntry in list) {
|
|
||||||
if (dirEntry.HasId && dirEntry.Id == id)
|
|
||||||
return dirEntry;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static T find<T>(IEnumerable<T> list, string name) where T : ResourceDirectoryEntry {
|
|
||||||
foreach (var dirEntry in list) {
|
|
||||||
if (dirEntry.HasStringName && dirEntry.Name == name)
|
|
||||||
return dirEntry;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
/*
|
|
||||||
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.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
public class Resources {
|
|
||||||
BinaryReader reader;
|
|
||||||
uint startOffset;
|
|
||||||
uint totalSize;
|
|
||||||
ResourceDirectory root;
|
|
||||||
|
|
||||||
public BinaryReader Reader {
|
|
||||||
get { return reader; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Resources(BinaryReader reader, uint startOffset, uint totalSize) {
|
|
||||||
this.reader = reader;
|
|
||||||
this.startOffset = startOffset;
|
|
||||||
this.totalSize = totalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceDirectory getRoot() {
|
|
||||||
if (root != null)
|
|
||||||
return root;
|
|
||||||
return root = new ResourceDirectory("root", this, startOffset == 0 ? -1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool isSizeAvailable(int offset, int size) {
|
|
||||||
if (offset < 0 || offset + size < offset)
|
|
||||||
return false;
|
|
||||||
return (uint)(offset + size) <= totalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool isSizeAvailable(int size) {
|
|
||||||
return isSizeAvailable((int)(reader.BaseStream.Position - startOffset), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool seek(int offset) {
|
|
||||||
if (!isSizeAvailable(offset, 0))
|
|
||||||
return false;
|
|
||||||
reader.BaseStream.Position = startOffset + offset;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ushort readUInt16() {
|
|
||||||
return reader.ReadUInt16();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint readUInt32() {
|
|
||||||
return reader.ReadUInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] readBytes(int size) {
|
|
||||||
return reader.ReadBytes(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string readString(int offset) {
|
|
||||||
if (!seek(offset))
|
|
||||||
return null;
|
|
||||||
if (!isSizeAvailable(2))
|
|
||||||
return null;
|
|
||||||
int size = readUInt16();
|
|
||||||
int sizeInBytes = size * 2;
|
|
||||||
if (!isSizeAvailable(sizeInBytes))
|
|
||||||
return null;
|
|
||||||
var stringData = readBytes(sizeInBytes);
|
|
||||||
try {
|
|
||||||
return Encoding.Unicode.GetString(stringData);
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
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.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace de4dot.PE {
|
|
||||||
public class SectionHeader : IFileLocation {
|
|
||||||
public byte[] name;
|
|
||||||
public uint virtualSize;
|
|
||||||
public uint virtualAddress;
|
|
||||||
public uint sizeOfRawData;
|
|
||||||
public uint pointerToRawData;
|
|
||||||
public uint pointerToRelocations;
|
|
||||||
public uint pointerToLinenumbers;
|
|
||||||
public ushort numberOfRelocations;
|
|
||||||
public ushort numberOfLinenumbers;
|
|
||||||
public uint characteristics;
|
|
||||||
public string displayName;
|
|
||||||
|
|
||||||
uint offset;
|
|
||||||
public uint Offset {
|
|
||||||
get { return offset; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Length {
|
|
||||||
get { return 10 * 4; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public SectionHeader(BinaryReader reader) {
|
|
||||||
offset = (uint)reader.BaseStream.Position;
|
|
||||||
name = reader.ReadBytes(8);
|
|
||||||
virtualSize = reader.ReadUInt32();
|
|
||||||
virtualAddress = reader.ReadUInt32();
|
|
||||||
sizeOfRawData = reader.ReadUInt32();
|
|
||||||
pointerToRawData = reader.ReadUInt32();
|
|
||||||
pointerToRelocations = reader.ReadUInt32();
|
|
||||||
pointerToLinenumbers = reader.ReadUInt32();
|
|
||||||
numberOfRelocations = reader.ReadUInt16();
|
|
||||||
numberOfLinenumbers = reader.ReadUInt16();
|
|
||||||
characteristics = reader.ReadUInt32();
|
|
||||||
|
|
||||||
var sb = new StringBuilder(name.Length);
|
|
||||||
foreach (var c in name) {
|
|
||||||
if (c == 0)
|
|
||||||
break;
|
|
||||||
sb.Append((char)c);
|
|
||||||
}
|
|
||||||
displayName = sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool isInside(uint offset, uint length) {
|
|
||||||
return offset >= pointerToRawData && offset + length <= pointerToRawData + sizeOfRawData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() {
|
|
||||||
return string.Format("{0:X8} {1:X8} {2:X8} - {3}", virtualAddress, virtualSize, sizeOfRawData, displayName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,7 +21,7 @@ using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
[assembly: AssemblyTitle("blocks")]
|
[assembly: AssemblyTitle("blocks")]
|
||||||
[assembly: AssemblyDescription("Modifies Mono.Cecil MethodDefinition bodies")]
|
[assembly: AssemblyDescription("Modifies dot10 MethodDef bodies")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("")]
|
||||||
[assembly: AssemblyProduct("blocks")]
|
[assembly: AssemblyProduct("blocks")]
|
||||||
|
|
|
@ -73,22 +73,6 @@
|
||||||
<Compile Include="InstructionListParser.cs" />
|
<Compile Include="InstructionListParser.cs" />
|
||||||
<Compile Include="MemberDefDict.cs" />
|
<Compile Include="MemberDefDict.cs" />
|
||||||
<Compile Include="MethodBlocks.cs" />
|
<Compile Include="MethodBlocks.cs" />
|
||||||
<Compile Include="PE\Cor20Header.cs" />
|
|
||||||
<Compile Include="PE\DataDirectory.cs" />
|
|
||||||
<Compile Include="PE\DotNetStream.cs" />
|
|
||||||
<Compile Include="PE\FileHeader.cs" />
|
|
||||||
<Compile Include="PE\IFileLocation.cs" />
|
|
||||||
<Compile Include="PE\Metadata.cs" />
|
|
||||||
<Compile Include="PE\MetadataTables.cs" />
|
|
||||||
<Compile Include="PE\MetadataType.cs" />
|
|
||||||
<Compile Include="PE\MetadataTypeBuilder.cs" />
|
|
||||||
<Compile Include="PE\OptionalHeader.cs" />
|
|
||||||
<Compile Include="PE\PeImage.cs" />
|
|
||||||
<Compile Include="PE\ResourceData.cs" />
|
|
||||||
<Compile Include="PE\ResourceDirectory.cs" />
|
|
||||||
<Compile Include="PE\ResourceDirectoryEntry.cs" />
|
|
||||||
<Compile Include="PE\Resources.cs" />
|
|
||||||
<Compile Include="PE\SectionHeader.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ScopeBlock.cs" />
|
<Compile Include="ScopeBlock.cs" />
|
||||||
<Compile Include="TryBlock.cs" />
|
<Compile Include="TryBlock.cs" />
|
||||||
|
|
|
@ -35,8 +35,18 @@ namespace de4dot.code.AssemblyClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NewProcessAssemblyClientFactory : IAssemblyClientFactory {
|
public class NewProcessAssemblyClientFactory : IAssemblyClientFactory {
|
||||||
|
ServerClrVersion serverVersion;
|
||||||
|
|
||||||
|
public NewProcessAssemblyClientFactory() {
|
||||||
|
this.serverVersion = ServerClrVersion.CLR_ANY_ANYCPU;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal NewProcessAssemblyClientFactory(ServerClrVersion serverVersion) {
|
||||||
|
this.serverVersion = serverVersion;
|
||||||
|
}
|
||||||
|
|
||||||
public IAssemblyClient create() {
|
public IAssemblyClient create() {
|
||||||
return new AssemblyClient(new NewProcessAssemblyServerLoader());
|
return new AssemblyClient(new NewProcessAssemblyServerLoader(serverVersion));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,23 +21,45 @@ using System;
|
||||||
using AssemblyData;
|
using AssemblyData;
|
||||||
|
|
||||||
namespace de4dot.code.AssemblyClient {
|
namespace de4dot.code.AssemblyClient {
|
||||||
|
enum ServerClrVersion {
|
||||||
|
CLR_ANY_ANYCPU,
|
||||||
|
CLR_ANY_x86,
|
||||||
|
CLR_ANY_x64,
|
||||||
|
CLR_v20_x86,
|
||||||
|
CLR_v20_x64,
|
||||||
|
CLR_v40_x86,
|
||||||
|
CLR_v40_x64,
|
||||||
|
}
|
||||||
|
|
||||||
abstract class IpcAssemblyServerLoader : IAssemblyServerLoader {
|
abstract class IpcAssemblyServerLoader : IAssemblyServerLoader {
|
||||||
const string ASSEMBLY_SERVER_FILENAME_X86 = "AssemblyServer.exe";
|
|
||||||
const string ASSEMBLY_SERVER_FILENAME_X64 = "AssemblyServer-x64.exe";
|
|
||||||
readonly string assemblyServerFilename;
|
readonly string assemblyServerFilename;
|
||||||
protected string ipcName;
|
protected string ipcName;
|
||||||
protected string ipcUri;
|
protected string ipcUri;
|
||||||
string url;
|
string url;
|
||||||
|
|
||||||
protected IpcAssemblyServerLoader() {
|
protected IpcAssemblyServerLoader()
|
||||||
assemblyServerFilename = getServerName();
|
: this(ServerClrVersion.CLR_ANY_ANYCPU) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IpcAssemblyServerLoader(ServerClrVersion serverVersion) {
|
||||||
|
assemblyServerFilename = getServerName(serverVersion);
|
||||||
ipcName = Utils.randomName(15, 20);
|
ipcName = Utils.randomName(15, 20);
|
||||||
ipcUri = Utils.randomName(15, 20);
|
ipcUri = Utils.randomName(15, 20);
|
||||||
url = string.Format("ipc://{0}/{1}", ipcName, ipcUri);
|
url = string.Format("ipc://{0}/{1}", ipcName, ipcUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
static string getServerName() {
|
static string getServerName(ServerClrVersion serverVersion) {
|
||||||
return IntPtr.Size == 4 ? ASSEMBLY_SERVER_FILENAME_X86 : ASSEMBLY_SERVER_FILENAME_X64;
|
if (serverVersion == ServerClrVersion.CLR_ANY_ANYCPU)
|
||||||
|
serverVersion = IntPtr.Size == 4 ? ServerClrVersion.CLR_ANY_x86 : ServerClrVersion.CLR_ANY_x64;
|
||||||
|
switch (serverVersion) {
|
||||||
|
case ServerClrVersion.CLR_ANY_x86: return "AssemblyServer.exe";
|
||||||
|
case ServerClrVersion.CLR_ANY_x64: return "AssemblyServer-x64.exe";
|
||||||
|
case ServerClrVersion.CLR_v20_x86: return "AssemblyServer-CLR20.exe";
|
||||||
|
case ServerClrVersion.CLR_v20_x64: return "AssemblyServer-CLR20-x64.exe";
|
||||||
|
case ServerClrVersion.CLR_v40_x86: return "AssemblyServer-CLR40.exe";
|
||||||
|
case ServerClrVersion.CLR_v40_x64: return "AssemblyServer-CLR40-x64.exe";
|
||||||
|
default: throw new ArgumentException(string.Format("Invalid server version: {0}", serverVersion));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadServer() {
|
public void loadServer() {
|
||||||
|
|
|
@ -25,6 +25,13 @@ namespace de4dot.code.AssemblyClient {
|
||||||
class NewProcessAssemblyServerLoader : IpcAssemblyServerLoader {
|
class NewProcessAssemblyServerLoader : IpcAssemblyServerLoader {
|
||||||
Process process;
|
Process process;
|
||||||
|
|
||||||
|
public NewProcessAssemblyServerLoader() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NewProcessAssemblyServerLoader(ServerClrVersion version)
|
||||||
|
: base(version) {
|
||||||
|
}
|
||||||
|
|
||||||
public override void loadServer(string filename) {
|
public override void loadServer(string filename) {
|
||||||
if (process != null)
|
if (process != null)
|
||||||
throw new ApplicationException("Server is already loaded");
|
throw new ApplicationException("Server is already loaded");
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace de4dot.code {
|
||||||
dataDict.Remove(name);
|
dataDict.Remove(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ITypeDefOrRef getNonGenericTypeReference(ITypeDefOrRef typeRef) {
|
static ITypeDefOrRef getNonGenericTypeRef(ITypeDefOrRef typeRef) {
|
||||||
var ts = typeRef as TypeSpec;
|
var ts = typeRef as TypeSpec;
|
||||||
if (ts == null)
|
if (ts == null)
|
||||||
return typeRef;
|
return typeRef;
|
||||||
|
@ -59,7 +59,7 @@ namespace de4dot.code {
|
||||||
public TypeDef resolveType(ITypeDefOrRef type) {
|
public TypeDef resolveType(ITypeDefOrRef type) {
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return null;
|
return null;
|
||||||
type = getNonGenericTypeReference(type);
|
type = getNonGenericTypeRef(type);
|
||||||
|
|
||||||
var typeDef = type as TypeDef;
|
var typeDef = type as TypeDef;
|
||||||
if (typeDef != null)
|
if (typeDef != null)
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace de4dot.code {
|
||||||
void deobfuscateEnd();
|
void deobfuscateEnd();
|
||||||
void deobfuscateCleanUp();
|
void deobfuscateCleanUp();
|
||||||
|
|
||||||
void load(IEnumerable<IDeobfuscator> deobfuscators);
|
void load(IList<IDeobfuscator> deobfuscators);
|
||||||
void save();
|
void save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,11 +133,11 @@ namespace de4dot.code {
|
||||||
printExInfo(exInfo);
|
printExInfo(exInfo);
|
||||||
var instrString = instr.OpCode.Name;
|
var instrString = instr.OpCode.Name;
|
||||||
var operandString = getOperandString(instr);
|
var operandString = getOperandString(instr);
|
||||||
var memberReference = instr.Operand as ITokenOperand;
|
var memberRef = instr.Operand as ITokenOperand;
|
||||||
if (operandString == "")
|
if (operandString == "")
|
||||||
Logger.log(loggerEvent, "{0}", instrString);
|
Logger.log(loggerEvent, "{0}", instrString);
|
||||||
else if (memberReference != null)
|
else if (memberRef != null)
|
||||||
Logger.log(loggerEvent, "{0,-9} {1} // {2:X8}", instrString, Utils.removeNewlines(operandString), memberReference.MDToken.ToUInt32());
|
Logger.log(loggerEvent, "{0,-9} {1} // {2:X8}", instrString, Utils.removeNewlines(operandString), memberRef.MDToken.ToUInt32());
|
||||||
else
|
else
|
||||||
Logger.log(loggerEvent, "{0,-9} {1}", instrString, Utils.removeNewlines(operandString));
|
Logger.log(loggerEvent, "{0,-9} {1}", instrString, Utils.removeNewlines(operandString));
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,7 +165,7 @@ namespace de4dot.code {
|
||||||
this.callEndIndex = callEndIndex;
|
this.callEndIndex = callEndIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMethod getMethodReference() {
|
public IMethod getMethodRef() {
|
||||||
return (IMethod)block.Instructions[callEndIndex].Operand;
|
return (IMethod)block.Instructions[callEndIndex].Operand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ namespace de4dot.code {
|
||||||
|
|
||||||
bool findArgs(CallResult callResult) {
|
bool findArgs(CallResult callResult) {
|
||||||
var block = callResult.block;
|
var block = callResult.block;
|
||||||
var method = callResult.getMethodReference();
|
var method = callResult.getMethodRef();
|
||||||
var methodArgs = DotNetUtils.getArgs(method);
|
var methodArgs = DotNetUtils.getArgs(method);
|
||||||
int numArgs = methodArgs.Count;
|
int numArgs = methodArgs.Count;
|
||||||
var args = new object[numArgs];
|
var args = new object[numArgs];
|
||||||
|
|
|
@ -160,14 +160,22 @@ namespace de4dot.code {
|
||||||
return noExt + "-cleaned" + ext;
|
return noExt + "-cleaned" + ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load(IEnumerable<IDeobfuscator> deobfuscators) {
|
public void load(IList<IDeobfuscator> deobfuscators) {
|
||||||
loadModule(deobfuscators);
|
try {
|
||||||
TheAssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(Filename));
|
loadModule(deobfuscators);
|
||||||
TheAssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(NewFilename));
|
TheAssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(Filename));
|
||||||
detectObfuscator(deobfuscators);
|
TheAssemblyResolver.Instance.addSearchDirectory(Utils.getDirName(NewFilename));
|
||||||
if (deob == null)
|
detectObfuscator(deobfuscators);
|
||||||
throw new ApplicationException("Could not detect obfuscator!");
|
if (deob == null)
|
||||||
initializeDeobfuscator();
|
throw new ApplicationException("Could not detect obfuscator!");
|
||||||
|
initializeDeobfuscator();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
foreach (var d in deobfuscators) {
|
||||||
|
if (d != deob && d != null)
|
||||||
|
d.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadModule(IEnumerable<IDeobfuscator> deobfuscators) {
|
void loadModule(IEnumerable<IDeobfuscator> deobfuscators) {
|
||||||
|
@ -187,32 +195,32 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool unpackNativeImage(IEnumerable<IDeobfuscator> deobfuscators) {
|
bool unpackNativeImage(IEnumerable<IDeobfuscator> deobfuscators) {
|
||||||
var peImage = new PEImage(Filename);
|
using (var peImage = new PEImage(Filename)) {
|
||||||
|
foreach (var deob in deobfuscators) {
|
||||||
|
byte[] unpackedData = null;
|
||||||
|
try {
|
||||||
|
unpackedData = deob.unpackNativeFile(peImage);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
if (unpackedData == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
foreach (var deob in deobfuscators) {
|
var oldModule = module;
|
||||||
byte[] unpackedData = null;
|
try {
|
||||||
try {
|
module = assemblyModule.load(unpackedData);
|
||||||
unpackedData = deob.unpackNativeFile(peImage);
|
}
|
||||||
|
catch {
|
||||||
|
Logger.w("Could not load unpacked data. File: {0}, deobfuscator: {0}", peImage.FileName ?? "(unknown filename)", deob.TypeLong);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (oldModule != null)
|
||||||
|
oldModule.Dispose();
|
||||||
|
}
|
||||||
|
this.deob = deob;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
catch {
|
|
||||||
}
|
|
||||||
if (unpackedData == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var oldModule = module;
|
|
||||||
try {
|
|
||||||
module = assemblyModule.load(unpackedData);
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Logger.w("Could not load unpacked data. File: {0}, deobfuscator: {0}", peImage.FileName ?? "(unknown filename)", deob.TypeLong);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (oldModule != null)
|
|
||||||
oldModule.Dispose();
|
|
||||||
}
|
|
||||||
this.deob = deob;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -544,8 +552,6 @@ namespace de4dot.code {
|
||||||
deob.DeobfuscatedFile = null;
|
deob.DeobfuscatedFile = null;
|
||||||
|
|
||||||
if (!options.ControlFlowDeobfuscation) {
|
if (!options.ControlFlowDeobfuscation) {
|
||||||
// If it's the unknown type, we don't remove any types that could cause Mono.Cecil
|
|
||||||
// to throw an exception.
|
|
||||||
if (ShouldPreserveTokens())
|
if (ShouldPreserveTokens())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -778,9 +784,7 @@ namespace de4dot.code {
|
||||||
var baseDir = Utils.getDirName(options.NewFilename);
|
var baseDir = Utils.getDirName(options.NewFilename);
|
||||||
var newName = Path.Combine(baseDir, assemblyName + extension);
|
var newName = Path.Combine(baseDir, assemblyName + extension);
|
||||||
Logger.n("Creating file {0}", newName);
|
Logger.n("Creating file {0}", newName);
|
||||||
using (var writer = new BinaryWriter(new FileStream(newName, FileMode.Create))) {
|
File.WriteAllBytes(newName, data);
|
||||||
writer.Write(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDeobfuscatedFile.stringDecryptersAdded() {
|
void IDeobfuscatedFile.stringDecryptersAdded() {
|
||||||
|
@ -795,6 +799,8 @@ namespace de4dot.code {
|
||||||
deobfuscateCleanUp();
|
deobfuscateCleanUp();
|
||||||
if (module != null)
|
if (module != null)
|
||||||
module.Dispose();
|
module.Dispose();
|
||||||
|
if (deob != null)
|
||||||
|
deob.Dispose();
|
||||||
module = null;
|
module = null;
|
||||||
deob = null;
|
deob = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ namespace de4dot.code {
|
||||||
}
|
}
|
||||||
|
|
||||||
class StaticStringInliner : StringInlinerBase {
|
class StaticStringInliner : StringInlinerBase {
|
||||||
MethodDefinitionAndDeclaringTypeDict<Func<MethodDef, MethodSpec, object[], string>> stringDecrypters = new MethodDefinitionAndDeclaringTypeDict<Func<MethodDef, MethodSpec, object[], string>>();
|
MethodDefAndDeclaringTypeDict<Func<MethodDef, MethodSpec, object[], string>> stringDecrypters = new MethodDefAndDeclaringTypeDict<Func<MethodDef, MethodSpec, object[], string>>();
|
||||||
|
|
||||||
public override bool HasHandlers {
|
public override bool HasHandlers {
|
||||||
get { return stringDecrypters.Count != 0; }
|
get { return stringDecrypters.Count != 0; }
|
||||||
|
|
|
@ -182,7 +182,7 @@
|
||||||
<Compile Include="deobfuscators\DeobUtils.cs" />
|
<Compile Include="deobfuscators\DeobUtils.cs" />
|
||||||
<Compile Include="deobfuscators\Dotfuscator\Deobfuscator.cs" />
|
<Compile Include="deobfuscators\Dotfuscator\Deobfuscator.cs" />
|
||||||
<Compile Include="deobfuscators\Dotfuscator\StringDecrypter.cs" />
|
<Compile Include="deobfuscators\Dotfuscator\StringDecrypter.cs" />
|
||||||
<Compile Include="deobfuscators\dotNET_Reactor\MyPEImage.cs" />
|
<Compile Include="deobfuscators\MyPEImage.cs" />
|
||||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\AntiStrongName.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v3\AntiStrongName.cs" />
|
||||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\ApplicationModeDecrypter.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v3\ApplicationModeDecrypter.cs" />
|
||||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\ApplicationModeUnpacker.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v3\ApplicationModeUnpacker.cs" />
|
||||||
|
|
|
@ -22,7 +22,6 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.PE;
|
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
class CliSecureRtType {
|
class CliSecureRtType {
|
||||||
|
@ -192,13 +191,9 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool findNativeCode(byte[] moduleBytes) {
|
bool findNativeCode(byte[] moduleBytes) {
|
||||||
var stream = moduleBytes != null ?
|
var bytes = moduleBytes != null ? moduleBytes : DeobUtils.readModule(module);
|
||||||
(Stream)new MemoryStream(moduleBytes) :
|
using (var peImage = new MyPEImage(bytes))
|
||||||
(Stream)new FileStream(module.Location, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
||||||
using (stream) {
|
|
||||||
var peImage = new PeImage(stream);
|
|
||||||
return foundSig = MethodsDecrypter.detect(peImage);
|
return foundSig = MethodsDecrypter.detect(peImage);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool isAtLeastVersion50() {
|
public bool isAtLeastVersion50() {
|
||||||
|
|
|
@ -23,7 +23,6 @@ using dot10.IO;
|
||||||
using dot10.PE;
|
using dot10.PE;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.PE;
|
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
public class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
public class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
||||||
|
@ -209,11 +208,11 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
byte[] fileData = ModuleBytes ?? DeobUtils.readModule(module);
|
byte[] fileData = ModuleBytes ?? DeobUtils.readModule(module);
|
||||||
var peImage = new PeImage(fileData);
|
using (var peImage = new MyPEImage(fileData)) {
|
||||||
|
if (!new MethodsDecrypter().decrypt(peImage, module, cliSecureRtType, ref dumpedMethods)) {
|
||||||
if (!new MethodsDecrypter().decrypt(peImage, module, cliSecureRtType, ref dumpedMethods)) {
|
Logger.v("Methods aren't encrypted or invalid signature");
|
||||||
Logger.v("Methods aren't encrypted or invalid signature");
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newFileData = fileData;
|
newFileData = fileData;
|
||||||
|
|
|
@ -20,9 +20,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using dot10.IO;
|
||||||
|
using dot10.PE;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using de4dot.PE;
|
using dot10.DotNet.MD;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
using de4dot.code.AssemblyClient;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
class CodeHeader {
|
class CodeHeader {
|
||||||
|
@ -61,7 +64,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
Pro,
|
Pro,
|
||||||
}
|
}
|
||||||
|
|
||||||
PeImage peImage;
|
MyPEImage peImage;
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
CliSecureRtType csRtType;
|
CliSecureRtType csRtType;
|
||||||
CodeHeader codeHeader = new CodeHeader();
|
CodeHeader codeHeader = new CodeHeader();
|
||||||
|
@ -73,35 +76,36 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class DecrypterBase : IDecrypter {
|
abstract class DecrypterBase : IDecrypter {
|
||||||
protected readonly PeImage peImage;
|
protected readonly MyPEImage peImage;
|
||||||
protected readonly CodeHeader codeHeader;
|
protected readonly CodeHeader codeHeader;
|
||||||
protected readonly uint endOfMetadata;
|
protected readonly uint endOfMetadata;
|
||||||
|
|
||||||
public DecrypterBase(PeImage peImage, CodeHeader codeHeader) {
|
public DecrypterBase(MyPEImage peImage, CodeHeader codeHeader) {
|
||||||
this.peImage = peImage;
|
this.peImage = peImage;
|
||||||
this.codeHeader = codeHeader;
|
this.codeHeader = codeHeader;
|
||||||
endOfMetadata = peImage.rvaToOffset(peImage.Cor20Header.metadataDirectory.virtualAddress + peImage.Cor20Header.metadataDirectory.size);
|
var mdDir = peImage.Cor20Header.MetaData;
|
||||||
|
endOfMetadata = peImage.rvaToOffset((uint)mdDir.VirtualAddress + mdDir.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections);
|
public abstract MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections);
|
||||||
|
|
||||||
protected MethodBodyHeader getCodeBytes(byte[] methodBody, out byte[] code, out byte[] extraSections) {
|
protected MethodBodyHeader getCodeBytes(byte[] methodBody, out byte[] code, out byte[] extraSections) {
|
||||||
return MethodBodyParser.parseMethodBody(new BinaryReader(new MemoryStream(methodBody)), out code, out extraSections);
|
return MethodBodyParser.parseMethodBody(MemoryImageStream.Create(methodBody), out code, out extraSections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CS 1.1 (could be other versions too)
|
// CS 1.1 (could be other versions too)
|
||||||
class Decrypter10 {
|
class Decrypter10 {
|
||||||
PeImage peImage;
|
MyPEImage peImage;
|
||||||
CsBlowfish blowfish;
|
CsBlowfish blowfish;
|
||||||
|
|
||||||
public Decrypter10(PeImage peImage, byte[] key) {
|
public Decrypter10(MyPEImage peImage, byte[] key) {
|
||||||
this.peImage = peImage;
|
this.peImage = peImage;
|
||||||
this.blowfish = new CsBlowfish(key);
|
this.blowfish = new CsBlowfish(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodBodyHeader decrypt(uint bodyOffset, out byte[] code, out byte[] extraSections) {
|
public MethodBodyHeader decrypt(uint bodyOffset, out byte[] code, out byte[] extraSections) {
|
||||||
peImage.Reader.BaseStream.Position = bodyOffset;
|
peImage.Reader.Position = bodyOffset;
|
||||||
var mbHeader = MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections);
|
var mbHeader = MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections);
|
||||||
blowfish.decrypt(code);
|
blowfish.decrypt(code);
|
||||||
return mbHeader;
|
return mbHeader;
|
||||||
|
@ -110,31 +114,31 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
|
|
||||||
// CS 3.0 (could be other versions too)
|
// CS 3.0 (could be other versions too)
|
||||||
class Decrypter30 : DecrypterBase {
|
class Decrypter30 : DecrypterBase {
|
||||||
public Decrypter30(PeImage peImage, CodeHeader codeHeader)
|
public Decrypter30(MyPEImage peImage, CodeHeader codeHeader)
|
||||||
: base(peImage, codeHeader) {
|
: base(peImage, codeHeader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
|
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
|
||||||
peImage.Reader.BaseStream.Position = peImage.rvaToOffset(methodInfo.codeOffs);
|
peImage.Reader.Position = peImage.rvaToOffset(methodInfo.codeOffs);
|
||||||
return MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections);
|
return MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CS 4.0 (could be other versions too)
|
// CS 4.0 (could be other versions too)
|
||||||
class Decrypter40 : DecrypterBase {
|
class Decrypter40 : DecrypterBase {
|
||||||
public Decrypter40(PeImage peImage, CodeHeader codeHeader)
|
public Decrypter40(MyPEImage peImage, CodeHeader codeHeader)
|
||||||
: base(peImage, codeHeader) {
|
: base(peImage, codeHeader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
|
public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) {
|
||||||
peImage.Reader.BaseStream.Position = endOfMetadata + methodInfo.codeOffs;
|
peImage.Reader.Position = endOfMetadata + methodInfo.codeOffs;
|
||||||
return MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections);
|
return MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CS 4.5 (could be other versions too)
|
// CS 4.5 (could be other versions too)
|
||||||
class Decrypter45 : DecrypterBase {
|
class Decrypter45 : DecrypterBase {
|
||||||
public Decrypter45(PeImage peImage, CodeHeader codeHeader)
|
public Decrypter45(MyPEImage peImage, CodeHeader codeHeader)
|
||||||
: base(peImage, codeHeader) {
|
: base(peImage, codeHeader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +157,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
class Decrypter5 : DecrypterBase {
|
class Decrypter5 : DecrypterBase {
|
||||||
readonly uint codeHeaderSize;
|
readonly uint codeHeaderSize;
|
||||||
|
|
||||||
public Decrypter5(PeImage peImage, CodeHeader codeHeader, uint codeHeaderSize)
|
public Decrypter5(MyPEImage peImage, CodeHeader codeHeader, uint codeHeaderSize)
|
||||||
: base(peImage, codeHeader) {
|
: base(peImage, codeHeader) {
|
||||||
this.codeHeaderSize = codeHeaderSize;
|
this.codeHeaderSize = codeHeaderSize;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +178,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
class ProDecrypter : DecrypterBase {
|
class ProDecrypter : DecrypterBase {
|
||||||
readonly uint[] key = new uint[4];
|
readonly uint[] key = new uint[4];
|
||||||
|
|
||||||
public ProDecrypter(PeImage peImage, CodeHeader codeHeader)
|
public ProDecrypter(MyPEImage peImage, CodeHeader codeHeader)
|
||||||
: base(peImage, codeHeader) {
|
: base(peImage, codeHeader) {
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
key[i] = be_readUInt32(codeHeader.decryptionKey, i * 4);
|
key[i] = be_readUInt32(codeHeader.decryptionKey, i * 4);
|
||||||
|
@ -222,7 +226,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
interface ICsHeader {
|
interface ICsHeader {
|
||||||
IDecrypter createDecrypter();
|
IDecrypter createDecrypter();
|
||||||
List<MethodInfo> getMethodInfos(uint codeHeaderOffset);
|
List<MethodInfo> getMethodInfos(uint codeHeaderOffset);
|
||||||
void patchMethodDefTable(MetadataType methodDefTable, IList<MethodInfo> methodInfos);
|
void patchMethodTable(MDTable methodDefTable, IList<MethodInfo> methodInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class CsHeaderBase : ICsHeader {
|
abstract class CsHeaderBase : ICsHeader {
|
||||||
|
@ -236,7 +240,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
|
|
||||||
public abstract IDecrypter createDecrypter();
|
public abstract IDecrypter createDecrypter();
|
||||||
|
|
||||||
public virtual void patchMethodDefTable(MetadataType methodDefTable, IList<MethodInfo> methodInfos) {
|
public virtual void patchMethodTable(MDTable methodDefTable, IList<MethodInfo> methodInfos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract List<MethodInfo> getMethodInfos(uint codeHeaderOffset);
|
public abstract List<MethodInfo> getMethodInfos(uint codeHeaderOffset);
|
||||||
|
@ -347,10 +351,10 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
return getMethodInfos4(codeHeaderOffset);
|
return getMethodInfos4(codeHeaderOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void patchMethodDefTable(MetadataType methodDefTable, IList<MethodInfo> methodInfos) {
|
public override void patchMethodTable(MDTable methodDefTable, IList<MethodInfo> methodInfos) {
|
||||||
uint offset = methodDefTable.fileOffset - methodDefTable.totalSize;
|
uint offset = (uint)methodDefTable.StartOffset - methodDefTable.RowSize;
|
||||||
foreach (var methodInfo in methodInfos) {
|
foreach (var methodInfo in methodInfos) {
|
||||||
offset += methodDefTable.totalSize;
|
offset += methodDefTable.RowSize;
|
||||||
if (methodInfo.flags == 0 || methodInfo.codeOffs == 0)
|
if (methodInfo.flags == 0 || methodInfo.codeOffs == 0)
|
||||||
continue;
|
continue;
|
||||||
uint rva = methodsDecrypter.peImage.offsetReadUInt32(offset);
|
uint rva = methodsDecrypter.peImage.offsetReadUInt32(offset);
|
||||||
|
@ -370,7 +374,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
V52, // 5.2+ (or maybe 5.1+)
|
V52, // 5.2+ (or maybe 5.1+)
|
||||||
}
|
}
|
||||||
|
|
||||||
List<CsHeaderVersion> getCsHeaderVersions(uint codeHeaderOffset, MetadataType methodDefTable) {
|
List<CsHeaderVersion> getCsHeaderVersions(uint codeHeaderOffset, MDTable methodDefTable) {
|
||||||
if (sigType == SigType.Old)
|
if (sigType == SigType.Old)
|
||||||
return new List<CsHeaderVersion> { CsHeaderVersion.V10 };
|
return new List<CsHeaderVersion> { CsHeaderVersion.V10 };
|
||||||
if (!isOldHeader(methodDefTable))
|
if (!isOldHeader(methodDefTable))
|
||||||
|
@ -408,10 +412,10 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isOldHeader(MetadataType methodDefTable) {
|
bool isOldHeader(MDTable methodDefTable) {
|
||||||
if (methodDefTable.totalSize != codeHeader.methodDefElemSize)
|
if (methodDefTable.RowSize != codeHeader.methodDefElemSize)
|
||||||
return true;
|
return true;
|
||||||
if (methodDefTable.fileOffset - peImage.rvaToOffset(peImage.Cor20Header.metadataDirectory.virtualAddress) != codeHeader.methodDefTableOffset)
|
if ((uint)methodDefTable.StartOffset - peImage.rvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress) != codeHeader.methodDefTableOffset)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -434,7 +438,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool decrypt(PeImage peImage, ModuleDefMD module, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) {
|
public bool decrypt(MyPEImage peImage, ModuleDefMD module, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) {
|
||||||
this.peImage = peImage;
|
this.peImage = peImage;
|
||||||
this.csRtType = csRtType;
|
this.csRtType = csRtType;
|
||||||
this.module = module;
|
this.module = module;
|
||||||
|
@ -444,9 +448,9 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
case DecryptResult.NotEncrypted: return false;
|
case DecryptResult.NotEncrypted: return false;
|
||||||
|
|
||||||
case DecryptResult.Error:
|
case DecryptResult.Error:
|
||||||
Logger.w("Using dynamic method decryption");
|
Logger.n("Using dynamic method decryption");
|
||||||
byte[] moduleCctorBytes = getModuleCctorBytes(csRtType);
|
byte[] moduleCctorBytes = getModuleCctorBytes(csRtType);
|
||||||
dumpedMethods = de4dot.code.deobfuscators.MethodsDecrypter.decrypt(module.Location, moduleCctorBytes);
|
dumpedMethods = de4dot.code.deobfuscators.MethodsDecrypter.decrypt(module, moduleCctorBytes);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -469,27 +473,27 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
return moduleCctorBytes;
|
return moduleCctorBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint getCodeHeaderOffset(PeImage peImage) {
|
static uint getCodeHeaderOffset(MyPEImage peImage) {
|
||||||
return peImage.rvaToOffset(peImage.Cor20Header.metadataDirectory.virtualAddress + peImage.Cor20Header.metadataDirectory.size);
|
return peImage.rvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress + peImage.Cor20Header.MetaData.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static string[] sections = new string[] {
|
static string[] sections = new string[] {
|
||||||
".text", ".rsrc", ".data", ".rdata",
|
".text", ".rsrc", ".data", ".rdata",
|
||||||
};
|
};
|
||||||
static uint getOldCodeHeaderOffset(PeImage peImage) {
|
static uint getOldCodeHeaderOffset(MyPEImage peImage) {
|
||||||
var sect = getLastOf(peImage, sections);
|
var sect = getLastOf(peImage, sections);
|
||||||
if (sect == null || sect.virtualSize < 0x100)
|
if (sect == null || sect.VirtualSize < 0x100)
|
||||||
return 0;
|
return 0;
|
||||||
return peImage.rvaToOffset(sect.virtualAddress + sect.virtualSize - 0x100);
|
return peImage.rvaToOffset((uint)sect.VirtualAddress + sect.VirtualSize - 0x100);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SectionHeader getLastOf(PeImage peImage, string[] sections) {
|
static ImageSectionHeader getLastOf(MyPEImage peImage, string[] sections) {
|
||||||
SectionHeader sect = null;
|
ImageSectionHeader sect = null;
|
||||||
foreach (var name in sections) {
|
foreach (var name in sections) {
|
||||||
var sect2 = peImage.findSection(name);
|
var sect2 = peImage.findSection(name);
|
||||||
if (sect2 == null)
|
if (sect2 == null)
|
||||||
continue;
|
continue;
|
||||||
if (sect == null || sect2.virtualAddress > sect.virtualAddress)
|
if (sect == null || sect2.VirtualAddress > sect.VirtualAddress)
|
||||||
sect = sect2;
|
sect = sect2;
|
||||||
}
|
}
|
||||||
return sect;
|
return sect;
|
||||||
|
@ -500,8 +504,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
if (sigType == SigType.Unknown)
|
if (sigType == SigType.Unknown)
|
||||||
return DecryptResult.NotEncrypted;
|
return DecryptResult.NotEncrypted;
|
||||||
|
|
||||||
var metadataTables = peImage.Cor20Header.createMetadataTables();
|
var methodDefTable = peImage.DotNetFile.MetaData.TablesStream.MethodTable;
|
||||||
var methodDefTable = metadataTables.getMetadataType(MetadataIndex.iMethodDef);
|
|
||||||
|
|
||||||
foreach (var version in getCsHeaderVersions(codeHeaderOffset, methodDefTable)) {
|
foreach (var version in getCsHeaderVersions(codeHeaderOffset, methodDefTable)) {
|
||||||
try {
|
try {
|
||||||
|
@ -534,66 +537,44 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
return codeHeaderOffset;
|
return codeHeaderOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decryptMethodsOld(MetadataType methodDefTable, ref DumpedMethods dumpedMethods) {
|
void decryptMethodsOld(MDTable methodDefTable, ref DumpedMethods dumpedMethods) {
|
||||||
dumpedMethods = new DumpedMethods();
|
dumpedMethods = new DumpedMethods();
|
||||||
uint offset = methodDefTable.fileOffset;
|
|
||||||
var decrypter = new Decrypter10(peImage, codeHeader.decryptionKey);
|
var decrypter = new Decrypter10(peImage, codeHeader.decryptionKey);
|
||||||
for (int i = 0; i < methodDefTable.rows; i++, offset += methodDefTable.totalSize) {
|
for (uint rid = 1; rid <= methodDefTable.Rows; rid++) {
|
||||||
var dm = new DumpedMethod();
|
var dm = new DumpedMethod();
|
||||||
dm.token = 0x06000001 + (uint)i;
|
|
||||||
|
|
||||||
var method = (MethodDef)module.ResolveMethod(MDToken.ToRID(dm.token));
|
var method = (MethodDef)module.ResolveMethod(rid);
|
||||||
if (method == null || method.DeclaringType == DotNetUtils.getModuleType(module))
|
if (method == null || method.DeclaringType == module.GlobalType)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint rva = peImage.offsetReadUInt32(offset + (uint)methodDefTable.fields[0].offset);
|
peImage.readMethodTableRowTo(dm, rid);
|
||||||
if (rva == 0)
|
if (dm.mdRVA == 0)
|
||||||
continue;
|
continue;
|
||||||
uint bodyOffset = peImage.rvaToOffset(rva);
|
uint bodyOffset = peImage.rvaToOffset(dm.mdRVA);
|
||||||
dm.mdRVA = peImage.offsetRead(offset + (uint)methodDefTable.fields[0].offset, methodDefTable.fields[0].size);
|
|
||||||
dm.mdImplFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[1].offset);
|
|
||||||
dm.mdFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[2].offset);
|
|
||||||
dm.mdName = peImage.offsetRead(offset + (uint)methodDefTable.fields[3].offset, methodDefTable.fields[3].size);
|
|
||||||
dm.mdSignature = peImage.offsetRead(offset + (uint)methodDefTable.fields[4].offset, methodDefTable.fields[4].size);
|
|
||||||
dm.mdParamList = peImage.offsetRead(offset + (uint)methodDefTable.fields[5].offset, methodDefTable.fields[5].size);
|
|
||||||
|
|
||||||
var mbHeader = decrypter.decrypt(bodyOffset, out dm.code, out dm.extraSections);
|
var mbHeader = decrypter.decrypt(bodyOffset, out dm.code, out dm.extraSections);
|
||||||
dm.mhFlags = mbHeader.flags;
|
peImage.updateMethodHeaderInfo(dm, mbHeader);
|
||||||
dm.mhMaxStack = mbHeader.maxStack;
|
|
||||||
dm.mhCodeSize = (uint)dm.code.Length;
|
|
||||||
dm.mhLocalVarSigTok = mbHeader.localVarSigTok;
|
|
||||||
|
|
||||||
dumpedMethods.add(dm);
|
dumpedMethods.add(dm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void decryptMethods(uint codeHeaderOffset, MetadataType methodDefTable, ICsHeader csHeader, ref DumpedMethods dumpedMethods) {
|
void decryptMethods(uint codeHeaderOffset, MDTable methodDefTable, ICsHeader csHeader, ref DumpedMethods dumpedMethods) {
|
||||||
var methodInfos = csHeader.getMethodInfos(codeHeaderOffset);
|
var methodInfos = csHeader.getMethodInfos(codeHeaderOffset);
|
||||||
csHeader.patchMethodDefTable(methodDefTable, methodInfos);
|
csHeader.patchMethodTable(methodDefTable, methodInfos);
|
||||||
|
|
||||||
dumpedMethods = new DumpedMethods();
|
dumpedMethods = new DumpedMethods();
|
||||||
uint offset = methodDefTable.fileOffset;
|
|
||||||
decrypter = csHeader.createDecrypter();
|
decrypter = csHeader.createDecrypter();
|
||||||
for (int i = 0; i < methodInfos.Count; i++, offset += methodDefTable.totalSize) {
|
for (uint rid = 1; rid <= (uint)methodInfos.Count; rid++) {
|
||||||
var methodInfo = methodInfos[i];
|
var methodInfo = methodInfos[(int)rid - 1];
|
||||||
if (methodInfo.codeOffs == 0)
|
if (methodInfo.codeOffs == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var dm = new DumpedMethod();
|
var dm = new DumpedMethod();
|
||||||
dm.token = 0x06000001 + (uint)i;
|
peImage.readMethodTableRowTo(dm, rid);
|
||||||
|
|
||||||
dm.mdRVA = peImage.offsetRead(offset + (uint)methodDefTable.fields[0].offset, methodDefTable.fields[0].size);
|
|
||||||
dm.mdImplFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[1].offset);
|
|
||||||
dm.mdFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[2].offset);
|
|
||||||
dm.mdName = peImage.offsetRead(offset + (uint)methodDefTable.fields[3].offset, methodDefTable.fields[3].size);
|
|
||||||
dm.mdSignature = peImage.offsetRead(offset + (uint)methodDefTable.fields[4].offset, methodDefTable.fields[4].size);
|
|
||||||
dm.mdParamList = peImage.offsetRead(offset + (uint)methodDefTable.fields[5].offset, methodDefTable.fields[5].size);
|
|
||||||
|
|
||||||
var mbHeader = decrypter.decrypt(methodInfo, out dm.code, out dm.extraSections);
|
var mbHeader = decrypter.decrypt(methodInfo, out dm.code, out dm.extraSections);
|
||||||
dm.mhFlags = mbHeader.flags;
|
peImage.updateMethodHeaderInfo(dm, mbHeader);
|
||||||
dm.mhMaxStack = mbHeader.maxStack;
|
|
||||||
dm.mhCodeSize = (uint)dm.code.Length;
|
|
||||||
dm.mhLocalVarSigTok = mbHeader.localVarSigTok;
|
|
||||||
|
|
||||||
dumpedMethods.add(dm);
|
dumpedMethods.add(dm);
|
||||||
}
|
}
|
||||||
|
@ -622,7 +603,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
return getSigType(signature) != SigType.Unknown;
|
return getSigType(signature) != SigType.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool detect(PeImage peImage) {
|
public static bool detect(MyPEImage peImage) {
|
||||||
try {
|
try {
|
||||||
uint codeHeaderOffset = getCodeHeaderOffset(peImage);
|
uint codeHeaderOffset = getCodeHeaderOffset(peImage);
|
||||||
if (isValidSignature(peImage.offsetReadBytes(codeHeaderOffset, 16)))
|
if (isValidSignature(peImage.offsetReadBytes(codeHeaderOffset, 16)))
|
||||||
|
|
|
@ -28,10 +28,10 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
IDeobfuscatorContext deobfuscatorContext;
|
IDeobfuscatorContext deobfuscatorContext;
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
EmbeddedResource resource;
|
EmbeddedResource resource;
|
||||||
AssemblyRef vmAssemblyReference;
|
AssemblyRef vmAssemblyRef;
|
||||||
|
|
||||||
public bool Detected {
|
public bool Detected {
|
||||||
get { return resource != null && vmAssemblyReference != null; }
|
get { return resource != null && vmAssemblyRef != null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmbeddedResource Resource {
|
public EmbeddedResource Resource {
|
||||||
|
@ -48,16 +48,16 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
if (oldOne.resource != null)
|
if (oldOne.resource != null)
|
||||||
this.resource = (EmbeddedResource)module.Resources[oldOne.module.Resources.IndexOf(oldOne.resource)];
|
this.resource = (EmbeddedResource)module.Resources[oldOne.module.Resources.IndexOf(oldOne.resource)];
|
||||||
if (oldOne.vmAssemblyReference != null)
|
if (oldOne.vmAssemblyRef != null)
|
||||||
this.vmAssemblyReference = module.ResolveAssemblyRef(oldOne.vmAssemblyReference.Rid);
|
this.vmAssemblyRef = module.ResolveAssemblyRef(oldOne.vmAssemblyRef.Rid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void find() {
|
public void find() {
|
||||||
resource = findCsvmResource();
|
resource = findCsvmResource();
|
||||||
vmAssemblyReference = findVmAssemblyReference();
|
vmAssemblyRef = findVmAssemblyRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyRef findVmAssemblyReference() {
|
AssemblyRef findVmAssemblyRef() {
|
||||||
foreach (var memberRef in module.GetMemberRefs()) {
|
foreach (var memberRef in module.GetMemberRefs()) {
|
||||||
var sig = memberRef.MethodSig;
|
var sig = memberRef.MethodSig;
|
||||||
if (sig == null)
|
if (sig == null)
|
||||||
|
@ -132,7 +132,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
}
|
}
|
||||||
|
|
||||||
VmOpCodeHandlerDetector getVmOpCodeHandlerDetector() {
|
VmOpCodeHandlerDetector getVmOpCodeHandlerDetector() {
|
||||||
var vmFilename = vmAssemblyReference.Name + ".dll";
|
var vmFilename = vmAssemblyRef.Name + ".dll";
|
||||||
var vmModulePath = Path.Combine(Path.GetDirectoryName(module.Location), vmFilename);
|
var vmModulePath = Path.Combine(Path.GetDirectoryName(module.Location), vmFilename);
|
||||||
Logger.v("CSVM filename: {0}", vmFilename);
|
Logger.v("CSVM filename: {0}", vmFilename);
|
||||||
|
|
||||||
|
|
|
@ -234,12 +234,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
throw new ApplicationException("Invalid number of locals");
|
throw new ApplicationException("Invalid number of locals");
|
||||||
|
|
||||||
for (int i = 0; i < numLocals; i++)
|
for (int i = 0; i < numLocals; i++)
|
||||||
locals.Add(new Local(readTypeReference(reader)));
|
locals.Add(new Local(readTypeRef(reader)));
|
||||||
|
|
||||||
return locals;
|
return locals;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeSig readTypeReference(BinaryReader reader) {
|
TypeSig readTypeRef(BinaryReader reader) {
|
||||||
var etype = (ElementType)reader.ReadInt32();
|
var etype = (ElementType)reader.ReadInt32();
|
||||||
switch (etype) {
|
switch (etype) {
|
||||||
case ElementType.Void: return module.CorLibTypes.Void;
|
case ElementType.Void: return module.CorLibTypes.Void;
|
||||||
|
@ -345,7 +345,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
|
|
||||||
object fixOperand(IList<Instruction> instrs, Instruction instr, IVmOperand vmOperand) {
|
object fixOperand(IList<Instruction> instrs, Instruction instr, IVmOperand vmOperand) {
|
||||||
if (vmOperand is TokenOperand)
|
if (vmOperand is TokenOperand)
|
||||||
return getMemberReference(((TokenOperand)vmOperand).token);
|
return getMemberRef(((TokenOperand)vmOperand).token);
|
||||||
|
|
||||||
if (vmOperand is TargetDisplOperand)
|
if (vmOperand is TargetDisplOperand)
|
||||||
return getInstruction(instrs, instr, ((TargetDisplOperand)vmOperand).displacement);
|
return getInstruction(instrs, instr, ((TargetDisplOperand)vmOperand).displacement);
|
||||||
|
@ -387,7 +387,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
return fieldRef;
|
return fieldRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
ITokenOperand getMemberReference(int token) {
|
ITokenOperand getMemberRef(int token) {
|
||||||
var memberRef = module.ResolveToken(token) as ITokenOperand;
|
var memberRef = module.ResolveToken(token) as ITokenOperand;
|
||||||
if (memberRef == null)
|
if (memberRef == null)
|
||||||
throw new ApplicationException(string.Format("Could not find member ref: {0:X8}", token));
|
throw new ApplicationException(string.Format("Could not find member ref: {0:X8}", token));
|
||||||
|
|
|
@ -75,7 +75,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
}
|
}
|
||||||
|
|
||||||
static internal IEnumerable<FieldDef> getFields(TypeDef type) {
|
static internal IEnumerable<FieldDef> getFields(TypeDef type) {
|
||||||
var typeFields = new FieldDefinitionAndDeclaringTypeDict<FieldDef>();
|
var typeFields = new FieldDefAndDeclaringTypeDict<FieldDef>();
|
||||||
foreach (var field in type.Fields)
|
foreach (var field in type.Fields)
|
||||||
typeFields.add(field, field);
|
typeFields.add(field, field);
|
||||||
var realFields = new Dictionary<FieldDef, bool>();
|
var realFields = new Dictionary<FieldDef, bool>();
|
||||||
|
|
|
@ -52,15 +52,15 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
string[] strings;
|
string[] strings;
|
||||||
AssemblyRef[] assemblyNames;
|
AssemblyRef[] assemblyNames;
|
||||||
Dictionary<string, int> methodOffsets;
|
Dictionary<string, int> methodOffsets;
|
||||||
List<TypeSig> typeReferences;
|
List<TypeSig> typeRefs;
|
||||||
MemberReferenceConverter memberReferenceConverter;
|
MemberRefConverter memberRefConverter;
|
||||||
IDeobfuscatorContext deobfuscatorContext;
|
IDeobfuscatorContext deobfuscatorContext;
|
||||||
|
|
||||||
public ImageReader(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module, byte[] data) {
|
public ImageReader(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module, byte[] data) {
|
||||||
this.deobfuscatorContext = deobfuscatorContext;
|
this.deobfuscatorContext = deobfuscatorContext;
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.reader = MemoryImageStream.Create(data);
|
this.reader = MemoryImageStream.Create(data);
|
||||||
this.memberReferenceConverter = new MemberReferenceConverter(module);
|
this.memberRefConverter = new MemberRefConverter(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool initialize() {
|
public bool initialize() {
|
||||||
|
@ -86,26 +86,26 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
void initializeV10() {
|
void initializeV10() {
|
||||||
reader.ReadInt16();
|
reader.ReadInt16();
|
||||||
int methodNamesOffset = (int)reader.ReadInt64();
|
int methodNamesOffset = (int)reader.ReadInt64();
|
||||||
int typeReferencesOffset = (int)reader.ReadInt64();
|
int typeRefsOffset = (int)reader.ReadInt64();
|
||||||
int assemblyReferencesOffset = (int)reader.ReadInt64();
|
int assemblyRefsOffset = (int)reader.ReadInt64();
|
||||||
int stringsOffset = (int)reader.ReadInt64();
|
int stringsOffset = (int)reader.ReadInt64();
|
||||||
|
|
||||||
initializeStrings(stringsOffset);
|
initializeStrings(stringsOffset);
|
||||||
initializeAssemblyNames(assemblyReferencesOffset);
|
initializeAssemblyNames(assemblyRefsOffset);
|
||||||
initializeMethodNames(methodNamesOffset);
|
initializeMethodNames(methodNamesOffset);
|
||||||
initializeTypeReferences(typeReferencesOffset);
|
initializeTypeRefs(typeRefsOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeV55() {
|
void initializeV55() {
|
||||||
int methodNamesOffset = (int)reader.ReadInt64() ^ METADATA_SIG;
|
int methodNamesOffset = (int)reader.ReadInt64() ^ METADATA_SIG;
|
||||||
int typeReferencesOffset = (int)reader.ReadInt64() ^ (METADATA_SIG << 1);
|
int typeRefsOffset = (int)reader.ReadInt64() ^ (METADATA_SIG << 1);
|
||||||
int assemblyReferencesOffset = (int)reader.ReadInt64() ^ ((METADATA_SIG << 1) + 1);
|
int assemblyRefsOffset = (int)reader.ReadInt64() ^ ((METADATA_SIG << 1) + 1);
|
||||||
int stringsOffset = (int)reader.ReadInt64() ^ (((METADATA_SIG << 1) + 1) << 1);
|
int stringsOffset = (int)reader.ReadInt64() ^ (((METADATA_SIG << 1) + 1) << 1);
|
||||||
|
|
||||||
initializeStrings(stringsOffset);
|
initializeStrings(stringsOffset);
|
||||||
initializeAssemblyNames(assemblyReferencesOffset);
|
initializeAssemblyNames(assemblyRefsOffset);
|
||||||
initializeMethodNames(methodNamesOffset);
|
initializeMethodNames(methodNamesOffset);
|
||||||
initializeTypeReferences(typeReferencesOffset);
|
initializeTypeRefs(typeRefsOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restore(string name, MethodDef method) {
|
public void restore(string name, MethodDef method) {
|
||||||
|
@ -138,11 +138,11 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
body.ExceptionHandlers.Add(eh);
|
body.ExceptionHandlers.Add(eh);
|
||||||
}
|
}
|
||||||
|
|
||||||
BabelMethodDefinition getMethod(string name) {
|
BabelMethodDef getMethod(string name) {
|
||||||
int offset = methodOffsets[name];
|
int offset = methodOffsets[name];
|
||||||
methodOffsets.Remove(name);
|
methodOffsets.Remove(name);
|
||||||
reader.Position = offset;
|
reader.Position = offset;
|
||||||
return new MethodDefinitionReader(this, reader).read();
|
return new MethodDefReader(this, reader).read();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string readString() {
|
public string readString() {
|
||||||
|
@ -150,7 +150,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeSig readTypeSig() {
|
public TypeSig readTypeSig() {
|
||||||
return typeReferences[readVariableLengthInt32()];
|
return typeRefs[readVariableLengthInt32()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeSig[] readTypeSigs() {
|
public TypeSig[] readTypeSigs() {
|
||||||
|
@ -160,7 +160,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
return refs;
|
return refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IField readFieldReference() {
|
public IField readFieldRef() {
|
||||||
var name = readString();
|
var name = readString();
|
||||||
var declaringType = readTypeSig();
|
var declaringType = readTypeSig();
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
Utils.removeNewlines(declaringType)));
|
Utils.removeNewlines(declaringType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return memberReferenceConverter.convert(fields[0]);
|
return memberRefConverter.convert(fields[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<FieldDef> getFields(TypeDef type, string name) {
|
static List<FieldDef> getFields(TypeDef type, string name) {
|
||||||
|
@ -180,10 +180,10 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
return new List<FieldDef>(type.FindFields(name));
|
return new List<FieldDef>(type.FindFields(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMethod readMethodReference() {
|
public IMethod readMethodRef() {
|
||||||
var babelMethodRef = new MethodReferenceReader(this, reader).read();
|
var babelMethodRef = new MethodRefReader(this, reader).read();
|
||||||
|
|
||||||
var method = getMethodReference(babelMethodRef);
|
var method = getMethodRef(babelMethodRef);
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
throw new ApplicationException(string.Format("Could not find method '{0}' in type '{1}'",
|
throw new ApplicationException(string.Format("Could not find method '{0}' in type '{1}'",
|
||||||
Utils.removeNewlines(babelMethodRef.Name),
|
Utils.removeNewlines(babelMethodRef.Name),
|
||||||
|
@ -198,7 +198,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
return module.UpdateRowId(mr);
|
return module.UpdateRowId(mr);
|
||||||
}
|
}
|
||||||
|
|
||||||
IMethod getMethodReference(BabelMethodreference babelMethodRef) {
|
IMethod getMethodRef(BabelMethodreference babelMethodRef) {
|
||||||
var declaringType = resolve(babelMethodRef.DeclaringType);
|
var declaringType = resolve(babelMethodRef.DeclaringType);
|
||||||
if (declaringType == null)
|
if (declaringType == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -221,10 +221,10 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
foreach (var method in declaringType.Methods) {
|
foreach (var method in declaringType.Methods) {
|
||||||
if (compareMethod(GenericArgsSubstitutor.create(method, gis, gim), babelMethodRef)) {
|
if (compareMethod(GenericArgsSubstitutor.create(method, gis, gim), babelMethodRef)) {
|
||||||
if (!babelMethodRef.IsGenericMethod)
|
if (!babelMethodRef.IsGenericMethod)
|
||||||
methods.Add(memberReferenceConverter.convert(method));
|
methods.Add(memberRefConverter.convert(method));
|
||||||
else {
|
else {
|
||||||
var gim2 = new GenericInstMethodSig(babelMethodRef.GenericArguments);
|
var gim2 = new GenericInstMethodSig(babelMethodRef.GenericArguments);
|
||||||
var ms = module.UpdateRowId(new MethodSpecUser(memberReferenceConverter.convert(method), gim2));
|
var ms = module.UpdateRowId(new MethodSpecUser(memberRefConverter.convert(method), gim2));
|
||||||
methods.Add(ms);
|
methods.Add(ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,39 +329,39 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeTypeReferences(int headerOffset) {
|
void initializeTypeRefs(int headerOffset) {
|
||||||
reader.Position = headerOffset;
|
reader.Position = headerOffset;
|
||||||
if (reader.ReadInt32() != TYPEREFS_SIG)
|
if (reader.ReadInt32() != TYPEREFS_SIG)
|
||||||
throw new ApplicationException("Invalid typerefs sig");
|
throw new ApplicationException("Invalid typerefs sig");
|
||||||
|
|
||||||
int numTypeRefs = reader.ReadInt32();
|
int numTypeRefs = reader.ReadInt32();
|
||||||
typeReferences = new List<TypeSig>(numTypeRefs + 1);
|
typeRefs = new List<TypeSig>(numTypeRefs + 1);
|
||||||
typeReferences.Add(null);
|
typeRefs.Add(null);
|
||||||
var genericArgFixes = new Dictionary<GenericInstSig, List<int>>();
|
var genericArgFixes = new Dictionary<GenericInstSig, List<int>>();
|
||||||
for (int i = 0; i < numTypeRefs; i++) {
|
for (int i = 0; i < numTypeRefs; i++) {
|
||||||
TypeId typeId = (TypeId)reader.ReadByte();
|
TypeId typeId = (TypeId)reader.ReadByte();
|
||||||
switch (typeId) {
|
switch (typeId) {
|
||||||
case TypeId.TypeRef:
|
case TypeId.TypeRef:
|
||||||
typeReferences.Add(readTypeRef());
|
typeRefs.Add(readTypeRef());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TypeId.GenericInstance:
|
case TypeId.GenericInstance:
|
||||||
List<int> genericArgs;
|
List<int> genericArgs;
|
||||||
var git = readGenericInstanceType(out genericArgs);
|
var git = readGenericInstanceType(out genericArgs);
|
||||||
typeReferences.Add(git);
|
typeRefs.Add(git);
|
||||||
genericArgFixes[git] = genericArgs;
|
genericArgFixes[git] = genericArgs;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TypeId.Pointer:
|
case TypeId.Pointer:
|
||||||
typeReferences.Add(readPointerType());
|
typeRefs.Add(readPointerType());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TypeId.Array:
|
case TypeId.Array:
|
||||||
typeReferences.Add(readArrayType());
|
typeRefs.Add(readArrayType());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TypeId.ByRef:
|
case TypeId.ByRef:
|
||||||
typeReferences.Add(readByReferenceType());
|
typeRefs.Add(readByRefType());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -372,7 +372,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
foreach (var kv in genericArgFixes) {
|
foreach (var kv in genericArgFixes) {
|
||||||
var git = kv.Key;
|
var git = kv.Key;
|
||||||
foreach (var typeNum in kv.Value)
|
foreach (var typeNum in kv.Value)
|
||||||
git.GenericArguments.Add(typeReferences[typeNum]);
|
git.GenericArguments.Add(typeRefs[typeNum]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,13 +381,13 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
parseReflectionTypeName(readString(), out ns, out name);
|
parseReflectionTypeName(readString(), out ns, out name);
|
||||||
var asmRef = assemblyNames[readVariableLengthInt32()];
|
var asmRef = assemblyNames[readVariableLengthInt32()];
|
||||||
var declaringType = readTypeSig();
|
var declaringType = readTypeSig();
|
||||||
var typeReference = new TypeRefUser(module, ns, name);
|
var typeRef = new TypeRefUser(module, ns, name);
|
||||||
if (declaringType != null)
|
if (declaringType != null)
|
||||||
typeReference.ResolutionScope = getTypeRef(declaringType);
|
typeRef.ResolutionScope = getTypeRef(declaringType);
|
||||||
else
|
else
|
||||||
typeReference.ResolutionScope = asmRef;
|
typeRef.ResolutionScope = asmRef;
|
||||||
|
|
||||||
return memberReferenceConverter.convert(typeReference);
|
return memberRefConverter.convert(typeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeRef getTypeRef(TypeSig type) {
|
TypeRef getTypeRef(TypeSig type) {
|
||||||
|
@ -469,7 +469,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
return new ArraySig(typeSig, rank);
|
return new ArraySig(typeSig, rank);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByRefSig readByReferenceType() {
|
ByRefSig readByRefType() {
|
||||||
return new ByRefSig(readTypeSig());
|
return new ByRefSig(readTypeSig());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,14 @@ using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
// Converts type references/definitions in one module to this module
|
// Converts type references/definitions in one module to this module
|
||||||
class MemberReferenceConverter {
|
class MemberRefConverter {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
|
|
||||||
public ModuleDefMD Module {
|
public ModuleDefMD Module {
|
||||||
get { return module; }
|
get { return module; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MemberReferenceConverter(ModuleDefMD module) {
|
public MemberRefConverter(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
|
|
||||||
public IField convert(IField fieldRef) {
|
public IField convert(IField fieldRef) {
|
||||||
if (isInOurModule(fieldRef))
|
if (isInOurModule(fieldRef))
|
||||||
return tryGetFieldDefinition(fieldRef);
|
return tryGetFieldDef(fieldRef);
|
||||||
return createImporter().Import(fieldRef);
|
return createImporter().Import(fieldRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,11 +68,11 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
if (!(methodRef is MemberRef || methodRef is MethodDef) || methodRef.MethodSig == null)
|
if (!(methodRef is MemberRef || methodRef is MethodDef) || methodRef.MethodSig == null)
|
||||||
throw new ApplicationException("Invalid method reference type");
|
throw new ApplicationException("Invalid method reference type");
|
||||||
if (isInOurModule(methodRef))
|
if (isInOurModule(methodRef))
|
||||||
return (IMethodDefOrRef)tryGetMethodDefinition(methodRef);
|
return (IMethodDefOrRef)tryGetMethodDef(methodRef);
|
||||||
return (IMethodDefOrRef)createImporter().Import(methodRef);
|
return (IMethodDefOrRef)createImporter().Import(methodRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IField tryGetFieldDefinition(IField fieldRef) {
|
public IField tryGetFieldDef(IField fieldRef) {
|
||||||
var fieldDef = fieldRef as FieldDef;
|
var fieldDef = fieldRef as FieldDef;
|
||||||
if (fieldDef != null)
|
if (fieldDef != null)
|
||||||
return fieldDef;
|
return fieldDef;
|
||||||
|
@ -83,7 +83,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
return DotNetUtils.getField(declaringType, fieldRef);
|
return DotNetUtils.getField(declaringType, fieldRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMethod tryGetMethodDefinition(IMethod methodRef) {
|
public IMethod tryGetMethodDef(IMethod methodRef) {
|
||||||
var methodDef = methodRef as MethodDef;
|
var methodDef = methodRef as MethodDef;
|
||||||
if (methodDef != null)
|
if (methodDef != null)
|
||||||
return methodDef;
|
return methodDef;
|
||||||
|
|
|
@ -45,11 +45,11 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IField ReadInlineField(Instruction instr) {
|
protected override IField ReadInlineField(Instruction instr) {
|
||||||
return imageReader.readFieldReference();
|
return imageReader.readFieldRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IMethod ReadInlineMethod(Instruction instr) {
|
protected override IMethod ReadInlineMethod(Instruction instr) {
|
||||||
return imageReader.readMethodReference();
|
return imageReader.readMethodRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override MethodSig ReadInlineSig(Instruction instr) {
|
protected override MethodSig ReadInlineSig(Instruction instr) {
|
||||||
|
@ -63,8 +63,8 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
protected override ITokenOperand ReadInlineTok(Instruction instr) {
|
protected override ITokenOperand ReadInlineTok(Instruction instr) {
|
||||||
switch (reader.ReadByte()) {
|
switch (reader.ReadByte()) {
|
||||||
case 0: return imageReader.readTypeSig().ToTypeDefOrRef();
|
case 0: return imageReader.readTypeSig().ToTypeDefOrRef();
|
||||||
case 1: return imageReader.readFieldReference();
|
case 1: return imageReader.readFieldRef();
|
||||||
case 2: return imageReader.readMethodReference();
|
case 2: return imageReader.readMethodRef();
|
||||||
default: throw new ApplicationException("Unknown token type");
|
default: throw new ApplicationException("Unknown token type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BabelMethodDefinition : BabelMethodreference {
|
class BabelMethodDef : BabelMethodreference {
|
||||||
Parameter thisParameter;
|
Parameter thisParameter;
|
||||||
|
|
||||||
public int Flags2 { get; set; }
|
public int Flags2 { get; set; }
|
||||||
|
@ -95,16 +95,16 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MethodReferenceReader {
|
class MethodRefReader {
|
||||||
ImageReader imageReader;
|
ImageReader imageReader;
|
||||||
IBinaryReader reader;
|
IBinaryReader reader;
|
||||||
BabelMethodreference bmr;
|
BabelMethodreference bmr;
|
||||||
|
|
||||||
public MethodReferenceReader(ImageReader imageReader, IBinaryReader reader)
|
public MethodRefReader(ImageReader imageReader, IBinaryReader reader)
|
||||||
: this(imageReader, reader, new BabelMethodreference()) {
|
: this(imageReader, reader, new BabelMethodreference()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReferenceReader(ImageReader imageReader, IBinaryReader reader, BabelMethodreference bmr) {
|
public MethodRefReader(ImageReader imageReader, IBinaryReader reader, BabelMethodreference bmr) {
|
||||||
this.imageReader = imageReader;
|
this.imageReader = imageReader;
|
||||||
this.reader = reader;
|
this.reader = reader;
|
||||||
this.bmr = bmr;
|
this.bmr = bmr;
|
||||||
|
@ -133,19 +133,19 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MethodDefinitionReader {
|
class MethodDefReader {
|
||||||
MethodReferenceReader methodReferenceReader;
|
MethodRefReader methodRefReader;
|
||||||
MethodBodyReader methodBodyReader;
|
MethodBodyReader methodBodyReader;
|
||||||
BabelMethodDefinition bmd;
|
BabelMethodDef bmd;
|
||||||
|
|
||||||
public MethodDefinitionReader(ImageReader imageReader, IBinaryReader reader) {
|
public MethodDefReader(ImageReader imageReader, IBinaryReader reader) {
|
||||||
this.bmd = new BabelMethodDefinition();
|
this.bmd = new BabelMethodDef();
|
||||||
this.methodReferenceReader = new MethodReferenceReader(imageReader, reader, bmd);
|
this.methodRefReader = new MethodRefReader(imageReader, reader, bmd);
|
||||||
this.methodBodyReader = new MethodBodyReader(imageReader, reader);
|
this.methodBodyReader = new MethodBodyReader(imageReader, reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BabelMethodDefinition read() {
|
public BabelMethodDef read() {
|
||||||
methodReferenceReader.read();
|
methodRefReader.read();
|
||||||
methodBodyReader.read(bmd.getRealParameters());
|
methodBodyReader.read(bmd.getRealParameters());
|
||||||
bmd.setBody(methodBodyReader);
|
bmd.setBody(methodBodyReader);
|
||||||
return bmd;
|
return bmd;
|
||||||
|
|
|
@ -25,7 +25,7 @@ using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
class ProxyCallFixer : ProxyCallFixer2 {
|
class ProxyCallFixer : ProxyCallFixer2 {
|
||||||
MethodDefinitionAndDeclaringTypeDict<ProxyCreatorType> methodToType = new MethodDefinitionAndDeclaringTypeDict<ProxyCreatorType>();
|
MethodDefAndDeclaringTypeDict<ProxyCreatorType> methodToType = new MethodDefAndDeclaringTypeDict<ProxyCreatorType>();
|
||||||
|
|
||||||
public ProxyCallFixer(ModuleDefMD module)
|
public ProxyCallFixer(ModuleDefMD module)
|
||||||
: base(module) {
|
: base(module) {
|
||||||
|
|
|
@ -309,7 +309,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReflectionToCecilMethodCreator {
|
class ReflectionToDot10MethodCreator {
|
||||||
MethodDef method;
|
MethodDef method;
|
||||||
List<Instruction> instructions = new List<Instruction>();
|
List<Instruction> instructions = new List<Instruction>();
|
||||||
InstructionEmulator emulator;
|
InstructionEmulator emulator;
|
||||||
|
@ -331,7 +331,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
get { return instructions; }
|
get { return instructions; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReflectionToCecilMethodCreator(MethodDef method) {
|
public ReflectionToDot10MethodCreator(MethodDef method) {
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.emulator = new InstructionEmulator(method);
|
this.emulator = new InstructionEmulator(method);
|
||||||
}
|
}
|
||||||
|
@ -439,7 +439,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
emulator.pop(); // the this ptr
|
emulator.pop(); // the this ptr
|
||||||
addInstruction(new Instruction {
|
addInstruction(new Instruction {
|
||||||
OpCode = opcode,
|
OpCode = opcode,
|
||||||
Operand = createCecilOperand(opcode, operand),
|
Operand = createDot10Operand(opcode, operand),
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object createCecilOperand(OpCode opcode, Value op) {
|
object createDot10Operand(OpCode opcode, Value op) {
|
||||||
if (op is Int32Value)
|
if (op is Int32Value)
|
||||||
return ((Int32Value)op).value;
|
return ((Int32Value)op).value;
|
||||||
if (op is StringValue)
|
if (op is StringValue)
|
||||||
|
@ -470,7 +470,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<Instruction> getOffsetCalcInstructions(MethodDef method) {
|
static List<Instruction> getOffsetCalcInstructions(MethodDef method) {
|
||||||
var creator = new ReflectionToCecilMethodCreator(method);
|
var creator = new ReflectionToDot10MethodCreator(method);
|
||||||
creator.create();
|
creator.create();
|
||||||
var instrs = creator.Instructions;
|
var instrs = creator.Instructions;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.PE;
|
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.CodeFort {
|
namespace de4dot.code.deobfuscators.CodeFort {
|
||||||
public class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
public class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
||||||
|
|
|
@ -25,7 +25,7 @@ using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.CodeFort {
|
namespace de4dot.code.deobfuscators.CodeFort {
|
||||||
class ProxyCallFixer : ProxyCallFixer3 {
|
class ProxyCallFixer : ProxyCallFixer3 {
|
||||||
MethodDefinitionAndDeclaringTypeDict<bool> proxyTargetMethods = new MethodDefinitionAndDeclaringTypeDict<bool>();
|
MethodDefAndDeclaringTypeDict<bool> proxyTargetMethods = new MethodDefAndDeclaringTypeDict<bool>();
|
||||||
TypeDef proxyMethodsType;
|
TypeDef proxyMethodsType;
|
||||||
|
|
||||||
public TypeDef ProxyMethodsType {
|
public TypeDef ProxyMethodsType {
|
||||||
|
|
|
@ -19,11 +19,10 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using dot10.IO;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using dot10.DotNet.Emit;
|
using dot10.DotNet.Emit;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.PE;
|
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.CodeVeil {
|
namespace de4dot.code.deobfuscators.CodeVeil {
|
||||||
class MethodsDecrypter {
|
class MethodsDecrypter {
|
||||||
|
@ -32,23 +31,22 @@ namespace de4dot.code.deobfuscators.CodeVeil {
|
||||||
|
|
||||||
interface IDecrypter {
|
interface IDecrypter {
|
||||||
void initialize(byte[] methodsData);
|
void initialize(byte[] methodsData);
|
||||||
bool decrypt(BinaryReader fileDataReader, DumpedMethod dm);
|
bool decrypt(IBinaryReader fileDataReader, DumpedMethod dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Decrypter : IDecrypter {
|
class Decrypter : IDecrypter {
|
||||||
BinaryReader methodsDataReader;
|
IBinaryReader methodsDataReader;
|
||||||
|
|
||||||
public virtual void initialize(byte[] methodsData) {
|
public virtual void initialize(byte[] methodsData) {
|
||||||
methodsDataReader = new BinaryReader(new MemoryStream(methodsData));
|
methodsDataReader = MemoryImageStream.Create(methodsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool decrypt(BinaryReader fileDataReader, DumpedMethod dm) {
|
public virtual bool decrypt(IBinaryReader fileDataReader, DumpedMethod dm) {
|
||||||
if (fileDataReader.ReadByte() != 0x2A)
|
if (fileDataReader.ReadByte() != 0x2A)
|
||||||
return false; // Not a RET
|
return false; // Not a RET
|
||||||
int methodsDataOffset = DeobUtils.readVariableLengthInt32(fileDataReader);
|
methodsDataReader.Position = fileDataReader.ReadCompressedUInt32();
|
||||||
methodsDataReader.BaseStream.Position = methodsDataOffset;
|
|
||||||
|
|
||||||
dm.mhCodeSize = (uint)DeobUtils.readVariableLengthInt32(methodsDataReader);
|
dm.mhCodeSize = methodsDataReader.ReadCompressedUInt32();
|
||||||
dm.code = methodsDataReader.ReadBytes((int)dm.mhCodeSize);
|
dm.code = methodsDataReader.ReadBytes((int)dm.mhCodeSize);
|
||||||
if ((dm.mhFlags & 8) != 0)
|
if ((dm.mhFlags & 8) != 0)
|
||||||
dm.extraSections = MethodBodyParser.readExtraSections(methodsDataReader);
|
dm.extraSections = MethodBodyParser.readExtraSections(methodsDataReader);
|
||||||
|
@ -126,46 +124,38 @@ namespace de4dot.code.deobfuscators.CodeVeil {
|
||||||
if (decrypter == null)
|
if (decrypter == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var peImage = new PeImage(fileData);
|
using (var peImage = new MyPEImage(fileData)) {
|
||||||
if (peImage.Sections.Length <= 0)
|
if (peImage.Sections.Count <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var methodsData = findMethodsData(peImage, fileData);
|
var methodsData = findMethodsData(peImage, fileData);
|
||||||
if (methodsData == null)
|
if (methodsData == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
decrypter.initialize(methodsData);
|
decrypter.initialize(methodsData);
|
||||||
|
|
||||||
dumpedMethods = createDumpedMethods(peImage, fileData, methodsData);
|
dumpedMethods = createDumpedMethods(peImage, fileData, methodsData);
|
||||||
if (dumpedMethods == null)
|
if (dumpedMethods == null)
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DumpedMethods createDumpedMethods(PeImage peImage, byte[] fileData, byte[] methodsData) {
|
DumpedMethods createDumpedMethods(MyPEImage peImage, byte[] fileData, byte[] methodsData) {
|
||||||
var dumpedMethods = new DumpedMethods();
|
var dumpedMethods = new DumpedMethods();
|
||||||
|
|
||||||
var methodsDataReader = new BinaryReader(new MemoryStream(methodsData));
|
var methodsDataReader = MemoryImageStream.Create(methodsData);
|
||||||
var fileDataReader = new BinaryReader(new MemoryStream(fileData));
|
var fileDataReader = MemoryImageStream.Create(fileData);
|
||||||
|
|
||||||
var metadataTables = peImage.Cor20Header.createMetadataTables();
|
|
||||||
var methodDef = metadataTables.getMetadataType(MetadataIndex.iMethodDef);
|
|
||||||
uint methodDefOffset = methodDef.fileOffset;
|
|
||||||
for (int i = 0; i < methodDef.rows; i++, methodDefOffset += methodDef.totalSize) {
|
|
||||||
uint bodyRva = peImage.offsetReadUInt32(methodDefOffset);
|
|
||||||
if (bodyRva == 0)
|
|
||||||
continue;
|
|
||||||
uint bodyOffset = peImage.rvaToOffset(bodyRva);
|
|
||||||
|
|
||||||
|
var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable;
|
||||||
|
for (uint rid = 1; rid <= methodDef.Rows; rid++) {
|
||||||
var dm = new DumpedMethod();
|
var dm = new DumpedMethod();
|
||||||
dm.token = (uint)(0x06000001 + i);
|
|
||||||
dm.mdRVA = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[0].offset, methodDef.fields[0].size);
|
peImage.readMethodTableRowTo(dm, rid);
|
||||||
dm.mdImplFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[1].offset);
|
if (dm.mdRVA == 0)
|
||||||
dm.mdFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[2].offset);
|
continue;
|
||||||
dm.mdName = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[3].offset, methodDef.fields[3].size);
|
uint bodyOffset = peImage.rvaToOffset(dm.mdRVA);
|
||||||
dm.mdSignature = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[4].offset, methodDef.fields[4].size);
|
|
||||||
dm.mdParamList = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[5].offset, methodDef.fields[5].size);
|
|
||||||
|
|
||||||
byte b = peImage.offsetReadByte(bodyOffset);
|
byte b = peImage.offsetReadByte(bodyOffset);
|
||||||
uint codeOffset;
|
uint codeOffset;
|
||||||
|
@ -187,7 +177,7 @@ namespace de4dot.code.deobfuscators.CodeVeil {
|
||||||
dm.mhLocalVarSigTok = peImage.offsetReadUInt32(bodyOffset + 8);
|
dm.mhLocalVarSigTok = peImage.offsetReadUInt32(bodyOffset + 8);
|
||||||
codeOffset = bodyOffset + (uint)(dm.mhFlags >> 12) * 4;
|
codeOffset = bodyOffset + (uint)(dm.mhFlags >> 12) * 4;
|
||||||
}
|
}
|
||||||
fileDataReader.BaseStream.Position = codeOffset;
|
fileDataReader.Position = codeOffset;
|
||||||
|
|
||||||
if (!decrypter.decrypt(fileDataReader, dm))
|
if (!decrypter.decrypt(fileDataReader, dm))
|
||||||
continue;
|
continue;
|
||||||
|
@ -202,14 +192,14 @@ namespace de4dot.code.deobfuscators.CodeVeil {
|
||||||
static byte[] initializeMethodEnd = new byte[] {
|
static byte[] initializeMethodEnd = new byte[] {
|
||||||
0x33, 0xC0, 0x40, 0x5E, 0x5F, 0x5A, 0x59, 0x5B, 0xC9, 0xC2,
|
0x33, 0xC0, 0x40, 0x5E, 0x5F, 0x5A, 0x59, 0x5B, 0xC9, 0xC2,
|
||||||
};
|
};
|
||||||
byte[] findMethodsData(PeImage peImage, byte[] fileData) {
|
byte[] findMethodsData(MyPEImage peImage, byte[] fileData) {
|
||||||
var section = peImage.Sections[0];
|
var section = peImage.Sections[0];
|
||||||
|
|
||||||
var reader = new BinaryReader(new MemoryStream(fileData));
|
var reader = MemoryImageStream.Create(fileData);
|
||||||
|
|
||||||
const int RVA_EXECUTIVE_OFFSET = 1 * 4;
|
const int RVA_EXECUTIVE_OFFSET = 1 * 4;
|
||||||
const int ENC_CODE_OFFSET = 6 * 4;
|
const int ENC_CODE_OFFSET = 6 * 4;
|
||||||
int lastOffset = (int)(section.pointerToRawData + section.sizeOfRawData);
|
int lastOffset = (int)(section.PointerToRawData + section.SizeOfRawData);
|
||||||
for (int offset = getStartOffset(peImage); offset < lastOffset; ) {
|
for (int offset = getStartOffset(peImage); offset < lastOffset; ) {
|
||||||
offset = findSig(fileData, offset, lastOffset, initializeMethodEnd);
|
offset = findSig(fileData, offset, lastOffset, initializeMethodEnd);
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
|
@ -229,13 +219,13 @@ namespace de4dot.code.deobfuscators.CodeVeil {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int relOffs = BitConverter.ToInt32(fileData, offset + ENC_CODE_OFFSET);
|
int relOffs = BitConverter.ToInt32(fileData, offset + ENC_CODE_OFFSET);
|
||||||
if (relOffs <= 0 || relOffs >= section.sizeOfRawData)
|
if (relOffs <= 0 || relOffs >= section.SizeOfRawData)
|
||||||
continue;
|
continue;
|
||||||
reader.BaseStream.Position = section.pointerToRawData + relOffs;
|
reader.Position = section.PointerToRawData + relOffs;
|
||||||
|
|
||||||
int size = DeobUtils.readVariableLengthInt32(reader);
|
int size = (int)reader.ReadCompressedUInt32();
|
||||||
int endOffset = relOffs + size;
|
int endOffset = relOffs + size;
|
||||||
if (endOffset < relOffs || endOffset > section.sizeOfRawData)
|
if (endOffset < relOffs || endOffset > section.SizeOfRawData)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return reader.ReadBytes(size);
|
return reader.ReadBytes(size);
|
||||||
|
@ -244,7 +234,7 @@ namespace de4dot.code.deobfuscators.CodeVeil {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getStartOffset(PeImage peImage) {
|
int getStartOffset(MyPEImage peImage) {
|
||||||
int minOffset = int.MaxValue;
|
int minOffset = int.MaxValue;
|
||||||
foreach (var rva in mainType.Rvas) {
|
foreach (var rva in mainType.Rvas) {
|
||||||
int rvaOffs = (int)peImage.rvaToOffset((uint)rva);
|
int rvaOffs = (int)peImage.rvaToOffset((uint)rva);
|
||||||
|
|
|
@ -21,7 +21,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.PE;
|
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.CodeWall {
|
namespace de4dot.code.deobfuscators.CodeWall {
|
||||||
public class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
public class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
||||||
|
@ -164,10 +163,10 @@ namespace de4dot.code.deobfuscators.CodeWall {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
byte[] fileData = ModuleBytes ?? DeobUtils.readModule(module);
|
byte[] fileData = ModuleBytes ?? DeobUtils.readModule(module);
|
||||||
var peImage = new PeImage(fileData);
|
using (var peImage = new MyPEImage(fileData)) {
|
||||||
|
if (!methodsDecrypter.decrypt(peImage, ref dumpedMethods))
|
||||||
if (!methodsDecrypter.decrypt(peImage, ref dumpedMethods))
|
return false;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
newFileData = fileData;
|
newFileData = fileData;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
using System;
|
using System;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using dot10.DotNet.Emit;
|
using dot10.DotNet.Emit;
|
||||||
using de4dot.PE;
|
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.CodeWall {
|
namespace de4dot.code.deobfuscators.CodeWall {
|
||||||
|
@ -67,50 +66,33 @@ namespace de4dot.code.deobfuscators.CodeWall {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool decrypt(PeImage peImage, ref DumpedMethods dumpedMethods) {
|
public bool decrypt(MyPEImage peImage, ref DumpedMethods dumpedMethods) {
|
||||||
dumpedMethods = new DumpedMethods();
|
dumpedMethods = new DumpedMethods();
|
||||||
|
|
||||||
bool decrypted = false;
|
bool decrypted = false;
|
||||||
|
|
||||||
var metadataTables = peImage.Cor20Header.createMetadataTables();
|
var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable;
|
||||||
var methodDef = metadataTables.getMetadataType(MetadataIndex.iMethodDef);
|
for (uint rid = 1; rid <= methodDef.Rows; rid++) {
|
||||||
uint methodDefOffset = methodDef.fileOffset;
|
|
||||||
for (int i = 0; i < methodDef.rows; i++, methodDefOffset += methodDef.totalSize) {
|
|
||||||
uint bodyRva = peImage.offsetReadUInt32(methodDefOffset);
|
|
||||||
if (bodyRva == 0)
|
|
||||||
continue;
|
|
||||||
uint bodyOffset = peImage.rvaToOffset(bodyRva);
|
|
||||||
|
|
||||||
var dm = new DumpedMethod();
|
var dm = new DumpedMethod();
|
||||||
dm.token = (uint)(0x06000001 + i);
|
peImage.readMethodTableRowTo(dm, rid);
|
||||||
|
|
||||||
byte[] code, extraSections;
|
if (dm.mdRVA == 0)
|
||||||
peImage.Reader.BaseStream.Position = bodyOffset;
|
|
||||||
var mbHeader = MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections);
|
|
||||||
|
|
||||||
if (code.Length < 6 || code[0] != 0x2A || code[1] != 0x2A)
|
|
||||||
continue;
|
continue;
|
||||||
dm.code = code;
|
uint bodyOffset = peImage.rvaToOffset(dm.mdRVA);
|
||||||
dm.extraSections = extraSections;
|
|
||||||
|
|
||||||
int seed = BitConverter.ToInt32(code, 2);
|
peImage.Reader.Position = bodyOffset;
|
||||||
Array.Copy(newCodeHeader, code, newCodeHeader.Length);
|
var mbHeader = MethodBodyParser.parseMethodBody(peImage.Reader, out dm.code, out dm.extraSections);
|
||||||
|
peImage.updateMethodHeaderInfo(dm, mbHeader);
|
||||||
|
|
||||||
|
if (dm.code.Length < 6 || dm.code[0] != 0x2A || dm.code[1] != 0x2A)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int seed = BitConverter.ToInt32(dm.code, 2);
|
||||||
|
Array.Copy(newCodeHeader, dm.code, newCodeHeader.Length);
|
||||||
if (seed == 0)
|
if (seed == 0)
|
||||||
decrypt(code);
|
decrypt(dm.code);
|
||||||
else
|
else
|
||||||
decrypt(code, seed);
|
decrypt(dm.code, seed);
|
||||||
|
|
||||||
dm.mdRVA = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[0].offset, methodDef.fields[0].size);
|
|
||||||
dm.mdImplFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[1].offset);
|
|
||||||
dm.mdFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[2].offset);
|
|
||||||
dm.mdName = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[3].offset, methodDef.fields[3].size);
|
|
||||||
dm.mdSignature = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[4].offset, methodDef.fields[4].size);
|
|
||||||
dm.mdParamList = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[5].offset, methodDef.fields[5].size);
|
|
||||||
|
|
||||||
dm.mhFlags = mbHeader.flags;
|
|
||||||
dm.mhMaxStack = mbHeader.maxStack;
|
|
||||||
dm.mhCodeSize = (uint)dm.code.Length;
|
|
||||||
dm.mhLocalVarSigTok = mbHeader.localVarSigTok;
|
|
||||||
|
|
||||||
dumpedMethods.add(dm);
|
dumpedMethods.add(dm);
|
||||||
decrypted = true;
|
decrypted = true;
|
||||||
|
|
|
@ -29,7 +29,7 @@ using de4dot.blocks;
|
||||||
namespace de4dot.code.deobfuscators.CodeWall {
|
namespace de4dot.code.deobfuscators.CodeWall {
|
||||||
class StringDecrypter {
|
class StringDecrypter {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
MethodDefinitionAndDeclaringTypeDict<StringEncrypterInfo> stringEncrypterInfos = new MethodDefinitionAndDeclaringTypeDict<StringEncrypterInfo>();
|
MethodDefAndDeclaringTypeDict<StringEncrypterInfo> stringEncrypterInfos = new MethodDefAndDeclaringTypeDict<StringEncrypterInfo>();
|
||||||
Version version;
|
Version version;
|
||||||
|
|
||||||
public enum Version {
|
public enum Version {
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
|
||||||
|
|
||||||
public void read(MethodDef method) {
|
public void read(MethodDef method) {
|
||||||
this.parameters = method.Parameters;
|
this.parameters = method.Parameters;
|
||||||
this.locals = getLocals(method);
|
SetLocals(getLocals(method));
|
||||||
|
|
||||||
maxStackSize = (ushort)reader.ReadInt32();
|
maxStackSize = (ushort)reader.ReadInt32();
|
||||||
ReadInstructionsNumBytes(reader.ReadUInt32());
|
ReadInstructionsNumBytes(reader.ReadUInt32());
|
||||||
|
|
|
@ -25,7 +25,7 @@ using de4dot.blocks;
|
||||||
namespace de4dot.code.deobfuscators.DeepSea {
|
namespace de4dot.code.deobfuscators.DeepSea {
|
||||||
class ArrayBlockState {
|
class ArrayBlockState {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
FieldDefinitionAndDeclaringTypeDict<FieldInfo> fieldToInfo = new FieldDefinitionAndDeclaringTypeDict<FieldInfo>();
|
FieldDefAndDeclaringTypeDict<FieldInfo> fieldToInfo = new FieldDefAndDeclaringTypeDict<FieldInfo>();
|
||||||
|
|
||||||
public class FieldInfo {
|
public class FieldInfo {
|
||||||
public readonly FieldDef field;
|
public readonly FieldDef field;
|
||||||
|
|
|
@ -27,9 +27,9 @@ namespace de4dot.code.deobfuscators.DeepSea {
|
||||||
// DS 4.x can move fields from a class to a struct. This class restores the fields.
|
// DS 4.x can move fields from a class to a struct. This class restores the fields.
|
||||||
class FieldsRestorer {
|
class FieldsRestorer {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
TypeDefinitionDict<List<TypeDef>> structToOwners = new TypeDefinitionDict<List<TypeDef>>();
|
TypeDefDict<List<TypeDef>> structToOwners = new TypeDefDict<List<TypeDef>>();
|
||||||
FieldDefinitionAndDeclaringTypeDict<bool> structFieldsToFix = new FieldDefinitionAndDeclaringTypeDict<bool>();
|
FieldDefAndDeclaringTypeDict<bool> structFieldsToFix = new FieldDefAndDeclaringTypeDict<bool>();
|
||||||
TypeDefinitionDict<FieldDefinitionAndDeclaringTypeDict<FieldDef>> typeToFieldsDict = new TypeDefinitionDict<FieldDefinitionAndDeclaringTypeDict<FieldDef>>();
|
TypeDefDict<FieldDefAndDeclaringTypeDict<FieldDef>> typeToFieldsDict = new TypeDefDict<FieldDefAndDeclaringTypeDict<FieldDef>>();
|
||||||
|
|
||||||
public List<TypeDef> FieldStructs {
|
public List<TypeDef> FieldStructs {
|
||||||
get {
|
get {
|
||||||
|
@ -76,7 +76,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fieldsDict = new FieldDefinitionAndDeclaringTypeDict<FieldDef>();
|
var fieldsDict = new FieldDefAndDeclaringTypeDict<FieldDef>();
|
||||||
typeToFieldsDict.add(ownerType, fieldsDict);
|
typeToFieldsDict.add(ownerType, fieldsDict);
|
||||||
foreach (var structField in structType.Fields) {
|
foreach (var structField in structType.Fields) {
|
||||||
var newField = module.UpdateRowId(new FieldDefUser(structField.Name, structField.FieldSig.Clone(), structField.Attributes));
|
var newField = module.UpdateRowId(new FieldDefUser(structField.Name, structField.FieldSig.Clone(), structField.Attributes));
|
||||||
|
@ -144,7 +144,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<FieldDef> getPossibleFields(TypeDef type) {
|
IEnumerable<FieldDef> getPossibleFields(TypeDef type) {
|
||||||
var typeToFields = new TypeDefinitionDict<List<FieldDef>>();
|
var typeToFields = new TypeDefDict<List<FieldDef>>();
|
||||||
foreach (var field in type.Fields) {
|
foreach (var field in type.Fields) {
|
||||||
if (field.Attributes != FieldAttributes.Private)
|
if (field.Attributes != FieldAttributes.Private)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -27,7 +27,7 @@ using de4dot.blocks;
|
||||||
namespace de4dot.code.deobfuscators.DeepSea {
|
namespace de4dot.code.deobfuscators.DeepSea {
|
||||||
class StringDecrypter {
|
class StringDecrypter {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
MethodDefinitionAndDeclaringTypeDict<IDecrypterInfo> methodToInfo = new MethodDefinitionAndDeclaringTypeDict<IDecrypterInfo>();
|
MethodDefAndDeclaringTypeDict<IDecrypterInfo> methodToInfo = new MethodDefAndDeclaringTypeDict<IDecrypterInfo>();
|
||||||
DecrypterVersion version = DecrypterVersion.Unknown;
|
DecrypterVersion version = DecrypterVersion.Unknown;
|
||||||
|
|
||||||
public enum DecrypterVersion {
|
public enum DecrypterVersion {
|
||||||
|
@ -45,12 +45,12 @@ namespace de4dot.code.deobfuscators.DeepSea {
|
||||||
}
|
}
|
||||||
|
|
||||||
static short[] findKey(MethodDef initMethod, FieldDef keyField) {
|
static short[] findKey(MethodDef initMethod, FieldDef keyField) {
|
||||||
var fields = new FieldDefinitionAndDeclaringTypeDict<bool>();
|
var fields = new FieldDefAndDeclaringTypeDict<bool>();
|
||||||
fields.add(keyField, true);
|
fields.add(keyField, true);
|
||||||
return findKey(initMethod, fields);
|
return findKey(initMethod, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
static short[] findKey(MethodDef initMethod, FieldDefinitionAndDeclaringTypeDict<bool> fields) {
|
static short[] findKey(MethodDef initMethod, FieldDefAndDeclaringTypeDict<bool> fields) {
|
||||||
var instrs = initMethod.Body.Instructions;
|
var instrs = initMethod.Body.Instructions;
|
||||||
for (int i = 0; i < instrs.Count - 2; i++) {
|
for (int i = 0; i < instrs.Count - 2; i++) {
|
||||||
var ldci4 = instrs[i];
|
var ldci4 = instrs[i];
|
||||||
|
@ -153,7 +153,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
|
||||||
MethodDef cctor;
|
MethodDef cctor;
|
||||||
int magic;
|
int magic;
|
||||||
int arg1, arg2;
|
int arg1, arg2;
|
||||||
FieldDefinitionAndDeclaringTypeDict<bool> fields;
|
FieldDefAndDeclaringTypeDict<bool> fields;
|
||||||
ArrayInfo arrayInfo;
|
ArrayInfo arrayInfo;
|
||||||
ushort[] encryptedData;
|
ushort[] encryptedData;
|
||||||
short[] key;
|
short[] key;
|
||||||
|
@ -206,8 +206,8 @@ namespace de4dot.code.deobfuscators.DeepSea {
|
||||||
return count >= 2;
|
return count >= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FieldDefinitionAndDeclaringTypeDict<bool> getFields(MethodDef method) {
|
static FieldDefAndDeclaringTypeDict<bool> getFields(MethodDef method) {
|
||||||
var fields = new FieldDefinitionAndDeclaringTypeDict<bool>();
|
var fields = new FieldDefAndDeclaringTypeDict<bool>();
|
||||||
foreach (var instr in method.Body.Instructions) {
|
foreach (var instr in method.Body.Instructions) {
|
||||||
if (instr.OpCode.Code != Code.Ldsfld && instr.OpCode.Code != Code.Stsfld)
|
if (instr.OpCode.Code != Code.Ldsfld && instr.OpCode.Code != Code.Stsfld)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -189,19 +189,6 @@ namespace de4dot.code.deobfuscators {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Remove this method
|
|
||||||
public static int readVariableLengthInt32(BinaryReader reader) {
|
|
||||||
byte b = reader.ReadByte();
|
|
||||||
if ((b & 0x80) == 0)
|
|
||||||
return b;
|
|
||||||
if ((b & 0x40) == 0)
|
|
||||||
return (((int)b & 0x3F) << 8) + reader.ReadByte();
|
|
||||||
return (((int)b & 0x3F) << 24) +
|
|
||||||
((int)reader.ReadByte() << 16) +
|
|
||||||
((int)reader.ReadByte() << 8) +
|
|
||||||
reader.ReadByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int readVariableLengthInt32(byte[] data, ref int index) {
|
public static int readVariableLengthInt32(byte[] data, ref int index) {
|
||||||
byte b = data[index++];
|
byte b = data[index++];
|
||||||
if ((b & 0x80) == 0)
|
if ((b & 0x80) == 0)
|
||||||
|
|
|
@ -229,8 +229,8 @@ namespace de4dot.code.deobfuscators {
|
||||||
public abstract IEnumerable<int> getStringDecrypterMethods();
|
public abstract IEnumerable<int> getStringDecrypterMethods();
|
||||||
|
|
||||||
class MethodCallRemover {
|
class MethodCallRemover {
|
||||||
Dictionary<string, MethodDefinitionAndDeclaringTypeDict<bool>> methodNameInfos = new Dictionary<string, MethodDefinitionAndDeclaringTypeDict<bool>>();
|
Dictionary<string, MethodDefAndDeclaringTypeDict<bool>> methodNameInfos = new Dictionary<string, MethodDefAndDeclaringTypeDict<bool>>();
|
||||||
MethodDefinitionAndDeclaringTypeDict<MethodDefinitionAndDeclaringTypeDict<bool>> methodRefInfos = new MethodDefinitionAndDeclaringTypeDict<MethodDefinitionAndDeclaringTypeDict<bool>>();
|
MethodDefAndDeclaringTypeDict<MethodDefAndDeclaringTypeDict<bool>> methodRefInfos = new MethodDefAndDeclaringTypeDict<MethodDefAndDeclaringTypeDict<bool>>();
|
||||||
|
|
||||||
void checkMethod(IMethod methodToBeRemoved) {
|
void checkMethod(IMethod methodToBeRemoved) {
|
||||||
var sig = methodToBeRemoved.MethodSig;
|
var sig = methodToBeRemoved.MethodSig;
|
||||||
|
@ -245,9 +245,9 @@ namespace de4dot.code.deobfuscators {
|
||||||
return;
|
return;
|
||||||
checkMethod(methodToBeRemoved);
|
checkMethod(methodToBeRemoved);
|
||||||
|
|
||||||
MethodDefinitionAndDeclaringTypeDict<bool> dict;
|
MethodDefAndDeclaringTypeDict<bool> dict;
|
||||||
if (!methodNameInfos.TryGetValue(method, out dict))
|
if (!methodNameInfos.TryGetValue(method, out dict))
|
||||||
methodNameInfos[method] = dict = new MethodDefinitionAndDeclaringTypeDict<bool>();
|
methodNameInfos[method] = dict = new MethodDefAndDeclaringTypeDict<bool>();
|
||||||
dict.add(methodToBeRemoved, true);
|
dict.add(methodToBeRemoved, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
var dict = methodRefInfos.find(method);
|
var dict = methodRefInfos.find(method);
|
||||||
if (dict == null)
|
if (dict == null)
|
||||||
methodRefInfos.add(method, dict = new MethodDefinitionAndDeclaringTypeDict<bool>());
|
methodRefInfos.add(method, dict = new MethodDefAndDeclaringTypeDict<bool>());
|
||||||
dict.add(methodToBeRemoved, true);
|
dict.add(methodToBeRemoved, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeAll(IList<Block> allBlocks, Blocks blocks, string method) {
|
void removeAll(IList<Block> allBlocks, Blocks blocks, string method) {
|
||||||
MethodDefinitionAndDeclaringTypeDict<bool> info;
|
MethodDefAndDeclaringTypeDict<bool> info;
|
||||||
if (!methodNameInfos.TryGetValue(method, out info))
|
if (!methodNameInfos.TryGetValue(method, out info))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
removeCalls(allBlocks, blocks, info);
|
removeCalls(allBlocks, blocks, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeCalls(IList<Block> allBlocks, Blocks blocks, MethodDefinitionAndDeclaringTypeDict<bool> info) {
|
void removeCalls(IList<Block> allBlocks, Blocks blocks, MethodDefAndDeclaringTypeDict<bool> info) {
|
||||||
var instrsToDelete = new List<int>();
|
var instrsToDelete = new List<int>();
|
||||||
foreach (var block in allBlocks) {
|
foreach (var block in allBlocks) {
|
||||||
instrsToDelete.Clear();
|
instrsToDelete.Clear();
|
||||||
|
@ -782,5 +782,13 @@ namespace de4dot.code.deobfuscators {
|
||||||
protected static int toInt32(bool b) {
|
protected static int toInt32(bool b) {
|
||||||
return b ? 1 : 0;
|
return b ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ using de4dot.blocks;
|
||||||
namespace de4dot.code.deobfuscators.Dotfuscator {
|
namespace de4dot.code.deobfuscators.Dotfuscator {
|
||||||
class StringDecrypter {
|
class StringDecrypter {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
MethodDefinitionAndDeclaringTypeDict<StringDecrypterInfo> stringDecrypterMethods = new MethodDefinitionAndDeclaringTypeDict<StringDecrypterInfo>();
|
MethodDefAndDeclaringTypeDict<StringDecrypterInfo> stringDecrypterMethods = new MethodDefAndDeclaringTypeDict<StringDecrypterInfo>();
|
||||||
|
|
||||||
public class StringDecrypterInfo {
|
public class StringDecrypterInfo {
|
||||||
public MethodDef method;
|
public MethodDef method;
|
||||||
|
|
|
@ -24,7 +24,7 @@ using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
class ExceptionLoggerRemover {
|
class ExceptionLoggerRemover {
|
||||||
MethodDefinitionAndDeclaringTypeDict<bool> exceptionLoggerMethods = new MethodDefinitionAndDeclaringTypeDict<bool>();
|
MethodDefAndDeclaringTypeDict<bool> exceptionLoggerMethods = new MethodDefAndDeclaringTypeDict<bool>();
|
||||||
|
|
||||||
public int NumRemovedExceptionLoggers { get; set; }
|
public int NumRemovedExceptionLoggers { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
|
||||||
TypeDef delegateType;
|
TypeDef delegateType;
|
||||||
TypeDef delegateInitType;
|
TypeDef delegateInitType;
|
||||||
protected BinaryReader decryptedReader;
|
protected BinaryReader decryptedReader;
|
||||||
MethodDefinitionAndDeclaringTypeDict<Info> decrypterMethods = new MethodDefinitionAndDeclaringTypeDict<Info>();
|
MethodDefAndDeclaringTypeDict<Info> decrypterMethods = new MethodDefAndDeclaringTypeDict<Info>();
|
||||||
|
|
||||||
protected class Info {
|
protected class Info {
|
||||||
public MethodDef method;
|
public MethodDef method;
|
||||||
|
@ -66,7 +66,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
|
||||||
|
|
||||||
public IEnumerable<TypeDef> DecrypterTypes {
|
public IEnumerable<TypeDef> DecrypterTypes {
|
||||||
get {
|
get {
|
||||||
var types = new TypeDefinitionDict<TypeDef>();
|
var types = new TypeDefDict<TypeDef>();
|
||||||
foreach (var info in decrypterMethods.getValues()) {
|
foreach (var info in decrypterMethods.getValues()) {
|
||||||
if (info.referenced)
|
if (info.referenced)
|
||||||
types.add(info.method.DeclaringType, info.method.DeclaringType);
|
types.add(info.method.DeclaringType, info.method.DeclaringType);
|
||||||
|
|
|
@ -25,7 +25,7 @@ using de4dot.blocks;
|
||||||
namespace de4dot.code.deobfuscators.Goliath_NET {
|
namespace de4dot.code.deobfuscators.Goliath_NET {
|
||||||
class LocalsRestorer {
|
class LocalsRestorer {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
TypeDefinitionDict<Info> typeToInfo = new TypeDefinitionDict<Info>();
|
TypeDefDict<Info> typeToInfo = new TypeDefDict<Info>();
|
||||||
|
|
||||||
class Info {
|
class Info {
|
||||||
public TypeDef type;
|
public TypeDef type;
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
RenameResourceKeys = 2,
|
RenameResourceKeys = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IDeobfuscator : INameChecker {
|
public interface IDeobfuscator : INameChecker, IDisposable {
|
||||||
string Type { get; }
|
string Type { get; }
|
||||||
string TypeLong { get; }
|
string TypeLong { get; }
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
|
@ -243,7 +243,7 @@ namespace de4dot.code.deobfuscators.ILProtector {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restoreMethod(MethodDef method, MethodReader methodReader) {
|
static void restoreMethod(MethodDef method, MethodReader methodReader) {
|
||||||
// body.MaxStackSize = <let Mono.Cecil calculate this>
|
// body.MaxStackSize = <let dot10 calculate this>
|
||||||
method.Body.InitLocals = methodReader.InitLocals;
|
method.Body.InitLocals = methodReader.InitLocals;
|
||||||
methodReader.RestoreMethod(method);
|
methodReader.RestoreMethod(method);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,9 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
MemberRef createInitializeArrayMethod() {
|
MemberRef createInitializeArrayMethod() {
|
||||||
if (initializeArrayMethod == null) {
|
if (initializeArrayMethod == null) {
|
||||||
var runtimeHelpersType = DotNetUtils.findOrCreateTypeReference(module, module.CorLibTypes.AssemblyRef, "System.Runtime.CompilerServices", "RuntimeHelpers", false);
|
var runtimeHelpersType = DotNetUtils.findOrCreateTypeRef(module, module.CorLibTypes.AssemblyRef, "System.Runtime.CompilerServices", "RuntimeHelpers", false);
|
||||||
var systemArrayType = DotNetUtils.findOrCreateTypeReference(module, module.CorLibTypes.AssemblyRef, "System", "Array", false);
|
var systemArrayType = DotNetUtils.findOrCreateTypeRef(module, module.CorLibTypes.AssemblyRef, "System", "Array", false);
|
||||||
var runtimeFieldHandleType = DotNetUtils.findOrCreateTypeReference(module, module.CorLibTypes.AssemblyRef, "System", "RuntimeFieldHandle", true);
|
var runtimeFieldHandleType = DotNetUtils.findOrCreateTypeRef(module, module.CorLibTypes.AssemblyRef, "System", "RuntimeFieldHandle", true);
|
||||||
var methodSig = MethodSig.CreateStatic(module.CorLibTypes.Void, systemArrayType, runtimeFieldHandleType);
|
var methodSig = MethodSig.CreateStatic(module.CorLibTypes.Void, systemArrayType, runtimeFieldHandleType);
|
||||||
initializeArrayMethod = module.UpdateRowId(new MemberRefUser(module, "InitializeArray", methodSig, runtimeHelpersType.TypeDefOrRef));
|
initializeArrayMethod = module.UpdateRowId(new MemberRefUser(module, "InitializeArray", methodSig, runtimeHelpersType.TypeDefOrRef));
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
return arrayType;
|
return arrayType;
|
||||||
|
|
||||||
if (valueType == null)
|
if (valueType == null)
|
||||||
valueType = DotNetUtils.findOrCreateTypeReference(module, module.CorLibTypes.AssemblyRef, "System", "ValueType", false);
|
valueType = DotNetUtils.findOrCreateTypeRef(module, module.CorLibTypes.AssemblyRef, "System", "ValueType", false);
|
||||||
arrayType = new TypeDefUser("", string.Format("__StaticArrayInitTypeSize={0}", size), valueType.TypeDefOrRef);
|
arrayType = new TypeDefUser("", string.Format("__StaticArrayInitTypeSize={0}", size), valueType.TypeDefOrRef);
|
||||||
module.UpdateRowId(arrayType);
|
module.UpdateRowId(arrayType);
|
||||||
arrayType.Attributes = TypeAttributes.NestedPrivate | TypeAttributes.ExplicitLayout |
|
arrayType.Attributes = TypeAttributes.NestedPrivate | TypeAttributes.ExplicitLayout |
|
||||||
|
|
|
@ -21,8 +21,8 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using dot10.PE;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using de4dot.PE;
|
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.MPRESS {
|
namespace de4dot.code.deobfuscators.MPRESS {
|
||||||
|
@ -159,7 +159,7 @@ namespace de4dot.code.deobfuscators.MPRESS {
|
||||||
if (checkMethods(type, methods_v1x)) {
|
if (checkMethods(type, methods_v1x)) {
|
||||||
var lfMethod = DotNetUtils.getMethod(type, "System.Boolean", "(System.String,System.Byte[]&)");
|
var lfMethod = DotNetUtils.getMethod(type, "System.Boolean", "(System.String,System.Byte[]&)");
|
||||||
if (lfMethod != null) {
|
if (lfMethod != null) {
|
||||||
if (DeobUtils.hasInteger(lfMethod, (int)Machine.amd64))
|
if (DeobUtils.hasInteger(lfMethod, (int)Machine.AMD64))
|
||||||
return Version.V218;
|
return Version.V218;
|
||||||
return Version.V1x_217;
|
return Version.V1x_217;
|
||||||
}
|
}
|
||||||
|
@ -194,37 +194,39 @@ namespace de4dot.code.deobfuscators.MPRESS {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
byte[] fileData = ModuleBytes ?? DeobUtils.readModule(module);
|
byte[] fileData = ModuleBytes ?? DeobUtils.readModule(module);
|
||||||
var peImage = new PeImage(fileData);
|
byte[] decompressed;
|
||||||
var section = peImage.Sections[peImage.Sections.Length - 1];
|
using (var peImage = new MyPEImage(fileData)) {
|
||||||
var offset = section.pointerToRawData;
|
var section = peImage.Sections[peImage.Sections.Count - 1];
|
||||||
offset += 16;
|
var offset = section.PointerToRawData;
|
||||||
|
offset += 16;
|
||||||
|
|
||||||
byte[] decompressed, compressed;
|
byte[] compressed;
|
||||||
int compressedLen;
|
int compressedLen;
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case Version.V0x:
|
case Version.V0x:
|
||||||
compressedLen = fileData.Length - (int)offset;
|
compressedLen = fileData.Length - (int)offset;
|
||||||
compressed = peImage.offsetReadBytes(offset, compressedLen);
|
compressed = peImage.offsetReadBytes(offset, compressedLen);
|
||||||
decompressed = Lzmat.decompress_old(compressed);
|
decompressed = Lzmat.decompress_old(compressed);
|
||||||
if (decompressed == null)
|
if (decompressed == null)
|
||||||
throw new ApplicationException("LZMAT decompression failed");
|
throw new ApplicationException("LZMAT decompression failed");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Version.V1x_217:
|
case Version.V1x_217:
|
||||||
case Version.V218:
|
case Version.V218:
|
||||||
if (peImage.FileHeader.machine == Machine.amd64 && version == Version.V218)
|
if (peImage.PEImage.ImageNTHeaders.FileHeader.Machine == Machine.AMD64 && version == Version.V218)
|
||||||
offset = section.pointerToRawData + section.virtualSize;
|
offset = section.PointerToRawData + section.VirtualSize;
|
||||||
int decompressedLen = (int)peImage.offsetReadUInt32(offset);
|
int decompressedLen = (int)peImage.offsetReadUInt32(offset);
|
||||||
compressedLen = fileData.Length - (int)offset - 4;
|
compressedLen = fileData.Length - (int)offset - 4;
|
||||||
compressed = peImage.offsetReadBytes(offset + 4, compressedLen);
|
compressed = peImage.offsetReadBytes(offset + 4, compressedLen);
|
||||||
decompressed = new byte[decompressedLen];
|
decompressed = new byte[decompressedLen];
|
||||||
uint decompressedLen2;
|
uint decompressedLen2;
|
||||||
if (Lzmat.decompress(decompressed, out decompressedLen2, compressed) != LzmatStatus.OK)
|
if (Lzmat.decompress(decompressed, out decompressedLen2, compressed) != LzmatStatus.OK)
|
||||||
throw new ApplicationException("LZMAT decompression failed");
|
throw new ApplicationException("LZMAT decompression failed");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new ApplicationException("Unknown MPRESS version");
|
throw new ApplicationException("Unknown MPRESS version");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newFileData = decompressed;
|
newFileData = decompressed;
|
||||||
|
|
|
@ -17,22 +17,27 @@
|
||||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using de4dot.PE;
|
using System;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.MaxtoCode {
|
namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
class DecrypterInfo {
|
class DecrypterInfo : IDisposable {
|
||||||
public MainType mainType;
|
public MainType mainType;
|
||||||
public readonly PeImage peImage;
|
public readonly MyPEImage peImage;
|
||||||
public readonly PeHeader peHeader;
|
public readonly PeHeader peHeader;
|
||||||
public readonly McKey mcKey;
|
public readonly McKey mcKey;
|
||||||
public readonly byte[] fileData;
|
public readonly byte[] fileData;
|
||||||
|
|
||||||
public DecrypterInfo(MainType mainType, byte[] fileData) {
|
public DecrypterInfo(MainType mainType, byte[] fileData) {
|
||||||
this.mainType = mainType;
|
this.mainType = mainType;
|
||||||
this.peImage = new PeImage(fileData);
|
this.peImage = new MyPEImage(fileData);
|
||||||
this.peHeader = new PeHeader(mainType, peImage);
|
this.peHeader = new PeHeader(mainType, peImage);
|
||||||
this.mcKey = new McKey(peImage, peHeader);
|
this.mcKey = new McKey(peImage, peHeader);
|
||||||
this.fileData = fileData;
|
this.fileData = fileData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
if (peImage != null)
|
||||||
|
peImage.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,10 +120,18 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
newOne.setModule(module);
|
newOne.setModule(module);
|
||||||
newOne.mainType = new MainType(module, mainType);
|
newOne.mainType = new MainType(module, mainType);
|
||||||
newOne.decrypterInfo = decrypterInfo;
|
newOne.decrypterInfo = decrypterInfo;
|
||||||
newOne.decrypterInfo.mainType = newOne.mainType;
|
decrypterInfo = null;
|
||||||
|
if (newOne.decrypterInfo != null)
|
||||||
|
newOne.decrypterInfo.mainType = newOne.mainType;
|
||||||
return newOne;
|
return newOne;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void freePEImage() {
|
||||||
|
if (decrypterInfo != null)
|
||||||
|
decrypterInfo.Dispose();
|
||||||
|
decrypterInfo = null;
|
||||||
|
}
|
||||||
|
|
||||||
public override void deobfuscateBegin() {
|
public override void deobfuscateBegin() {
|
||||||
base.deobfuscateBegin();
|
base.deobfuscateBegin();
|
||||||
|
|
||||||
|
@ -134,6 +142,8 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
staticStringInliner.add(stringDecrypter.Method, (method, gim, args) => stringDecrypter.decrypt((uint)args[0]));
|
staticStringInliner.add(stringDecrypter.Method, (method, gim, args) => stringDecrypter.decrypt((uint)args[0]));
|
||||||
DeobfuscatedFile.stringDecryptersAdded();
|
DeobfuscatedFile.stringDecryptersAdded();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
freePEImage();
|
||||||
|
|
||||||
foreach (var method in mainType.InitMethods)
|
foreach (var method in mainType.InitMethods)
|
||||||
addCctorInitCallToBeRemoved(method);
|
addCctorInitCallToBeRemoved(method);
|
||||||
|
@ -142,6 +152,11 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
removeInvalidResources();
|
removeInvalidResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void deobfuscateEnd() {
|
||||||
|
freePEImage();
|
||||||
|
base.deobfuscateEnd();
|
||||||
|
}
|
||||||
|
|
||||||
static Encoding getEncoding(int cp) {
|
static Encoding getEncoding(int cp) {
|
||||||
try {
|
try {
|
||||||
return Encoding.GetEncoding(cp);
|
return Encoding.GetEncoding(cp);
|
||||||
|
@ -235,5 +250,11 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
list.Add(stringDecrypter.Method.MDToken.ToInt32());
|
list.Add(stringDecrypter.Method.MDToken.ToInt32());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing)
|
||||||
|
freePEImage();
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using de4dot.PE;
|
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.MaxtoCode {
|
namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
class McKey {
|
class McKey {
|
||||||
|
@ -30,7 +29,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
get { return data[index]; }
|
get { return data[index]; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public McKey(PeImage peImage, PeHeader peHeader) {
|
public McKey(MyPEImage peImage, PeHeader peHeader) {
|
||||||
this.peHeader = peHeader;
|
this.peHeader = peHeader;
|
||||||
try {
|
try {
|
||||||
this.data = peImage.readBytes(peHeader.getMcKeyRva(), 0x2000);
|
this.data = peImage.readBytes(peHeader.getMcKeyRva(), 0x2000);
|
||||||
|
|
|
@ -21,7 +21,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using de4dot.PE;
|
using dot10.IO;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.MaxtoCode {
|
namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
|
@ -31,7 +31,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
|
|
||||||
class MethodInfos {
|
class MethodInfos {
|
||||||
MainType mainType;
|
MainType mainType;
|
||||||
PeImage peImage;
|
MyPEImage peImage;
|
||||||
PeHeader peHeader;
|
PeHeader peHeader;
|
||||||
McKey mcKey;
|
McKey mcKey;
|
||||||
uint structSize;
|
uint structSize;
|
||||||
|
@ -61,7 +61,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodInfos(MainType mainType, PeImage peImage, PeHeader peHeader, McKey mcKey) {
|
public MethodInfos(MainType mainType, MyPEImage peImage, PeHeader peHeader, McKey mcKey) {
|
||||||
this.mainType = mainType;
|
this.mainType = mainType;
|
||||||
this.peImage = peImage;
|
this.peImage = peImage;
|
||||||
this.peHeader = peHeader;
|
this.peHeader = peHeader;
|
||||||
|
@ -463,55 +463,21 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
var methodInfos = new MethodInfos(decrypterInfo.mainType, peImage, decrypterInfo.peHeader, decrypterInfo.mcKey);
|
var methodInfos = new MethodInfos(decrypterInfo.mainType, peImage, decrypterInfo.peHeader, decrypterInfo.mcKey);
|
||||||
methodInfos.initializeInfos();
|
methodInfos.initializeInfos();
|
||||||
|
|
||||||
var metadataTables = peImage.Cor20Header.createMetadataTables();
|
var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable;
|
||||||
var methodDef = metadataTables.getMetadataType(MetadataIndex.iMethodDef);
|
for (uint rid = 1; rid <= methodDef.Rows; rid++) {
|
||||||
uint methodDefOffset = methodDef.fileOffset;
|
var dm = new DumpedMethod();
|
||||||
for (int i = 0; i < methodDef.rows; i++, methodDefOffset += methodDef.totalSize) {
|
peImage.readMethodTableRowTo(dm, rid);
|
||||||
uint bodyRva = peImage.offsetReadUInt32(methodDefOffset);
|
|
||||||
if (bodyRva == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var info = methodInfos.lookup(bodyRva);
|
var info = methodInfos.lookup(dm.mdRVA);
|
||||||
if (info == null)
|
if (info == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint bodyOffset = peImage.rvaToOffset(bodyRva);
|
ushort magic = peImage.readUInt16(dm.mdRVA);
|
||||||
ushort magic = peImage.offsetReadUInt16(bodyOffset);
|
|
||||||
if (magic != 0xFFF3)
|
if (magic != 0xFFF3)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var dm = new DumpedMethod();
|
var mbHeader = MethodBodyParser.parseMethodBody(MemoryImageStream.Create(info.body), out dm.code, out dm.extraSections);
|
||||||
dm.token = (uint)(0x06000001 + i);
|
peImage.updateMethodHeaderInfo(dm, mbHeader);
|
||||||
dm.mdRVA = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[0].offset, methodDef.fields[0].size);
|
|
||||||
dm.mdImplFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[1].offset);
|
|
||||||
dm.mdFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[2].offset);
|
|
||||||
dm.mdName = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[3].offset, methodDef.fields[3].size);
|
|
||||||
dm.mdSignature = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[4].offset, methodDef.fields[4].size);
|
|
||||||
dm.mdParamList = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[5].offset, methodDef.fields[5].size);
|
|
||||||
|
|
||||||
var reader = new BinaryReader(new MemoryStream(info.body));
|
|
||||||
byte b = reader.ReadByte();
|
|
||||||
if ((b & 3) == 2) {
|
|
||||||
dm.mhFlags = 2;
|
|
||||||
dm.mhMaxStack = 8;
|
|
||||||
dm.mhCodeSize = (uint)(b >> 2);
|
|
||||||
dm.mhLocalVarSigTok = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reader.BaseStream.Position--;
|
|
||||||
dm.mhFlags = reader.ReadUInt16();
|
|
||||||
dm.mhMaxStack = reader.ReadUInt16();
|
|
||||||
dm.mhCodeSize = reader.ReadUInt32();
|
|
||||||
dm.mhLocalVarSigTok = reader.ReadUInt32();
|
|
||||||
uint codeOffset = (uint)(dm.mhFlags >> 12) * 4;
|
|
||||||
reader.BaseStream.Position += codeOffset - 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
dm.code = reader.ReadBytes((int)dm.mhCodeSize);
|
|
||||||
if ((dm.mhFlags & 8) != 0) {
|
|
||||||
reader.BaseStream.Position = (reader.BaseStream.Position + 3) & ~3;
|
|
||||||
dm.extraSections = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
|
|
||||||
}
|
|
||||||
|
|
||||||
dumpedMethods.add(dm);
|
dumpedMethods.add(dm);
|
||||||
}
|
}
|
||||||
|
@ -529,8 +495,8 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
uint resourceSize = peHeader.readUInt32(0x0E14) ^ mcKey.readUInt32(0x00AA);
|
uint resourceSize = peHeader.readUInt32(0x0E14) ^ mcKey.readUInt32(0x00AA);
|
||||||
if (resourceRva == 0 || resourceSize == 0)
|
if (resourceRva == 0 || resourceSize == 0)
|
||||||
return;
|
return;
|
||||||
if (resourceRva != peImage.Cor20Header.resources.virtualAddress ||
|
if (resourceRva != (uint)peImage.Cor20Header.Resources.VirtualAddress ||
|
||||||
resourceSize != peImage.Cor20Header.resources.size) {
|
resourceSize != peImage.Cor20Header.Resources.Size) {
|
||||||
Logger.w("Invalid resource RVA and size found");
|
Logger.w("Invalid resource RVA and size found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,10 +517,10 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
uint usHeapSize = peHeader.readUInt32(0x0E04) ^ mcKey.readUInt32(0x0082);
|
uint usHeapSize = peHeader.readUInt32(0x0E04) ^ mcKey.readUInt32(0x0082);
|
||||||
if (usHeapRva == 0 || usHeapSize == 0)
|
if (usHeapRva == 0 || usHeapSize == 0)
|
||||||
return;
|
return;
|
||||||
var usHeap = peImage.Cor20Header.metadata.getStream("#US");
|
var usHeap = peImage.DotNetFile.MetaData.USStream;
|
||||||
if (usHeap == null ||
|
if (usHeap.StartOffset == 0 || // Start offset is 0 if it's not present in the file
|
||||||
peImage.rvaToOffset(usHeapRva) != usHeap.fileOffset ||
|
peImage.rvaToOffset(usHeapRva) != (uint)usHeap.StartOffset ||
|
||||||
usHeapSize != usHeap.Length) {
|
usHeapSize != (uint)(usHeap.EndOffset - usHeap.StartOffset)) {
|
||||||
Logger.w("Invalid #US heap RVA and size found");
|
Logger.w("Invalid #US heap RVA and size found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using de4dot.PE;
|
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.MaxtoCode {
|
namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
enum EncryptionVersion {
|
enum EncryptionVersion {
|
||||||
|
@ -40,7 +39,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
get { return version; }
|
get { return version; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public PeHeader(MainType mainType, PeImage peImage) {
|
public PeHeader(MainType mainType, MyPEImage peImage) {
|
||||||
uint headerOffset;
|
uint headerOffset;
|
||||||
version = getHeaderOffsetAndVersion(peImage, out headerOffset);
|
version = getHeaderOffsetAndVersion(peImage, out headerOffset);
|
||||||
headerData = peImage.offsetReadBytes(headerOffset, 0x1000);
|
headerData = peImage.offsetReadBytes(headerOffset, 0x1000);
|
||||||
|
@ -58,7 +57,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return BitConverter.ToUInt32(headerData, offset);
|
return BitConverter.ToUInt32(headerData, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static EncryptionVersion getHeaderOffsetAndVersion(PeImage peImage, out uint headerOffset) {
|
static EncryptionVersion getHeaderOffsetAndVersion(MyPEImage peImage, out uint headerOffset) {
|
||||||
headerOffset = 0;
|
headerOffset = 0;
|
||||||
|
|
||||||
var version = getVersion(peImage, headerOffset);
|
var version = getVersion(peImage, headerOffset);
|
||||||
|
@ -69,8 +68,8 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
if (section == null)
|
if (section == null)
|
||||||
return EncryptionVersion.Unknown;
|
return EncryptionVersion.Unknown;
|
||||||
|
|
||||||
headerOffset = section.pointerToRawData;
|
headerOffset = section.PointerToRawData;
|
||||||
uint end = section.pointerToRawData + section.sizeOfRawData - 0x1000 + 1;
|
uint end = section.PointerToRawData + section.SizeOfRawData - 0x1000 + 1;
|
||||||
while (headerOffset < end) {
|
while (headerOffset < end) {
|
||||||
version = getVersion(peImage, headerOffset);
|
version = getVersion(peImage, headerOffset);
|
||||||
if (version != EncryptionVersion.Unknown)
|
if (version != EncryptionVersion.Unknown)
|
||||||
|
@ -81,7 +80,7 @@ namespace de4dot.code.deobfuscators.MaxtoCode {
|
||||||
return EncryptionVersion.Unknown;
|
return EncryptionVersion.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EncryptionVersion getVersion(PeImage peImage, uint headerOffset) {
|
static EncryptionVersion getVersion(MyPEImage peImage, uint headerOffset) {
|
||||||
uint m1lo = peImage.offsetReadUInt32(headerOffset + 0x900);
|
uint m1lo = peImage.offsetReadUInt32(headerOffset + 0x900);
|
||||||
uint m1hi = peImage.offsetReadUInt32(headerOffset + 0x904);
|
uint m1hi = peImage.offsetReadUInt32(headerOffset + 0x904);
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,11 @@ using dot10.DotNet;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
class MemberReferenceBuilder {
|
class MemberRefBuilder {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
Dictionary<TypeSig, TypeSig> createdTypes = new Dictionary<TypeSig, TypeSig>(TypeEqualityComparer.Instance);
|
Dictionary<TypeSig, TypeSig> createdTypes = new Dictionary<TypeSig, TypeSig>(TypeEqualityComparer.Instance);
|
||||||
|
|
||||||
public MemberReferenceBuilder(ModuleDefMD module) {
|
public MemberRefBuilder(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassSig type(string ns, string name, string asmSimpleName) {
|
public ClassSig type(string ns, string name, string asmSimpleName) {
|
||||||
return type(ns, name, findAssemblyReference(asmSimpleName));
|
return type(ns, name, findAssemblyRef(asmSimpleName));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassSig type(string ns, string name) {
|
public ClassSig type(string ns, string name) {
|
||||||
|
@ -120,7 +120,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTypeSig valueType(string ns, string name, string asmSimpleName) {
|
public ValueTypeSig valueType(string ns, string name, string asmSimpleName) {
|
||||||
return valueType(ns, name, findAssemblyReference(asmSimpleName));
|
return valueType(ns, name, findAssemblyRef(asmSimpleName));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTypeSig valueType(string ns, string name) {
|
public ValueTypeSig valueType(string ns, string name) {
|
||||||
|
@ -173,7 +173,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
return module.UpdateRowId(new MemberRefUser(module, name, sig, declaringType));
|
return module.UpdateRowId(new MemberRefUser(module, name, sig, declaringType));
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyRef findAssemblyReference(string asmSimpleName) {
|
AssemblyRef findAssemblyRef(string asmSimpleName) {
|
||||||
var asmRef = module.GetAssemblyRef(asmSimpleName);
|
var asmRef = module.GetAssemblyRef(asmSimpleName);
|
||||||
if (asmRef == null)
|
if (asmRef == null)
|
||||||
throw new ApplicationException(string.Format("Could not find assembly {0} in assembly references", asmSimpleName));
|
throw new ApplicationException(string.Format("Could not find assembly {0} in assembly references", asmSimpleName));
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using dot10.IO;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
@ -39,7 +40,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class MethodBodyParser {
|
static class MethodBodyParser {
|
||||||
public static MethodBodyHeader parseMethodBody(BinaryReader reader, out byte[] code, out byte[] extraSections) {
|
public static MethodBodyHeader parseMethodBody(IBinaryReader reader, out byte[] code, out byte[] extraSections) {
|
||||||
try {
|
try {
|
||||||
return parseMethodBody2(reader, out code, out extraSections);
|
return parseMethodBody2(reader, out code, out extraSections);
|
||||||
}
|
}
|
||||||
|
@ -49,14 +50,10 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool verify(byte[] data) {
|
public static bool verify(byte[] data) {
|
||||||
return verify(new BinaryReader(new MemoryStream(data)));
|
return verify(MemoryImageStream.Create(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool verify(Stream data) {
|
public static bool verify(IBinaryReader reader) {
|
||||||
return verify(new BinaryReader(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool verify(BinaryReader reader) {
|
|
||||||
try {
|
try {
|
||||||
byte[] code, extraSections;
|
byte[] code, extraSections;
|
||||||
parseMethodBody(reader, out code, out extraSections);
|
parseMethodBody(reader, out code, out extraSections);
|
||||||
|
@ -67,7 +64,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static MethodBodyHeader parseMethodBody2(BinaryReader reader, out byte[] code, out byte[] extraSections) {
|
static MethodBodyHeader parseMethodBody2(IBinaryReader reader, out byte[] code, out byte[] extraSections) {
|
||||||
var mbHeader = new MethodBodyHeader();
|
var mbHeader = new MethodBodyHeader();
|
||||||
|
|
||||||
uint codeOffset;
|
uint codeOffset;
|
||||||
|
@ -95,7 +92,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
else
|
else
|
||||||
throw new InvalidMethodBody();
|
throw new InvalidMethodBody();
|
||||||
|
|
||||||
if (mbHeader.codeSize + codeOffset > reader.BaseStream.Length)
|
if (mbHeader.codeSize + codeOffset > reader.Length)
|
||||||
throw new InvalidMethodBody();
|
throw new InvalidMethodBody();
|
||||||
code = reader.ReadBytes((int)mbHeader.codeSize);
|
code = reader.ReadBytes((int)mbHeader.codeSize);
|
||||||
|
|
||||||
|
@ -107,11 +104,11 @@ namespace de4dot.code.deobfuscators {
|
||||||
return mbHeader;
|
return mbHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void align(BinaryReader reader, int alignment) {
|
static void align(IBinaryReader reader, int alignment) {
|
||||||
reader.BaseStream.Position = (reader.BaseStream.Position + alignment - 1) & ~(alignment - 1);
|
reader.Position = (reader.Position + alignment - 1) & ~(alignment - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] readExtraSections(BinaryReader reader) {
|
public static byte[] readExtraSections(IBinaryReader reader) {
|
||||||
try {
|
try {
|
||||||
return readExtraSections2(reader);
|
return readExtraSections2(reader);
|
||||||
}
|
}
|
||||||
|
@ -120,16 +117,16 @@ namespace de4dot.code.deobfuscators {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte[] readExtraSections2(BinaryReader reader) {
|
static byte[] readExtraSections2(IBinaryReader reader) {
|
||||||
align(reader, 4);
|
align(reader, 4);
|
||||||
int startPos = (int)reader.BaseStream.Position;
|
int startPos = (int)reader.Position;
|
||||||
parseSection(reader);
|
parseSection(reader);
|
||||||
int size = (int)reader.BaseStream.Position - startPos;
|
int size = (int)reader.Position - startPos;
|
||||||
reader.BaseStream.Position = startPos;
|
reader.Position = startPos;
|
||||||
return reader.ReadBytes(size);
|
return reader.ReadBytes(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parseSection(BinaryReader reader) {
|
static void parseSection(IBinaryReader reader) {
|
||||||
byte flags;
|
byte flags;
|
||||||
do {
|
do {
|
||||||
align(reader, 4);
|
align(reader, 4);
|
||||||
|
@ -141,20 +138,20 @@ namespace de4dot.code.deobfuscators {
|
||||||
throw new InvalidMethodBody("Invalid bits set");
|
throw new InvalidMethodBody("Invalid bits set");
|
||||||
|
|
||||||
if ((flags & 0x40) != 0) {
|
if ((flags & 0x40) != 0) {
|
||||||
reader.BaseStream.Position--;
|
reader.Position--;
|
||||||
int num = (int)(reader.ReadUInt32() >> 8) / 24;
|
int num = (int)(reader.ReadUInt32() >> 8) / 24;
|
||||||
reader.BaseStream.Position += num * 24;
|
reader.Position += num * 24;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int num = reader.ReadByte() / 12;
|
int num = reader.ReadByte() / 12;
|
||||||
reader.BaseStream.Position += 2 + num * 12;
|
reader.Position += 2 + num * 12;
|
||||||
}
|
}
|
||||||
} while ((flags & 0x80) != 0);
|
} while ((flags & 0x80) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte peek(BinaryReader reader) {
|
static byte peek(IBinaryReader reader) {
|
||||||
byte b = reader.ReadByte();
|
byte b = reader.ReadByte();
|
||||||
reader.BaseStream.Position--;
|
reader.Position--;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,9 @@ using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
class MethodCallRestorerBase {
|
class MethodCallRestorerBase {
|
||||||
protected MemberReferenceBuilder builder;
|
protected MemberRefBuilder builder;
|
||||||
protected ModuleDefMD module;
|
protected ModuleDefMD module;
|
||||||
MethodDefinitionAndDeclaringTypeDict<NewMethodInfo> oldToNewMethod = new MethodDefinitionAndDeclaringTypeDict<NewMethodInfo>();
|
MethodDefAndDeclaringTypeDict<NewMethodInfo> oldToNewMethod = new MethodDefAndDeclaringTypeDict<NewMethodInfo>();
|
||||||
|
|
||||||
class NewMethodInfo {
|
class NewMethodInfo {
|
||||||
public OpCode opCode;
|
public OpCode opCode;
|
||||||
|
@ -40,7 +40,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
|
|
||||||
public MethodCallRestorerBase(ModuleDefMD module) {
|
public MethodCallRestorerBase(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.builder = new MemberReferenceBuilder(module);
|
this.builder = new MemberRefBuilder(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createGetManifestResourceStream1(MethodDef oldMethod) {
|
public void createGetManifestResourceStream1(MethodDef oldMethod) {
|
||||||
|
|
|
@ -23,8 +23,8 @@ using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
class MethodCollection {
|
class MethodCollection {
|
||||||
TypeDefinitionDict<bool> types = new TypeDefinitionDict<bool>();
|
TypeDefDict<bool> types = new TypeDefDict<bool>();
|
||||||
MethodDefinitionAndDeclaringTypeDict<bool> methods = new MethodDefinitionAndDeclaringTypeDict<bool>();
|
MethodDefAndDeclaringTypeDict<bool> methods = new MethodDefAndDeclaringTypeDict<bool>();
|
||||||
|
|
||||||
public bool exists(IMethod method) {
|
public bool exists(IMethod method) {
|
||||||
if (method == null)
|
if (method == null)
|
||||||
|
|
|
@ -257,12 +257,12 @@ namespace de4dot.code.deobfuscators {
|
||||||
local = pushInstr.Operand as Local;
|
local = pushInstr.Operand as Local;
|
||||||
if (local == null)
|
if (local == null)
|
||||||
return null;
|
return null;
|
||||||
type = createByReferenceType(local.Type.RemovePinned());
|
type = createByRefType(local.Type.RemovePinned());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldarga:
|
case Code.Ldarga:
|
||||||
case Code.Ldarga_S:
|
case Code.Ldarga_S:
|
||||||
type = createByReferenceType(pushInstr.GetArgumentType(method.MethodSig, method.DeclaringType));
|
type = createByRefType(pushInstr.GetArgumentType(method.MethodSig, method.DeclaringType));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldfld:
|
case Code.Ldfld:
|
||||||
|
@ -278,12 +278,12 @@ namespace de4dot.code.deobfuscators {
|
||||||
var field2 = pushInstr.Operand as IField;
|
var field2 = pushInstr.Operand as IField;
|
||||||
if (field2 == null || field2.FieldSig == null)
|
if (field2 == null || field2.FieldSig == null)
|
||||||
return null;
|
return null;
|
||||||
type = createByReferenceType(field2.FieldSig.GetFieldType());
|
type = createByRefType(field2.FieldSig.GetFieldType());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldelema:
|
case Code.Ldelema:
|
||||||
case Code.Unbox:
|
case Code.Unbox:
|
||||||
type = createByReferenceType(pushInstr.Operand as ITypeDefOrRef);
|
type = createByRefType(pushInstr.Operand as ITypeDefOrRef);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -293,13 +293,13 @@ namespace de4dot.code.deobfuscators {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ByRefSig createByReferenceType(ITypeDefOrRef elementType) {
|
static ByRefSig createByRefType(ITypeDefOrRef elementType) {
|
||||||
if (elementType == null)
|
if (elementType == null)
|
||||||
return null;
|
return null;
|
||||||
return new ByRefSig(elementType.ToTypeSig());
|
return new ByRefSig(elementType.ToTypeSig());
|
||||||
}
|
}
|
||||||
|
|
||||||
static ByRefSig createByReferenceType(TypeSig elementType) {
|
static ByRefSig createByRefType(TypeSig elementType) {
|
||||||
if (elementType == null)
|
if (elementType == null)
|
||||||
return null;
|
return null;
|
||||||
return new ByRefSig(elementType);
|
return new ByRefSig(elementType);
|
||||||
|
|
|
@ -24,8 +24,12 @@ using de4dot.mdecrypt;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators {
|
namespace de4dot.code.deobfuscators {
|
||||||
static class MethodsDecrypter {
|
static class MethodsDecrypter {
|
||||||
public static DumpedMethods decrypt(string filename, byte[] moduleCctorBytes) {
|
public static DumpedMethods decrypt(ModuleDef module, byte[] moduleCctorBytes) {
|
||||||
using (var client = new NewProcessAssemblyClientFactory().create()) {
|
return decrypt(getServerClrVersion(module), module.Location, moduleCctorBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DumpedMethods decrypt(ServerClrVersion serverVersion, string filename, byte[] moduleCctorBytes) {
|
||||||
|
using (var client = new NewProcessAssemblyClientFactory(serverVersion).create()) {
|
||||||
client.connect();
|
client.connect();
|
||||||
client.waitConnected();
|
client.waitConnected();
|
||||||
var info = new DecryptMethodsInfo();
|
var info = new DecryptMethodsInfo();
|
||||||
|
@ -35,5 +39,20 @@ namespace de4dot.code.deobfuscators {
|
||||||
return client.Service.decryptMethods();
|
return client.Service.decryptMethods();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ServerClrVersion getServerClrVersion(ModuleDef module) {
|
||||||
|
switch (module.GetPointerSize()) {
|
||||||
|
default:
|
||||||
|
case 4:
|
||||||
|
if (module.IsClr40)
|
||||||
|
return ServerClrVersion.CLR_v40_x86;
|
||||||
|
return ServerClrVersion.CLR_v20_x86;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
if (module.IsClr40)
|
||||||
|
return ServerClrVersion.CLR_v40_x64;
|
||||||
|
return ServerClrVersion.CLR_v20_x64;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,59 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using dot10.IO;
|
using dot10.IO;
|
||||||
using dot10.PE;
|
using dot10.PE;
|
||||||
using dot10.DotNet.MD;
|
using dot10.DotNet.MD;
|
||||||
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.dotNET_Reactor {
|
namespace de4dot.code.deobfuscators {
|
||||||
sealed class MyPEImage : IDisposable {
|
sealed class MyPEImage : IDisposable {
|
||||||
IPEImage peImage;
|
IPEImage peImage;
|
||||||
byte[] peImageData;
|
byte[] peImageData;
|
||||||
IImageStream peStream;
|
IImageStream peStream;
|
||||||
DotNetFile dnFile;
|
DotNetFile dnFile;
|
||||||
|
bool dnFileInitialized;
|
||||||
ImageSectionHeader dotNetSection;
|
ImageSectionHeader dotNetSection;
|
||||||
bool ownPeImage;
|
bool ownPeImage;
|
||||||
|
|
||||||
|
public DotNetFile DotNetFile {
|
||||||
|
get {
|
||||||
|
if (dnFileInitialized)
|
||||||
|
return dnFile;
|
||||||
|
dnFileInitialized = true;
|
||||||
|
|
||||||
|
var dotNetDir = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[14];
|
||||||
|
if (dotNetDir.VirtualAddress != 0 && dotNetDir.Size >= 0x48) {
|
||||||
|
dnFile = DotNetFile.Load(peImage, false);
|
||||||
|
dotNetSection = findSection(dotNetDir.VirtualAddress);
|
||||||
|
}
|
||||||
|
return dnFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageCor20Header Cor20Header {
|
||||||
|
get { return DotNetFile.MetaData.ImageCor20Header; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBinaryReader Reader {
|
||||||
|
get { return peStream; }
|
||||||
|
}
|
||||||
|
|
||||||
public IPEImage PEImage {
|
public IPEImage PEImage {
|
||||||
get { return peImage; }
|
get { return peImage; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImageFileHeader FileHeader {
|
||||||
|
get { return peImage.ImageNTHeaders.FileHeader; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IImageOptionalHeader OptionalHeader {
|
||||||
|
get { return peImage.ImageNTHeaders.OptionalHeader; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IList<ImageSectionHeader> Sections {
|
||||||
|
get { return peImage.ImageSectionHeaders; }
|
||||||
|
}
|
||||||
|
|
||||||
public uint Length {
|
public uint Length {
|
||||||
get { return (uint)peStream.Length; }
|
get { return (uint)peStream.Length; }
|
||||||
}
|
}
|
||||||
|
@ -33,13 +71,6 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor {
|
||||||
void initialize(IPEImage peImage) {
|
void initialize(IPEImage peImage) {
|
||||||
this.peImage = peImage;
|
this.peImage = peImage;
|
||||||
this.peStream = peImage.CreateFullStream();
|
this.peStream = peImage.CreateFullStream();
|
||||||
|
|
||||||
//TODO: Only init this if they use the .NET MD
|
|
||||||
var dotNetDir = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[14];
|
|
||||||
if (dotNetDir.VirtualAddress != 0 && dotNetDir.Size >= 0x48) {
|
|
||||||
dnFile = DotNetFile.Load(peImage, false);
|
|
||||||
dotNetSection = findSection(dotNetDir.VirtualAddress);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageSectionHeader findSection(RVA rva) {
|
ImageSectionHeader findSection(RVA rva) {
|
||||||
|
@ -50,10 +81,66 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImageSectionHeader findSection(string name) {
|
||||||
|
foreach (var section in peImage.ImageSectionHeaders) {
|
||||||
|
if (section.DisplayName == name)
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readMethodTableRowTo(DumpedMethod dm, uint rid) {
|
||||||
|
dm.token = 0x06000000 + rid;
|
||||||
|
var row = DotNetFile.MetaData.TablesStream.ReadMethodRow(rid);
|
||||||
|
if (row == null)
|
||||||
|
throw new ArgumentException("Invalid Method rid");
|
||||||
|
dm.mdRVA = row.RVA;
|
||||||
|
dm.mdImplFlags = row.ImplFlags;
|
||||||
|
dm.mdFlags = row.Flags;
|
||||||
|
dm.mdName = row.Name;
|
||||||
|
dm.mdSignature = row.Signature;
|
||||||
|
dm.mdParamList = row.ParamList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateMethodHeaderInfo(DumpedMethod dm, MethodBodyHeader mbHeader) {
|
||||||
|
dm.mhFlags = mbHeader.flags;
|
||||||
|
dm.mhMaxStack = mbHeader.maxStack;
|
||||||
|
dm.mhCodeSize = dm.code == null ? 0 : (uint)dm.code.Length;
|
||||||
|
dm.mhLocalVarSigTok = mbHeader.localVarSigTok;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint rvaToOffset(uint rva) {
|
||||||
|
return (uint)peImage.ToFileOffset((RVA)rva);
|
||||||
|
}
|
||||||
|
|
||||||
static bool isInside(ImageSectionHeader section, uint offset, uint length) {
|
static bool isInside(ImageSectionHeader section, uint offset, uint length) {
|
||||||
return offset >= section.PointerToRawData && offset + length <= section.PointerToRawData + section.SizeOfRawData;
|
return offset >= section.PointerToRawData && offset + length <= section.PointerToRawData + section.SizeOfRawData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void writeUInt32(uint rva, uint data) {
|
||||||
|
offsetWriteUInt32(rvaToOffset(rva), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeUInt16(uint rva, ushort data) {
|
||||||
|
offsetWriteUInt16(rvaToOffset(rva), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte readByte(uint rva) {
|
||||||
|
return offsetReadByte(rvaToOffset(rva));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readInt32(uint rva) {
|
||||||
|
return (int)offsetReadUInt32(rvaToOffset(rva));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ushort readUInt16(uint rva) {
|
||||||
|
return offsetReadUInt16(rvaToOffset(rva));
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] readBytes(uint rva, int size) {
|
||||||
|
return offsetReadBytes(rvaToOffset(rva), size);
|
||||||
|
}
|
||||||
|
|
||||||
public void offsetWriteUInt32(uint offset, uint val) {
|
public void offsetWriteUInt32(uint offset, uint val) {
|
||||||
peImageData[offset + 0] = (byte)val;
|
peImageData[offset + 0] = (byte)val;
|
||||||
peImageData[offset + 1] = (byte)(val >> 8);
|
peImageData[offset + 1] = (byte)(val >> 8);
|
||||||
|
@ -99,14 +186,14 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool dotNetSafeWriteOffset(uint offset, byte[] data) {
|
public bool dotNetSafeWriteOffset(uint offset, byte[] data) {
|
||||||
if (dnFile != null) {
|
if (DotNetFile != null) {
|
||||||
uint length = (uint)data.Length;
|
uint length = (uint)data.Length;
|
||||||
|
|
||||||
if (!isInside(dotNetSection, offset, length))
|
if (!isInside(dotNetSection, offset, length))
|
||||||
return false;
|
return false;
|
||||||
if (intersect(offset, length, dnFile.MetaData.ImageCor20Header))
|
if (intersect(offset, length, DotNetFile.MetaData.ImageCor20Header))
|
||||||
return false;
|
return false;
|
||||||
if (intersect(offset, length, dnFile.MetaData.MetaDataHeader))
|
if (intersect(offset, length, DotNetFile.MetaData.MetaDataHeader))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,7 +181,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
// ...push args...
|
// ...push args...
|
||||||
// call Invoke
|
// call Invoke
|
||||||
abstract class ProxyCallFixer1 : ProxyCallFixerBase {
|
abstract class ProxyCallFixer1 : ProxyCallFixerBase {
|
||||||
FieldDefinitionAndDeclaringTypeDict<DelegateInfo> fieldToDelegateInfo = new FieldDefinitionAndDeclaringTypeDict<DelegateInfo>();
|
FieldDefAndDeclaringTypeDict<DelegateInfo> fieldToDelegateInfo = new FieldDefAndDeclaringTypeDict<DelegateInfo>();
|
||||||
|
|
||||||
protected ProxyCallFixer1(ModuleDefMD module)
|
protected ProxyCallFixer1(ModuleDefMD module)
|
||||||
: base(module) {
|
: base(module) {
|
||||||
|
@ -369,7 +369,7 @@ namespace de4dot.code.deobfuscators {
|
||||||
// ...push args...
|
// ...push args...
|
||||||
// call static method
|
// call static method
|
||||||
abstract class ProxyCallFixer2 : ProxyCallFixerBase {
|
abstract class ProxyCallFixer2 : ProxyCallFixerBase {
|
||||||
MethodDefinitionAndDeclaringTypeDict<DelegateInfo> proxyMethodToDelegateInfo = new MethodDefinitionAndDeclaringTypeDict<DelegateInfo>();
|
MethodDefAndDeclaringTypeDict<DelegateInfo> proxyMethodToDelegateInfo = new MethodDefAndDeclaringTypeDict<DelegateInfo>();
|
||||||
|
|
||||||
protected ProxyCallFixer2(ModuleDefMD module)
|
protected ProxyCallFixer2(ModuleDefMD module)
|
||||||
: base(module) {
|
: base(module) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace de4dot.code.deobfuscators.Rummage {
|
||||||
class StringDecrypter {
|
class StringDecrypter {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
MethodDef stringDecrypterMethod;
|
MethodDef stringDecrypterMethod;
|
||||||
FieldDefinitionAndDeclaringTypeDict<StringInfo> stringInfos = new FieldDefinitionAndDeclaringTypeDict<StringInfo>();
|
FieldDefAndDeclaringTypeDict<StringInfo> stringInfos = new FieldDefAndDeclaringTypeDict<StringInfo>();
|
||||||
int fileDispl;
|
int fileDispl;
|
||||||
uint[] key;
|
uint[] key;
|
||||||
BinaryReader reader;
|
BinaryReader reader;
|
||||||
|
|
|
@ -85,11 +85,11 @@ namespace de4dot.code.deobfuscators.Skater_NET {
|
||||||
protected override void scanForObfuscator() {
|
protected override void scanForObfuscator() {
|
||||||
stringDecrypter = new StringDecrypter(module);
|
stringDecrypter = new StringDecrypter(module);
|
||||||
|
|
||||||
if (hasAssemblyReference("Microsoft.VisualBasic"))
|
if (hasAssemblyRef("Microsoft.VisualBasic"))
|
||||||
stringDecrypter.find();
|
stringDecrypter.find();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasAssemblyReference(string name) {
|
bool hasAssemblyRef(string name) {
|
||||||
foreach (var asmRef in module.GetAssemblyRefs()) {
|
foreach (var asmRef in module.GetAssemblyRefs()) {
|
||||||
if (asmRef.Name == name)
|
if (asmRef.Name == name)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace de4dot.code.deobfuscators.Skater_NET {
|
||||||
ModuleDefMD module;
|
ModuleDefMD module;
|
||||||
TypeDef decrypterType;
|
TypeDef decrypterType;
|
||||||
MethodDef decrypterCctor;
|
MethodDef decrypterCctor;
|
||||||
FieldDefinitionAndDeclaringTypeDict<string> fieldToDecryptedString = new FieldDefinitionAndDeclaringTypeDict<string>();
|
FieldDefAndDeclaringTypeDict<string> fieldToDecryptedString = new FieldDefAndDeclaringTypeDict<string>();
|
||||||
bool canRemoveType;
|
bool canRemoveType;
|
||||||
IDecrypter decrypter;
|
IDecrypter decrypter;
|
||||||
|
|
||||||
|
|
|
@ -416,8 +416,8 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
if (decrypter.CanDecrypt) {
|
if (decrypter.CanDecrypt) {
|
||||||
var invokeMethod = info.GetStringDelegate == null ? null : info.GetStringDelegate.FindMethod("Invoke");
|
var invokeMethod = info.GetStringDelegate == null ? null : info.GetStringDelegate.FindMethod("Invoke");
|
||||||
staticStringInliner.add(invokeMethod, (method, gim, args) => {
|
staticStringInliner.add(invokeMethod, (method, gim, args) => {
|
||||||
var fieldDefinition = DotNetUtils.getField(module, (IField)args[0]);
|
var fieldDef = DotNetUtils.getField(module, (IField)args[0]);
|
||||||
return decrypter.decrypt(fieldDefinition.MDToken.ToInt32(), (int)args[1]);
|
return decrypter.decrypt(fieldDef.MDToken.ToInt32(), (int)args[1]);
|
||||||
});
|
});
|
||||||
staticStringInliner.add(info.StringDecrypterMethod, (method, gim, args) => {
|
staticStringInliner.add(info.StringDecrypterMethod, (method, gim, args) => {
|
||||||
return decrypter.decrypt(0, (int)args[0]);
|
return decrypter.decrypt(0, (int)args[0]);
|
||||||
|
|
|
@ -217,7 +217,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
|
|
||||||
// Find the string decrypter string offset value or null if none found
|
// Find the string decrypter string offset value or null if none found
|
||||||
int? findOffsetValue(MethodDef method) {
|
int? findOffsetValue(MethodDef method) {
|
||||||
var fieldDict = new FieldDefinitionAndDeclaringTypeDict<IField>();
|
var fieldDict = new FieldDefAndDeclaringTypeDict<IField>();
|
||||||
foreach (var field in method.DeclaringType.Fields)
|
foreach (var field in method.DeclaringType.Fields)
|
||||||
fieldDict.add(field, field);
|
fieldDict.add(field, field);
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ namespace de4dot.code.deobfuscators.SmartAssembly {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int? findOffsetValue(MethodDef method, FieldDef offsetField, FieldDefinitionAndDeclaringTypeDict<IField> fields) {
|
int? findOffsetValue(MethodDef method, FieldDef offsetField, FieldDefAndDeclaringTypeDict<IField> fields) {
|
||||||
var instructions = method.Body.Instructions;
|
var instructions = method.Body.Instructions;
|
||||||
for (int i = 0; i <= instructions.Count - 2; i++) {
|
for (int i = 0; i <= instructions.Count - 2; i++) {
|
||||||
var ldstr = instructions[i];
|
var ldstr = instructions[i];
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user