Merge branch 'master' into confuser
This commit is contained in:
commit
45d4367e3a
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,4 +7,3 @@
|
|||
/Debug/
|
||||
/Release/
|
||||
/de4dot.snk
|
||||
/cecil/
|
||||
|
|
6
.gitmodules
vendored
6
.gitmodules
vendored
|
@ -1,3 +1,3 @@
|
|||
[submodule "dot10"]
|
||||
path = dot10
|
||||
url = e:/work/dot10.git
|
||||
[submodule "dnlib"]
|
||||
path = dnlib
|
||||
url = git@bitbucket.org:0xd4d/dnlib.git
|
||||
|
|
|
@ -74,9 +74,9 @@
|
|||
<Project>{5C93C5E2-196F-4877-BF65-96FEBFCEFCA1}</Project>
|
||||
<Name>de4dot.mdecrypt</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\dot10\src\dot10.csproj">
|
||||
<ProjectReference Include="..\dnlib\src\dnlib.csproj">
|
||||
<Project>{FDFC1237-143F-4919-8318-4926901F4639}</Project>
|
||||
<Name>dot10</Name>
|
||||
<Name>dnlib</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
|
|
@ -21,7 +21,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
using de4dot.mdecrypt;
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
using de4dot.mdecrypt;
|
||||
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
|
|
|
@ -22,19 +22,19 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using dot10.DotNet.Emit;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
using OpCode = dot10.DotNet.Emit.OpCode;
|
||||
using OpCodes = dot10.DotNet.Emit.OpCodes;
|
||||
using OperandType = dot10.DotNet.Emit.OperandType;
|
||||
using OpCode = dnlib.DotNet.Emit.OpCode;
|
||||
using OpCodes = dnlib.DotNet.Emit.OpCodes;
|
||||
using OperandType = dnlib.DotNet.Emit.OperandType;
|
||||
using ROpCode = System.Reflection.Emit.OpCode;
|
||||
using ROpCodes = System.Reflection.Emit.OpCodes;
|
||||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
class CodeGenerator {
|
||||
static Dictionary<OpCode, ROpCode> dot10ToReflection = new Dictionary<OpCode, ROpCode>();
|
||||
static Dictionary<OpCode, ROpCode> dnlibToReflection = new Dictionary<OpCode, ROpCode>();
|
||||
static CodeGenerator() {
|
||||
var refDict = new Dictionary<short, ROpCode>(0x100);
|
||||
foreach (var f in typeof(ROpCodes).GetFields(BindingFlags.Static | BindingFlags.Public)) {
|
||||
|
@ -51,7 +51,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
ROpCode ropcode;
|
||||
if (!refDict.TryGetValue(opcode.Value, out ropcode))
|
||||
continue;
|
||||
dot10ToReflection[opcode] = ropcode;
|
||||
dnlibToReflection[opcode] = ropcode;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,7 +332,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
|
||||
ROpCode convertOpCode(OpCode opcode) {
|
||||
ROpCode ropcode;
|
||||
if (dot10ToReflection.TryGetValue(opcode, out ropcode))
|
||||
if (dnlibToReflection.TryGetValue(opcode, out ropcode))
|
||||
return ropcode;
|
||||
return ROpCodes.Nop;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
using System.Reflection;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
class MField {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
using System.Reflection;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
class MMethod {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
|
|
|
@ -22,12 +22,12 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using dot10.DotNet.Emit;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
using OpCode = dot10.DotNet.Emit.OpCode;
|
||||
using OpCodes = dot10.DotNet.Emit.OpCodes;
|
||||
using OpCode = dnlib.DotNet.Emit.OpCode;
|
||||
using OpCodes = dnlib.DotNet.Emit.OpCodes;
|
||||
using ROpCode = System.Reflection.Emit.OpCode;
|
||||
using ROpCodes = System.Reflection.Emit.OpCodes;
|
||||
|
||||
|
@ -251,7 +251,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
if (calledMethod.DeclaringType.DefinitionAssembly.IsCorLib()) {
|
||||
var calledMethodFullName = calledMethod.FullName;
|
||||
if (calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetAssembly(System.Type)") {
|
||||
block.replace(i, 1, Instruction.Create(OpCodes.Nop));
|
||||
block.replace(i, 1, OpCodes.Nop.ToInstruction());
|
||||
insertLoadThis(block, i + 1);
|
||||
insertCallOurMethod(block, i + 2, "static_rtGetAssembly_TypeArg");
|
||||
i += 2;
|
||||
|
@ -260,9 +260,9 @@ namespace AssemblyData.methodsrewriter {
|
|||
else if (calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetCallingAssembly()" ||
|
||||
calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetEntryAssembly()" ||
|
||||
calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetExecutingAssembly()") {
|
||||
block.replace(i, 1, Instruction.Create(OpCodes.Nop));
|
||||
block.replace(i, 1, OpCodes.Nop.ToInstruction());
|
||||
insertLoadThis(block, i + 1);
|
||||
block.insert(i + 2, Instruction.Create(OpCodes.Ldc_I4, currentMethodInfo.delegateIndex));
|
||||
block.insert(i + 2, OpCodes.Ldc_I4.ToInstruction(currentMethodInfo.delegateIndex));
|
||||
insertCallOurMethod(block, i + 3, "rtGetAssembly");
|
||||
i += 3;
|
||||
continue;
|
||||
|
@ -274,32 +274,32 @@ namespace AssemblyData.methodsrewriter {
|
|||
createMethod(method.methodBase);
|
||||
var newMethodInfo = realMethodToNewMethod[method.methodBase];
|
||||
|
||||
block.replace(i, 1, Instruction.Create(OpCodes.Nop));
|
||||
block.replace(i, 1, OpCodes.Nop.ToInstruction());
|
||||
int n = i + 1;
|
||||
|
||||
// Pop all pushed args to a temp array
|
||||
var mparams = getParameters(method.methodDef);
|
||||
if (mparams.Count > 0) {
|
||||
block.insert(n++, Instruction.Create(OpCodes.Ldc_I4, mparams.Count));
|
||||
block.insert(n++, OpCodes.Ldc_I4.ToInstruction(mparams.Count));
|
||||
var objectType = method.methodDef.DeclaringType.Module.CorLibTypes.Object;
|
||||
block.insert(n++, Instruction.Create(OpCodes.Newarr, objectType));
|
||||
block.insert(n++, OpCodes.Newarr.ToInstruction(objectType));
|
||||
block.insert(n++, create(OpCodes.Stloc, new Operand(Operand.Type.TempObjArray)));
|
||||
|
||||
for (int j = mparams.Count - 1; j >= 0; j--) {
|
||||
var argType = mparams[j];
|
||||
if (argType.RemovePinnedAndModifiers().IsValueType)
|
||||
block.insert(n++, Instruction.Create(OpCodes.Box, ((TypeDefOrRefSig)argType).TypeDefOrRef));
|
||||
block.insert(n++, OpCodes.Box.ToInstruction(((TypeDefOrRefSig)argType).TypeDefOrRef));
|
||||
block.insert(n++, create(OpCodes.Stloc, new Operand(Operand.Type.TempObj)));
|
||||
block.insert(n++, create(OpCodes.Ldloc, new Operand(Operand.Type.TempObjArray)));
|
||||
block.insert(n++, Instruction.Create(OpCodes.Ldc_I4, j));
|
||||
block.insert(n++, OpCodes.Ldc_I4.ToInstruction(j));
|
||||
block.insert(n++, create(OpCodes.Ldloc, new Operand(Operand.Type.TempObj)));
|
||||
block.insert(n++, Instruction.Create(OpCodes.Stelem_Ref));
|
||||
block.insert(n++, OpCodes.Stelem_Ref.ToInstruction());
|
||||
}
|
||||
}
|
||||
|
||||
// Push delegate instance
|
||||
insertLoadThis(block, n++);
|
||||
block.insert(n++, Instruction.Create(OpCodes.Ldc_I4, newMethodInfo.delegateIndex));
|
||||
block.insert(n++, OpCodes.Ldc_I4.ToInstruction(newMethodInfo.delegateIndex));
|
||||
insertCallOurMethod(block, n++, "rtGetDelegateInstance");
|
||||
block.insert(n++, create(OpCodes.Castclass, new Operand(Operand.Type.ReflectionType, newMethodInfo.delegateType)));
|
||||
|
||||
|
@ -307,11 +307,11 @@ namespace AssemblyData.methodsrewriter {
|
|||
if (mparams.Count > 0) {
|
||||
for (int j = 0; j < mparams.Count; j++) {
|
||||
block.insert(n++, create(OpCodes.Ldloc, new Operand(Operand.Type.TempObjArray)));
|
||||
block.insert(n++, Instruction.Create(OpCodes.Ldc_I4, j));
|
||||
block.insert(n++, Instruction.Create(OpCodes.Ldelem_Ref));
|
||||
block.insert(n++, OpCodes.Ldc_I4.ToInstruction(j));
|
||||
block.insert(n++, OpCodes.Ldelem_Ref.ToInstruction());
|
||||
var argType = mparams[j];
|
||||
if (argType.RemovePinnedAndModifiers().IsValueType)
|
||||
block.insert(n++, Instruction.Create(OpCodes.Unbox_Any, ((TypeDefOrRefSig)argType).TypeDefOrRef));
|
||||
block.insert(n++, OpCodes.Unbox_Any.ToInstruction(((TypeDefOrRefSig)argType).TypeDefOrRef));
|
||||
else {
|
||||
// Don't cast it to its correct type. This will sometimes cause
|
||||
// an exception in some EF obfuscated assembly since we'll be
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
|
@ -40,7 +40,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
if (!fields.TryGetValue(fieldRef.Name.String, out list))
|
||||
return null;
|
||||
|
||||
fieldRef = GenericArgsSubstitutor.create(fieldRef, fieldRef.DeclaringType.ToGenericInstSig());
|
||||
fieldRef = GenericArgsSubstitutor.create(fieldRef, fieldRef.DeclaringType.TryGetGenericInstSig());
|
||||
|
||||
foreach (var field in list) {
|
||||
if (ResolverUtils.compareFields(field, fieldRef))
|
||||
|
@ -71,7 +71,7 @@ namespace AssemblyData.methodsrewriter {
|
|||
if (!methods.TryGetValue(methodRef.Name.String, out list))
|
||||
return null;
|
||||
|
||||
methodRef = GenericArgsSubstitutor.create(methodRef, methodRef.DeclaringType.ToGenericInstSig());
|
||||
methodRef = GenericArgsSubstitutor.create(methodRef, methodRef.DeclaringType.TryGetGenericInstSig());
|
||||
|
||||
foreach (var method in list) {
|
||||
if (ResolverUtils.compareMethods(method, methodRef))
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace AssemblyData.methodsrewriter {
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -17,6 +17,6 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
</LICENSE>
|
||||
|
||||
Official site: https://github.com/0xd4d/de4dot
|
||||
Official site: https://bitbucket.org/0xd4d/de4dot
|
||||
|
||||
See the file COPYING for more details.
|
||||
|
|
24
LICENSE.dnlib.txt
Normal file
24
LICENSE.dnlib.txt
Normal file
|
@ -0,0 +1,24 @@
|
|||
<LICENSE>
|
||||
Copyright (C) 2012 de4dot@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
</LICENSE>
|
||||
|
||||
Official site: https://bitbucket.org/0xd4d/dnlib
|
259
README.md
259
README.md
|
@ -0,0 +1,259 @@
|
|||
Description
|
||||
===========
|
||||
|
||||
de4dot is an open source (GPLv3) .NET deobfuscator and unpacker written in C#. It will try its best to restore a packed and obfuscated assembly to almost the original assembly. Most of the obfuscation can be completely restored (eg. string encryption), but symbol renaming is impossible to restore since the original names aren't (usually) part of the obfuscated assembly.
|
||||
|
||||
Features
|
||||
========
|
||||
|
||||
Here's a pseudo random list of the things it will do depending on what obfuscator was used to obfuscate an assembly:
|
||||
|
||||
* Inline methods. Some obfuscators move small parts of a method to another static method and calls it.
|
||||
* Decrypt strings statically or dynamically
|
||||
* Decrypt other constants. Some obfuscators can also encrypt other constants, such as all integers, all doubles, etc.
|
||||
* Decrypt methods statically or dynamically
|
||||
* Remove proxy methods. Many obfuscators replace most/all call instructions with a call to a delegate. This delegate in turn calls the real method.
|
||||
* Rename symbols. Even though most symbols can't be restored, it will rename them to human readable strings. Sometimes, some of the original names can be restored, though.
|
||||
* Devirtualize virtualized code
|
||||
* Decrypt resources. Many obfuscators have an option to encrypt .NET resources.
|
||||
* Decrypt embedded files. Many obfuscators have an option to embed and possibly encrypt/compress other assemblies.
|
||||
* Remove tamper detection code
|
||||
* Remove anti-debug code
|
||||
* Control flow deobfuscation. Many obfuscators modify the IL code so it looks like spaghetti code making it very difficult to understand the code.
|
||||
* Restore class fields. Some obfuscators can move fields from one class to some other obfuscator created class.
|
||||
* Convert a PE exe to a .NET exe. Some obfuscators wrap a .NET assembly inside a Win32 PE so a .NET decompiler can't read the file.
|
||||
* Removes most/all junk classes added by the obfuscator.
|
||||
* Fixes some peverify errors. Many of the obfuscators are buggy and create unverifiable code by mistake.
|
||||
* Restore the types of method parameters and fields
|
||||
|
||||
|
||||
Supported obfuscators/packers
|
||||
=============================
|
||||
|
||||
* Agile.NET (aka CliSecure)
|
||||
* Babel.NET
|
||||
* CodeFort
|
||||
* CodeVeil
|
||||
* CodeWall
|
||||
* CryptoObfuscator
|
||||
* DeepSea Obfuscator
|
||||
* Dotfuscator
|
||||
* .NET Reactor
|
||||
* Eazfuscator.NET
|
||||
* Goliath.NET
|
||||
* ILProtector
|
||||
* MaxtoCode
|
||||
* MPRESS
|
||||
* Rummage
|
||||
* Skater.NET
|
||||
* SmartAssembly
|
||||
* Spices.Net
|
||||
* Xenocode
|
||||
|
||||
Some of the above obfuscators are rarely used (eg. Goliath.NET), so they have had much less testing. Help me out by reporting bugs or problems you find.
|
||||
|
||||
How to use de4dot
|
||||
=================
|
||||
|
||||
N00b users
|
||||
----------
|
||||
|
||||
Drag and drop the file(s) onto de4dot.exe and wait a few seconds.
|
||||
|
||||
Deobfuscate more than one file at a time
|
||||
----------------------------------------
|
||||
|
||||
When more than one assembly has been obfuscated, it's very likely that you must deobfuscate them all at the same time unless you disable symbol renaming. The reason is that if assembly A has a reference to class C in assembly B, and you rename symbols only in assembly B, then class C could be renamed to eg. Class0 but the reference in assembly A still references a class called C in assembly B. If you deobfuscate both assemblies at the same time, all references will also be updated.
|
||||
|
||||
Find all obfuscated files and deobfuscate them
|
||||
----------------------------------------------
|
||||
|
||||
The following command line will deobfuscate all assemblies that have been obfuscated by a supported obfuscator and save the assemblies to `c:\output`
|
||||
|
||||
de4dot -r c:\input -ru -ro c:\output
|
||||
|
||||
`-r` means recursive search. `-ru` means it should ignore unknown files. `-ro` means it should place the output files in the following directory. Typically, you'd first copy `c:\input` to `c:\output`, and then run the command. That way all the files will be in `c:\output`, even non-assemblies and non-processed assemblies. When de4dot is finished, you'd just double click the main assembly in `c:\output` and it should hopefully start.
|
||||
|
||||
Detect obfuscator
|
||||
-----------------
|
||||
|
||||
Use the `-d` option to detect the obfuscator without deobfuscating any assembly.
|
||||
|
||||
Find all .NET assemblies and detect obfuscator. If it's an unsupported obfuscator or if it's not obfuscated, it will print "Unknown obfuscator".
|
||||
|
||||
de4dot -d -r c:\input
|
||||
|
||||
Same as above except that it will only show which files have been obfuscated by a supported obfuscator.
|
||||
|
||||
de4dot -d -r c:\input -ru
|
||||
|
||||
Detect obfuscator
|
||||
|
||||
de4dot -d file1.dll file2.dll file3.dll
|
||||
|
||||
Preserving metadata tokens
|
||||
--------------------------
|
||||
|
||||
Sometimes in rare cases, you'd want to preserve the metadata tokens. Use `--preserve-tokens` or `--preserve-table`. Also consider using `--keep-types` since it won't remove any types and methods added by the obfuscator. Another useful option is `--dont-create-params`. If used, the renamer won't create Param rows for method parameters that don't have a Param row. That way the ParamPtr table won't be added to your assemblies. Peverify has a bug and doesn't support it (you'll see lots of "errors").
|
||||
|
||||
The #Strings, #US and #Blob heaps can also be preserved by using `--preserve-strings`, `--preserve-us`, and `--preserve-blob` respectively. Of these three, `--preserve-us` is the most useful one since `ldstr` instruction and `module.ResolveString()` directly reference the #US heap.
|
||||
|
||||
`--preserve-sig-data` should be used if the obfuscator adds extra data at the end of signatures that it uses for its own purpose, eg. as decryption keys. Confuser is one obfuscator that does this.
|
||||
|
||||
`--preserve-tokens` preserves all important tokens but will also enable `--preserve-us`, `--preserve-blob` and `--preserve-sig-data`.
|
||||
|
||||
If it's detected as an unknown (unsupported) obfuscator (or if you force it with `-p un`), all tokens are preserved, including the #US heap and any extra data at the end of signatures. Also, no obfuscator types, fields or methods are removed.
|
||||
|
||||
Preserve all important tokens, #US, #Blob, extra sig data.
|
||||
|
||||
de4dot --preserve-tokens file1.dll
|
||||
|
||||
Preserve all important tokens, #US, #Blob, extra sig data and don't remove types/fields added by the obfuscator
|
||||
|
||||
de4dot --keep-types --preserve-tokens file1.dll
|
||||
|
||||
Preserve all important tokens, #US, #Blob, extra sig data and don't create extra Param rows to prevent the ParamPtr table from being created.
|
||||
|
||||
de4dot --dont-create-params --preserve-tokens file1.dll
|
||||
|
||||
Preserve all important tokens except the Param tokens.
|
||||
|
||||
de4dot --preserve-table all,-pd file1.dll
|
||||
|
||||
Dynamically decrypting strings
|
||||
------------------------------
|
||||
|
||||
Although `de4dot` supports a lot of obfuscators, there's still some it doesn't support. To decrypt strings, you'll first need to figure out which method or methods decrypt strings. To get the method token of these string decrypters, you can use ILDASM with the 'show metadata tokens' option enabled. A method token is a 32-bit number and begins with 06, eg. 06012345.
|
||||
|
||||
This command will load assembly file1.dll into memory by calling `Assembly.Load()`. When it detects calls to the two string decrypters (06012345 and 060ABCDE), it will call them by creating a dynamic method, and save the result (the decrypted string). The call to the string decrypter will be removed and the decrypted string will be in its place.
|
||||
|
||||
de4dot file1.dll --strtyp delegate --strtok 06012345 --strtok 060ABCDE
|
||||
|
||||
Since the assembly is loaded and executed, make sure you run this in a sandbox if you suspect the file to be malware.
|
||||
|
||||
Forcing detection of a certain obfuscator
|
||||
-----------------------------------------
|
||||
|
||||
`de4dot` isn't perfect. If it fails to detect an obfuscator, you can use the `-p` option to force it to assume it's been obfuscated by it.
|
||||
|
||||
Force SmartAssembly
|
||||
|
||||
de4dot file1.dll -p sa
|
||||
|
||||
Force unsupported obfuscator
|
||||
|
||||
de4dot file1.dll -p un
|
||||
|
||||
For other obfuscator types, see the help screen.
|
||||
|
||||
Disabling symbol renaming
|
||||
-------------------------
|
||||
|
||||
Renaming symbols isn't as easy as renaming A to B when reflection is involved. `de4dot` currently doesn't support renaming XAML so if you suspect that it uses WPF (or if it's a Silverlight app) you should disable renaming if the assembly fails to run.
|
||||
|
||||
de4dot --dont-rename file1.dll file2.dll
|
||||
|
||||
`--keep-names` can also be used to tell `de4dot` not to rename certain symbols, eg. "don't rename fields".
|
||||
|
||||
Rename everything that should be renamed except properties, events and methods.
|
||||
|
||||
de4dot --keep-names pem file1.dll
|
||||
|
||||
Using a different rename regex
|
||||
------------------------------
|
||||
|
||||
The default regexes should be enough, except possibly the one that is used when an unsupported obfuscator is detected. To see all default regexes, start `de4dot` without any arguments and it will list all options and all default values.
|
||||
|
||||
Eg., currently the following is the default regex used when Dotfuscator is detected
|
||||
|
||||
!^[a-z][a-z0-9]{0,2}$&!^A_[0-9]+$&^[a-zA-Z_<{$][a-zA-Z_0-9<>{}$.`-]*$
|
||||
|
||||
As you can see, it's not just one regex, it's more than one. Each is separated by `&` and each regex can be negated by using `!` in front of it. To show it more clearly, these regexes are used:
|
||||
|
||||
(negated) ^[a-z][a-z0-9]{0,2}$
|
||||
(negated) ^A_[0-9]+$
|
||||
^[a-zA-Z_<{$][a-zA-Z_0-9<>{}$.`-]*$
|
||||
|
||||
To change the regex(es), you must know the short type name of the obfuscator (see help screen). Eg. it's `sa` if it's SmartAssembly, and `un` if it's an unsupported/unknown obfuscator. The option to use is `--TYPE-name` (eg. `--sa-name` for SmartAssembly and `--un-name` for unknown/unsupported obfuscators):
|
||||
|
||||
de4dot --un-name "^[a-zA-Z]\w*$" file1.dll
|
||||
|
||||
Other options
|
||||
-------------
|
||||
|
||||
Start `de4dot` without any arguments and it will show all options.
|
||||
|
||||
Tiny FAQ
|
||||
========
|
||||
|
||||
Is this a cracker only tool?
|
||||
----------------------------
|
||||
|
||||
Of course. Not. Here's some legitimate uses of this software:
|
||||
|
||||
* Malware analysis
|
||||
|
||||
Many malware try to protect against analysis. They think obfuscating the code makes it hard. Mistake no. 1 was to use .NET.
|
||||
|
||||
* Speed up a program / use less memory
|
||||
|
||||
Unless only symbol renaming was used, the obfuscated assembly is usually slower and requires more memory at runtime compared to the original assembly. By unpacking and deobfuscating it, the program's memory usage and speed will be almost identical to the original program.
|
||||
|
||||
* Make the assembly compatible with mono
|
||||
|
||||
Most obfuscators don't support mono, even if the original assembly does. By unpacking and deobfuscating it, mono support will be restored.
|
||||
|
||||
* You lost your source code and only have the obfuscated .NET assemblies
|
||||
|
||||
By unpacking and deobfuscating your assemblies, you can then use any .NET decompiler (eg. the open source ILSpy) to get back your source code.
|
||||
|
||||
* Obfuscator created unverifiable code but code must be verifiable
|
||||
|
||||
Some of the obfuscators are buggy and create unverifiable code due to bugs in the software. Some of these errors are fixed by de4dot.
|
||||
|
||||
|
||||
I've "protected" my app with some obfuscator but I just found out about de4dot. Is .NET obfuscation useless?
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Yes. It's simply way too easy to restore most of these "protections".
|
||||
|
||||
|
||||
What do you think of these obfuscators? They're good, right?
|
||||
------------------------------------------------------------
|
||||
|
||||
:D
|
||||
|
||||
Speaking from experience with a lot of obfuscators, I can say that their protection is really weak. You see the same weak "protection" in pretty much every obfuscator. Copying ideas from other obfuscators seems to be their best skill.
|
||||
|
||||
99% of the people working for these companies have absolutely no experience in reverse engineering. If you have no experience in what is a good or a bad protection, it's very unlikely that you're able to write a good protection.
|
||||
|
||||
To show you an example, most obfuscators can encrypt all the strings in your assemblies. What they fail to tell you is that it's child's play to decrypt the strings. Here's an example from SecureTeam's Agile.NET (aka CliSecure). de4dot's Agile.NET string decrypter code is only 85 lines long, and that includes the GPLv3 comment at the top of the file and the code that detects the string decrypter in the assembly!
|
||||
|
||||
The actual string decrypter code is 4 lines long, and it's a simple XOR loop! When Agile.NET (aka CliSecure) encrypts your strings, it replaces the original strings with an XOR'd copy, and adds a call to their string decrypter. This decrypter merely XOR's every character and returns the decrypted string. Here's the string decrypter code de4dot uses:
|
||||
|
||||
:::C#
|
||||
public string decrypt(string es) {
|
||||
char[] buf = new char[es.Length];
|
||||
for (int i = 0; i < es.Length; i++)
|
||||
buf[i] = (char)(es[i] ^ stringDecrypterKey[i % stringDecrypterKey.Length]);
|
||||
return new string(buf);
|
||||
}
|
||||
|
||||
Your code might look like this:
|
||||
|
||||
:::C#
|
||||
string myString = "Hello World";
|
||||
|
||||
and the obfuscator (eg. Agile.NET / CliSecure) will replace that with something similar to this:
|
||||
|
||||
:::C#
|
||||
string myString = DecryptClass.decrypt("AoF41Fk5422");
|
||||
|
||||
Yes, Agile.NET's string encryption feature really is this bad! I bet you that none of their customers knows about this. And SecureTeam sure wants to keep it that way. :)
|
||||
|
||||
Even though most of the other obfuscators' string encryption feature isn't as bad as Agile.NET's string encryption, they still have one thing in common: it's very easy to decrypt the strings again.
|
||||
|
||||
I must use .NET so what's the best protection?
|
||||
----------------------------------------------
|
||||
|
||||
If you don't count "don't distribute it" as a solution, the best obfuscator feature is symbol renaming. It's impossible to restore the symbols unless they're part of the assembly. All of the other "protections" are 100% reversible.
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -17,20 +17,6 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
How to test it:
|
||||
- Compile this assembly and the other test assembly
|
||||
- Force rename of everything (set name regex to eg. .*)
|
||||
- Run peverify /IL /MD on both files
|
||||
- Decompile them and create a solution for both projects. I recommend using ILSpy.
|
||||
- Compile with VS. If it fails to build, make sure the decompiler isn't buggy.
|
||||
- Some manual inspection may be required as well even if it builds 100%.
|
||||
|
||||
Yes, it's not 100% automated. You get what you pay for! Buy something
|
||||
nice with the money you saved.
|
||||
*/
|
||||
|
||||
namespace Test.Rename {
|
||||
namespace test1 {
|
||||
public class Class1 : Test.Rename.Dll.test.pub1.Class1 {
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
public class Block : BaseBlock {
|
||||
|
@ -52,7 +52,7 @@ namespace de4dot.blocks {
|
|||
public Instr FirstInstr {
|
||||
get {
|
||||
if (instructions.Count == 0)
|
||||
add(new Instr(Instruction.Create(OpCodes.Nop)));
|
||||
add(new Instr(OpCodes.Nop.ToInstruction()));
|
||||
return instructions[0];
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ namespace de4dot.blocks {
|
|||
public Instr LastInstr {
|
||||
get {
|
||||
if (instructions.Count == 0)
|
||||
add(new Instr(Instruction.Create(OpCodes.Nop)));
|
||||
add(new Instr(OpCodes.Nop.ToInstruction()));
|
||||
return instructions[instructions.Count - 1];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
public class Blocks {
|
||||
|
@ -171,16 +171,16 @@ namespace de4dot.blocks {
|
|||
case Code.Ldloc_2:
|
||||
case Code.Ldloc_3:
|
||||
if (newIndex == 0)
|
||||
return Instruction.Create(OpCodes.Ldloc_0);
|
||||
return OpCodes.Ldloc_0.ToInstruction();
|
||||
if (newIndex == 1)
|
||||
return Instruction.Create(OpCodes.Ldloc_1);
|
||||
return OpCodes.Ldloc_1.ToInstruction();
|
||||
if (newIndex == 2)
|
||||
return Instruction.Create(OpCodes.Ldloc_2);
|
||||
return OpCodes.Ldloc_2.ToInstruction();
|
||||
if (newIndex == 3)
|
||||
return Instruction.Create(OpCodes.Ldloc_3);
|
||||
return OpCodes.Ldloc_3.ToInstruction();
|
||||
if (newIndex <= 0xFF)
|
||||
return Instruction.Create(OpCodes.Ldloc_S, local);
|
||||
return Instruction.Create(OpCodes.Ldloc, local);
|
||||
return OpCodes.Ldloc_S.ToInstruction(local);
|
||||
return OpCodes.Ldloc.ToInstruction(local);
|
||||
|
||||
case Code.Stloc:
|
||||
case Code.Stloc_S:
|
||||
|
@ -189,22 +189,22 @@ namespace de4dot.blocks {
|
|||
case Code.Stloc_2:
|
||||
case Code.Stloc_3:
|
||||
if (newIndex == 0)
|
||||
return Instruction.Create(OpCodes.Stloc_0);
|
||||
return OpCodes.Stloc_0.ToInstruction();
|
||||
if (newIndex == 1)
|
||||
return Instruction.Create(OpCodes.Stloc_1);
|
||||
return OpCodes.Stloc_1.ToInstruction();
|
||||
if (newIndex == 2)
|
||||
return Instruction.Create(OpCodes.Stloc_2);
|
||||
return OpCodes.Stloc_2.ToInstruction();
|
||||
if (newIndex == 3)
|
||||
return Instruction.Create(OpCodes.Stloc_3);
|
||||
return OpCodes.Stloc_3.ToInstruction();
|
||||
if (newIndex <= 0xFF)
|
||||
return Instruction.Create(OpCodes.Stloc_S, local);
|
||||
return Instruction.Create(OpCodes.Stloc, local);
|
||||
return OpCodes.Stloc_S.ToInstruction(local);
|
||||
return OpCodes.Stloc.ToInstruction(local);
|
||||
|
||||
case Code.Ldloca_S:
|
||||
case Code.Ldloca:
|
||||
if (newIndex <= 0xFF)
|
||||
return Instruction.Create(OpCodes.Ldloca_S, local);
|
||||
return Instruction.Create(OpCodes.Ldloca, local);
|
||||
return OpCodes.Ldloca_S.ToInstruction(local);
|
||||
return OpCodes.Ldloca.ToInstruction(local);
|
||||
|
||||
default:
|
||||
throw new ApplicationException("Invalid ld/st local instruction");
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
class CodeGenerator {
|
||||
|
@ -73,79 +73,9 @@ namespace de4dot.blocks {
|
|||
sortExceptions();
|
||||
layOutInstructions(out allInstructions, out allExceptionHandlers);
|
||||
|
||||
foreach (var instr in allInstructions) {
|
||||
if (instr.OpCode == OpCodes.Br_S) instr.OpCode = OpCodes.Br;
|
||||
else if (instr.OpCode == OpCodes.Brfalse_S) instr.OpCode = OpCodes.Brfalse;
|
||||
else if (instr.OpCode == OpCodes.Brtrue_S) instr.OpCode = OpCodes.Brtrue;
|
||||
else if (instr.OpCode == OpCodes.Beq_S) instr.OpCode = OpCodes.Beq;
|
||||
else if (instr.OpCode == OpCodes.Bge_S) instr.OpCode = OpCodes.Bge;
|
||||
else if (instr.OpCode == OpCodes.Bgt_S) instr.OpCode = OpCodes.Bgt;
|
||||
else if (instr.OpCode == OpCodes.Ble_S) instr.OpCode = OpCodes.Ble;
|
||||
else if (instr.OpCode == OpCodes.Blt_S) instr.OpCode = OpCodes.Blt;
|
||||
else if (instr.OpCode == OpCodes.Bne_Un_S) instr.OpCode = OpCodes.Bne_Un;
|
||||
else if (instr.OpCode == OpCodes.Bge_Un_S) instr.OpCode = OpCodes.Bge_Un;
|
||||
else if (instr.OpCode == OpCodes.Bgt_Un_S) instr.OpCode = OpCodes.Bgt_Un;
|
||||
else if (instr.OpCode == OpCodes.Ble_Un_S) instr.OpCode = OpCodes.Ble_Un;
|
||||
else if (instr.OpCode == OpCodes.Blt_Un_S) instr.OpCode = OpCodes.Blt_Un;
|
||||
else if (instr.OpCode == OpCodes.Leave_S) instr.OpCode = OpCodes.Leave;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (!optimizeBranches(allInstructions))
|
||||
break;
|
||||
}
|
||||
|
||||
recalculateInstructionOffsets(allInstructions);
|
||||
}
|
||||
|
||||
void recalculateInstructionOffsets(IList<Instruction> allInstructions) {
|
||||
uint offset = 0;
|
||||
foreach (var instr in allInstructions) {
|
||||
instr.Offset = offset;
|
||||
offset += (uint)instr.GetSize();
|
||||
}
|
||||
}
|
||||
|
||||
bool getShortBranch(Instruction instruction, out OpCode opcode) {
|
||||
switch (instruction.OpCode.Code) {
|
||||
case Code.Br: opcode = OpCodes.Br_S; return true;
|
||||
case Code.Brfalse: opcode = OpCodes.Brfalse_S; return true;
|
||||
case Code.Brtrue: opcode = OpCodes.Brtrue_S; return true;
|
||||
case Code.Beq: opcode = OpCodes.Beq_S; return true;
|
||||
case Code.Bge: opcode = OpCodes.Bge_S; return true;
|
||||
case Code.Bgt: opcode = OpCodes.Bgt_S; return true;
|
||||
case Code.Ble: opcode = OpCodes.Ble_S; return true;
|
||||
case Code.Blt: opcode = OpCodes.Blt_S; return true;
|
||||
case Code.Bne_Un: opcode = OpCodes.Bne_Un_S; return true;
|
||||
case Code.Bge_Un: opcode = OpCodes.Bge_Un_S; return true;
|
||||
case Code.Bgt_Un: opcode = OpCodes.Bgt_Un_S; return true;
|
||||
case Code.Ble_Un: opcode = OpCodes.Ble_Un_S; return true;
|
||||
case Code.Blt_Un: opcode = OpCodes.Blt_Un_S; return true;
|
||||
case Code.Leave: opcode = OpCodes.Leave_S; return true;
|
||||
default: opcode = OpCodes.Nop; return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if something was changed
|
||||
bool optimizeBranches(IList<Instruction> allInstructions) {
|
||||
bool changed = false;
|
||||
|
||||
recalculateInstructionOffsets(allInstructions);
|
||||
for (int i = 0; i < allInstructions.Count; i++) {
|
||||
var instruction = allInstructions[i];
|
||||
OpCode opcode;
|
||||
if (getShortBranch(instruction, out opcode)) {
|
||||
const int instrSize = 5; // It's a long branch instruction
|
||||
var target = (Instruction)instruction.Operand;
|
||||
int distance = target == null ? int.MaxValue : (int)(target.Offset - (instruction.Offset + instrSize));
|
||||
if (-0x80 <= distance && distance <= 0x7F) {
|
||||
instruction.OpCode = opcode;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
allInstructions.SimplifyBranches();
|
||||
allInstructions.OptimizeBranches();
|
||||
allInstructions.UpdateInstructionOffsets();
|
||||
}
|
||||
|
||||
class BlockInfo {
|
||||
|
@ -185,7 +115,7 @@ namespace de4dot.blocks {
|
|||
block.LastInstr.updateTargets(new List<Instr> { block.Targets[0].FirstInstr });
|
||||
}
|
||||
else if (block.FallThrough != null && block.FallThrough != next) {
|
||||
var instr = new Instr(Instruction.Create(OpCodes.Br, block.FallThrough.FirstInstr.Instruction));
|
||||
var instr = new Instr(OpCodes.Br.ToInstruction(block.FallThrough.FirstInstr.Instruction));
|
||||
instr.updateTargets(new List<Instr> { block.FallThrough.FirstInstr });
|
||||
allInstructions.Add(instr.Instruction);
|
||||
}
|
||||
|
@ -257,7 +187,7 @@ namespace de4dot.blocks {
|
|||
void fixEmptyBlocks() {
|
||||
foreach (var block in methodBlocks.getAllBlocks()) {
|
||||
if (block.Instructions.Count == 0) {
|
||||
block.Instructions.Add(new Instr(Instruction.Create(OpCodes.Nop)));
|
||||
block.Instructions.Add(new Instr(OpCodes.Nop.ToInstruction()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
public enum FrameworkType {
|
||||
|
@ -153,7 +153,7 @@ namespace de4dot.blocks {
|
|||
public static MethodDef getPInvokeMethod(TypeDef type, string methodName) {
|
||||
if (type == null)
|
||||
return null;
|
||||
var mname = new UTF8String(methodName);
|
||||
UTF8String mname = methodName;
|
||||
foreach (var method in type.Methods) {
|
||||
if (method.ImplMap == null)
|
||||
continue;
|
||||
|
@ -190,7 +190,7 @@ namespace de4dot.blocks {
|
|||
return null;
|
||||
if (method is MethodDef)
|
||||
return (MethodDef)method;
|
||||
var git = method.DeclaringType.ToGenericInstSig();
|
||||
var git = method.DeclaringType.TryGetGenericInstSig();
|
||||
var dt = git == null ? method.DeclaringType : git.GenericType.TypeDefOrRef;
|
||||
return getMethod(module, method, dt);
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ namespace de4dot.blocks {
|
|||
var resourceName = removeFromNullChar(tmp);
|
||||
if (resourceName == null)
|
||||
continue;
|
||||
var name = new UTF8String(resourceName);
|
||||
UTF8String name = resourceName;
|
||||
foreach (var resource in resources) {
|
||||
if (UTF8String.Equals(resource.Name, name))
|
||||
return resource;
|
||||
|
@ -360,11 +360,11 @@ namespace de4dot.blocks {
|
|||
var newMethod = new MethodDefUser(method.Name, method.MethodSig, method.ImplAttributes, method.Attributes);
|
||||
newMethod.Rid = method.Rid;
|
||||
newMethod.DeclaringType2 = method.DeclaringType;
|
||||
foreach (var pd in method.ParamList)
|
||||
newMethod.ParamList.Add(new ParamDefUser(pd.Name, pd.Sequence, pd.Attributes));
|
||||
foreach (var pd in method.ParamDefs)
|
||||
newMethod.ParamDefs.Add(new ParamDefUser(pd.Name, pd.Sequence, pd.Attributes));
|
||||
foreach (var gp in method.GenericParameters) {
|
||||
var newGp = new GenericParamUser(gp.Number, gp.Flags, gp.Name);
|
||||
foreach (var gpc in newGp.GenericParamConstraints)
|
||||
foreach (var gpc in gp.GenericParamConstraints)
|
||||
newGp.GenericParamConstraints.Add(new GenericParamConstraintUser(gpc.Constraint));
|
||||
newMethod.GenericParameters.Add(newGp);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet.MD;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet.MD;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
[Serializable]
|
||||
|
|
|
@ -23,7 +23,7 @@ using System.Collections.Generic;
|
|||
namespace de4dot.blocks {
|
||||
// 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
|
||||
// doesn't complain AND also to make sure dot10 sets the correct maxstack.
|
||||
// doesn't complain AND also to make sure dnlib sets the correct maxstack.
|
||||
class ForwardScanOrder {
|
||||
ScopeBlock scopeBlock;
|
||||
IList<BaseBlock> sorted;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
public struct GenericArgsSubstitutor {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
public class Instr {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
class InstructionListParser {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
public class TypeDefDict<TValue> {
|
||||
|
|
|
@ -21,7 +21,7 @@ using System.Reflection;
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("blocks")]
|
||||
[assembly: AssemblyDescription("Modifies dot10 MethodDef bodies")]
|
||||
[assembly: AssemblyDescription("Modifies dnlib MethodDef bodies")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("blocks")]
|
||||
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
// A normal branch may not transfer out of a protected block (try block), filter handler,
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
// Contains the filter handler block and the catch handler block.
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
<Compile Include="cflow\ConstantsFolder.cs" />
|
||||
<Compile Include="cflow\DeadCodeRemover.cs" />
|
||||
<Compile Include="cflow\DeadStoreRemover.cs" />
|
||||
<Compile Include="cflow\DupBlockDeobfuscator.cs" />
|
||||
<Compile Include="cflow\IBlocksDeobfuscator.cs" />
|
||||
<Compile Include="cflow\ICflowDeobfuscator.cs" />
|
||||
<Compile Include="cflow\InstructionEmulator.cs" />
|
||||
|
@ -80,9 +81,9 @@
|
|||
<Compile Include="Utils.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\dot10\src\dot10.csproj">
|
||||
<ProjectReference Include="..\dnlib\src\dnlib.csproj">
|
||||
<Project>{FDFC1237-143F-4919-8318-4926901F4639}</Project>
|
||||
<Name>dot10</Name>
|
||||
<Name>dnlib</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
class BlockCflowDeobfuscator : BlockDeobfuscator, IBranchHandler {
|
||||
|
@ -58,7 +58,7 @@ namespace de4dot.blocks.cflow {
|
|||
// Pop the arguments to the bcc instruction. The dead code remover will get rid of the
|
||||
// pop and any pushed arguments. Insert the pops just before the bcc instr.
|
||||
for (int i = 0; i < stackArgs; i++)
|
||||
block.insert(block.Instructions.Count - 1, Instruction.Create(OpCodes.Pop));
|
||||
block.insert(block.Instructions.Count - 1, OpCodes.Pop.ToInstruction());
|
||||
}
|
||||
|
||||
void IBranchHandler.handleNormal(int stackArgs, bool isTaken) {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
public class BlocksCflowDeobfuscator {
|
||||
|
@ -43,6 +43,7 @@ namespace de4dot.blocks.cflow {
|
|||
ourBlocksDeobfuscators.Add(new DeadCodeRemover { ExecuteOnNoChange = false });
|
||||
ourBlocksDeobfuscators.Add(new ConstantsFolder { ExecuteOnNoChange = true });
|
||||
ourBlocksDeobfuscators.Add(new StLdlocFixer { ExecuteOnNoChange = true });
|
||||
ourBlocksDeobfuscators.Add(new DupBlockCflowDeobfuscator { ExecuteOnNoChange = true });
|
||||
}
|
||||
|
||||
public void add(IEnumerable<IBlocksDeobfuscator> blocksDeobfuscators) {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
public interface IBranchHandler {
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
// Only deobfuscates a method once. A copy of the method (now deobfuscated) is returned.
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
public class CflowDeobfuscator : ICflowDeobfuscator {
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
|
@ -96,7 +96,7 @@ namespace de4dot.blocks.cflow {
|
|||
var intValue = (Int64Value)value;
|
||||
if (!intValue.allBitsValid())
|
||||
return false;
|
||||
block.Instructions[index] = new Instr(Instruction.Create(OpCodes.Ldc_I8, intValue.value));
|
||||
block.Instructions[index] = new Instr(OpCodes.Ldc_I8.ToInstruction(intValue.value));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
// Removes dead code that is the result of one of our optimizations, or created by the
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
// Removes dead stores by replacing the stloc with a pop. Other optimizations will notice it's
|
||||
|
@ -147,7 +147,7 @@ namespace de4dot.blocks.cflow {
|
|||
continue;
|
||||
if (!deadLocals[local.Index])
|
||||
continue;
|
||||
instructions[i] = new Instr(Instruction.Create(OpCodes.Pop));
|
||||
instructions[i] = new Instr(OpCodes.Pop.ToInstruction());
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
|
49
blocks/cflow/DupBlockDeobfuscator.cs
Normal file
49
blocks/cflow/DupBlockDeobfuscator.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright (C) 2011-2012 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
// If a block is just a dup followed by a bcc, try to append the block
|
||||
// to all its sources. Will fix some SA assemblies.
|
||||
class DupBlockCflowDeobfuscator : BlockDeobfuscator {
|
||||
protected override bool deobfuscate(Block block) {
|
||||
if (block.Instructions.Count != 2)
|
||||
return false;
|
||||
if (block.Instructions[0].OpCode.Code != Code.Dup)
|
||||
return false;
|
||||
if (!block.LastInstr.isConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch)
|
||||
return false;
|
||||
|
||||
bool modified = false;
|
||||
foreach (var source in new List<Block>(block.Sources)) {
|
||||
if (source.getOnlyTarget() != block)
|
||||
continue;
|
||||
if (!source.canAppend(block))
|
||||
continue;
|
||||
|
||||
source.append(block);
|
||||
modified = true;
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
public interface ICflowDeobfuscator {
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
public class InstructionEmulator {
|
||||
|
@ -232,6 +232,17 @@ namespace de4dot.blocks.cflow {
|
|||
valueStack.push(value);
|
||||
}
|
||||
|
||||
public void clearStack() {
|
||||
valueStack.clear();
|
||||
}
|
||||
|
||||
public void pop(int num) {
|
||||
if (num < 0)
|
||||
valueStack.clear();
|
||||
else
|
||||
valueStack.pop(num);
|
||||
}
|
||||
|
||||
public Value pop() {
|
||||
return valueStack.pop();
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
public class MethodCallInliner : MethodCallInlinerBase {
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
public abstract class MethodCallInlinerBase : IBlocksDeobfuscator {
|
||||
|
@ -75,7 +75,7 @@ namespace de4dot.blocks.cflow {
|
|||
|
||||
int methodArgsCount = DotNetUtils.getArgsCount(methodToInline);
|
||||
for (int i = 0; i < methodArgsCount; i++)
|
||||
block.insert(patchIndex++, Instruction.Create(OpCodes.Pop));
|
||||
block.insert(patchIndex++, OpCodes.Pop.ToInstruction());
|
||||
|
||||
block.Instructions[patchIndex] = new Instr(loadInstr.Clone());
|
||||
return true;
|
||||
|
@ -104,6 +104,10 @@ namespace de4dot.blocks.cflow {
|
|||
return tryInlineOtherMethod(patchIndex, methodToInline, instr, instrIndex, 0);
|
||||
}
|
||||
|
||||
protected virtual Instruction onAfterLoadArg(MethodDef methodToInline, Instruction instr, ref int instrIndex) {
|
||||
return instr;
|
||||
}
|
||||
|
||||
protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDef methodToInline, Instruction instr, int instrIndex, int popLastArgs) {
|
||||
int loadIndex = 0;
|
||||
int methodArgsCount = DotNetUtils.getArgsCount(methodToInline);
|
||||
|
@ -133,6 +137,7 @@ namespace de4dot.blocks.cflow {
|
|||
return null;
|
||||
loadIndex++;
|
||||
instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
|
||||
instr = onAfterLoadArg(methodToInline, instr, ref instrIndex);
|
||||
}
|
||||
if (instr == null || loadIndex != methodArgsCount - popLastArgs)
|
||||
return null;
|
||||
|
@ -224,7 +229,7 @@ namespace de4dot.blocks.cflow {
|
|||
return false;
|
||||
for (int i = 0; i < methodArgs.Count; i++) {
|
||||
var methodArg = methodArgs[i];
|
||||
var methodToInlineArg = methodToInlineArgs[i].Type;
|
||||
var methodToInlineArg = getArgType(methodToInline, methodToInlineArgs[i].Type);
|
||||
if (!isCompatibleType(i, methodArg, methodToInlineArg)) {
|
||||
if (i != 0 || !hasImplicitThis)
|
||||
return false;
|
||||
|
@ -236,6 +241,19 @@ namespace de4dot.blocks.cflow {
|
|||
return true;
|
||||
}
|
||||
|
||||
static TypeSig getArgType(MethodDef method, TypeSig arg) {
|
||||
if (arg.GetElementType() != ElementType.MVar)
|
||||
return arg;
|
||||
var mvar = (GenericMVar)arg;
|
||||
foreach (var gp in method.GenericParameters) {
|
||||
if (gp.Number != mvar.Number)
|
||||
continue;
|
||||
foreach (var gpc in gp.GenericParamConstraints)
|
||||
return gpc.Constraint.ToTypeSig();
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
protected virtual bool isCompatibleType(int paramIndex, IType origType, IType newType) {
|
||||
return new SigComparer().Equals(origType, newType);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
// Replace stloc + ldloc with dup + stloc
|
||||
|
@ -54,7 +54,7 @@ namespace de4dot.blocks.cflow {
|
|||
continue;
|
||||
if (local != Instr.getLocalVar(locals, instructions[i + 1]))
|
||||
break;
|
||||
instructions[i] = new Instr(Instruction.Create(OpCodes.Dup));
|
||||
instructions[i] = new Instr(OpCodes.Dup.ToInstruction());
|
||||
instructions[i + 1] = instr;
|
||||
changed = true;
|
||||
break;
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
class SwitchCflowDeobfuscator : BlockDeobfuscator {
|
||||
|
@ -165,7 +165,7 @@ namespace de4dot.blocks.cflow {
|
|||
if (target == null)
|
||||
continue;
|
||||
source.replaceLastNonBranchWithBranch(0, target);
|
||||
source.add(new Instr(Instruction.Create(OpCodes.Pop)));
|
||||
source.add(new Instr(OpCodes.Pop.ToInstruction()));
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
|
@ -232,7 +232,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
else {
|
||||
source.replaceLastNonBranchWithBranch(0, target);
|
||||
source.add(new Instr(Instruction.Create(OpCodes.Pop)));
|
||||
source.add(new Instr(OpCodes.Pop.ToInstruction()));
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +371,7 @@ namespace de4dot.blocks.cflow {
|
|||
var block = new Block();
|
||||
foreach (var kv in consts) {
|
||||
block.Instructions.Add(new Instr(Instruction.CreateLdcI4(kv.Value)));
|
||||
block.Instructions.Add(new Instr(Instruction.Create(OpCodes.Stloc, kv.Key)));
|
||||
block.Instructions.Add(new Instr(OpCodes.Stloc.ToInstruction(kv.Key)));
|
||||
}
|
||||
fallThrough.Parent.add(block);
|
||||
return block;
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace de4dot.code.AssemblyClient {
|
||||
public interface IAssemblyClientFactory {
|
||||
IAssemblyClient create();
|
||||
|
@ -45,8 +47,27 @@ namespace de4dot.code.AssemblyClient {
|
|||
this.serverVersion = serverVersion;
|
||||
}
|
||||
|
||||
public IAssemblyClient create(ModuleDef module) {
|
||||
return new AssemblyClient(new NewProcessAssemblyServerLoader(getServerClrVersion(module)));
|
||||
}
|
||||
|
||||
public IAssemblyClient create() {
|
||||
return new AssemblyClient(new NewProcessAssemblyServerLoader(serverVersion));
|
||||
}
|
||||
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Writer;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Writer;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code {
|
||||
|
@ -51,17 +51,7 @@ namespace de4dot.code {
|
|||
return module;
|
||||
}
|
||||
|
||||
public void save(string newFilename, bool preserveTokens, bool updateMaxStack, IModuleWriterListener writerListener) {
|
||||
MetaDataFlags mdFlags = 0;
|
||||
if (!updateMaxStack)
|
||||
mdFlags |= MetaDataFlags.KeepOldMaxStack;
|
||||
if (preserveTokens) {
|
||||
mdFlags |= MetaDataFlags.PreserveRids |
|
||||
MetaDataFlags.PreserveUSOffsets |
|
||||
MetaDataFlags.PreserveBlobOffsets |
|
||||
MetaDataFlags.PreserveExtraSignatureData;
|
||||
}
|
||||
|
||||
public void save(string newFilename, MetaDataFlags mdFlags, IModuleWriterListener writerListener) {
|
||||
if (module.IsILOnly) {
|
||||
var writerOptions = new ModuleWriterOptions(module, writerListener);
|
||||
writerOptions.MetaDataOptions.Flags |= mdFlags;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace de4dot.code {
|
||||
public class TheAssemblyResolver : AssemblyResolver {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code {
|
||||
|
@ -50,7 +50,7 @@ namespace de4dot.code {
|
|||
var ts = typeRef as TypeSpec;
|
||||
if (ts == null)
|
||||
return typeRef;
|
||||
var gis = ts.ToGenericInstSig();
|
||||
var gis = ts.TryGetGenericInstSig();
|
||||
if (gis == null || gis.GenericType == null)
|
||||
return typeRef;
|
||||
return gis.GenericType.TypeDefOrRef;
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using dot10.PE;
|
||||
using dot10.DotNet.MD;
|
||||
using dot10.DotNet.Emit;
|
||||
using dot10.DotNet;
|
||||
using dnlib.PE;
|
||||
using dnlib.DotNet.MD;
|
||||
using dnlib.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace de4dot.code {
|
||||
public interface IDeobfuscatorContext {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using de4dot.code.deobfuscators;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.code.renamer;
|
||||
|
||||
namespace de4dot.code {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace de4dot.code {
|
||||
public class Logger : ILogger {
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code {
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code {
|
||||
|
|
|
@ -22,10 +22,10 @@ using System.Collections.Generic;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dot10.DotNet.Writer;
|
||||
using dot10.PE;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using dnlib.DotNet.Writer;
|
||||
using dnlib.PE;
|
||||
using de4dot.code.deobfuscators;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
|
@ -88,6 +88,9 @@ namespace de4dot.code {
|
|||
public List<string> StringDecrypterMethods { get; private set; }
|
||||
public bool ControlFlowDeobfuscation { get; set; }
|
||||
public bool KeepObfuscatorTypes { get; set; }
|
||||
public bool PreserveTokens { get; set; }
|
||||
public MetaDataFlags MetaDataFlags { get; set; }
|
||||
public RenamerFlags RenamerFlags { get; set; }
|
||||
|
||||
public Options() {
|
||||
StringDecrypterType = DecrypterType.Default;
|
||||
|
@ -251,6 +254,8 @@ namespace de4dot.code {
|
|||
}
|
||||
|
||||
op.KeepObfuscatorTypes = options.KeepObfuscatorTypes;
|
||||
op.MetaDataFlags = options.MetaDataFlags;
|
||||
op.RenamerFlags = options.RenamerFlags;
|
||||
|
||||
return op;
|
||||
}
|
||||
|
@ -322,13 +327,26 @@ namespace de4dot.code {
|
|||
return detected;
|
||||
}
|
||||
|
||||
bool ShouldPreserveTokens() {
|
||||
return options.KeepObfuscatorTypes || deob.Type == "un";
|
||||
MetaDataFlags getMetaDataFlags() {
|
||||
var mdFlags = options.MetaDataFlags | deob.MetaDataFlags;
|
||||
|
||||
// Always preserve tokens if it's an unknown obfuscator
|
||||
if (deob.Type == "un") {
|
||||
mdFlags |= MetaDataFlags.PreserveRids |
|
||||
MetaDataFlags.PreserveUSOffsets |
|
||||
MetaDataFlags.PreserveBlobOffsets |
|
||||
MetaDataFlags.PreserveExtraSignatureData;
|
||||
}
|
||||
|
||||
return mdFlags;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
Logger.n("Saving {0}", options.NewFilename);
|
||||
assemblyModule.save(options.NewFilename, ShouldPreserveTokens(), options.ControlFlowDeobfuscation, deob as IModuleWriterListener);
|
||||
var mdFlags = getMetaDataFlags();
|
||||
if (!options.ControlFlowDeobfuscation)
|
||||
mdFlags |= MetaDataFlags.KeepOldMaxStack;
|
||||
assemblyModule.save(options.NewFilename, mdFlags, deob as IModuleWriterListener);
|
||||
}
|
||||
|
||||
IList<MethodDef> getAllMethods() {
|
||||
|
@ -355,7 +373,11 @@ namespace de4dot.code {
|
|||
case DecrypterType.Delegate:
|
||||
case DecrypterType.Emulate:
|
||||
checkSupportedStringDecrypter(StringFeatures.AllowDynamicDecryption);
|
||||
assemblyClient = assemblyClientFactory.create();
|
||||
var newProcFactory = assemblyClientFactory as NewProcessAssemblyClientFactory;
|
||||
if (newProcFactory != null)
|
||||
assemblyClient = newProcFactory.create(module);
|
||||
else
|
||||
assemblyClient = assemblyClientFactory.create();
|
||||
assemblyClient.connect();
|
||||
break;
|
||||
|
||||
|
@ -552,7 +574,7 @@ namespace de4dot.code {
|
|||
deob.DeobfuscatedFile = null;
|
||||
|
||||
if (!options.ControlFlowDeobfuscation) {
|
||||
if (ShouldPreserveTokens())
|
||||
if (options.KeepObfuscatorTypes || deob.Type == "un")
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -607,6 +629,11 @@ namespace de4dot.code {
|
|||
}
|
||||
}
|
||||
|
||||
bool CanOptimizeLocals() {
|
||||
// Don't remove any locals if we must preserve StandAloneSig table
|
||||
return (getMetaDataFlags() & MetaDataFlags.PreserveStandAloneSigRids) == 0;
|
||||
}
|
||||
|
||||
void deobfuscate(MethodDef method, BlocksCflowDeobfuscator cflowDeobfuscator, MethodPrinter methodPrinter, bool isVerbose, bool isVV) {
|
||||
if (!hasNonEmptyBody(method))
|
||||
return;
|
||||
|
@ -625,9 +652,7 @@ namespace de4dot.code {
|
|||
cflowDeobfuscator.deobfuscate();
|
||||
|
||||
if (options.ControlFlowDeobfuscation) {
|
||||
// Don't remove any locals if we should preserve tokens or we won't be able
|
||||
// to always preserve StandAloneSig tokens.
|
||||
if (!ShouldPreserveTokens())
|
||||
if (CanOptimizeLocals())
|
||||
numRemovedLocals = blocks.optimizeLocals();
|
||||
blocks.repartitionBlocks();
|
||||
}
|
||||
|
|
|
@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: AssemblyVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyFileVersion("1.9.1.3405")]
|
||||
[assembly: AssemblyVersion("2.0.2.3405")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.3405")]
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.code.AssemblyClient;
|
||||
using de4dot.blocks;
|
||||
|
||||
|
@ -36,7 +36,7 @@ namespace de4dot.code {
|
|||
continue;
|
||||
|
||||
int ldstrIndex = callResult.callStartIndex;
|
||||
block.replace(ldstrIndex, num, Instruction.Create(OpCodes.Ldstr, decryptedString));
|
||||
block.replace(ldstrIndex, num, OpCodes.Ldstr.ToInstruction(decryptedString));
|
||||
|
||||
// If it's followed by castclass string, remove it
|
||||
if (ldstrIndex + 1 < block.Instructions.Count) {
|
||||
|
|
|
@ -21,8 +21,8 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using dot10.DotNet;
|
||||
using dot10.IO;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.IO;
|
||||
|
||||
namespace de4dot.code {
|
||||
// These are in .NET 3.5 and later...
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
<Compile Include="deobfuscators\CodeWall\randomc\CRandomMother.cs" />
|
||||
<Compile Include="deobfuscators\CodeWall\StringDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\ConstantsReader.cs" />
|
||||
<Compile Include="deobfuscators\CRC32.cs" />
|
||||
<Compile Include="deobfuscators\CryptoObfuscator\AntiDebugger.cs" />
|
||||
<Compile Include="deobfuscators\CryptoObfuscator\AssemblyResolver.cs" />
|
||||
<Compile Include="deobfuscators\CryptoObfuscator\ConstantsDecrypter.cs" />
|
||||
|
@ -182,6 +183,7 @@
|
|||
<Compile Include="deobfuscators\DeobUtils.cs" />
|
||||
<Compile Include="deobfuscators\Dotfuscator\Deobfuscator.cs" />
|
||||
<Compile Include="deobfuscators\Dotfuscator\StringDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\Eazfuscator_NET\Dynocode.cs" />
|
||||
<Compile Include="deobfuscators\MyPEImage.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\AntiStrongName.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\ApplicationModeDecrypter.cs" />
|
||||
|
@ -260,6 +262,7 @@
|
|||
<Compile Include="deobfuscators\QuickLZ.cs" />
|
||||
<Compile Include="deobfuscators\RandomNameChecker.cs" />
|
||||
<Compile Include="deobfuscators\Rummage\Deobfuscator.cs" />
|
||||
<Compile Include="deobfuscators\Rummage\RummageVersion.cs" />
|
||||
<Compile Include="deobfuscators\Rummage\StringDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\Skater_NET\Deobfuscator.cs" />
|
||||
<Compile Include="deobfuscators\Skater_NET\EnumClassFinder.cs" />
|
||||
|
@ -366,15 +369,16 @@
|
|||
<Project>{5C93C5E2-196F-4877-BF65-96FEBFCEFCA1}</Project>
|
||||
<Name>de4dot.mdecrypt</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\dot10\src\dot10.csproj">
|
||||
<ProjectReference Include="..\dnlib\src\dnlib.csproj">
|
||||
<Project>{FDFC1237-143F-4919-8318-4926901F4639}</Project>
|
||||
<Name>dot10</Name>
|
||||
<Name>dnlib</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>copy "$(SolutionDir)LICENSE*.txt" "..\$(OutDir).."
|
||||
copy "$(SolutionDir)COPYING" "..\$(OutDir).."</PostBuildEvent>
|
||||
<PostBuildEvent>mkdir "..\$(OutDir)..\LICENSES"
|
||||
copy "$(SolutionDir)LICENSE*.txt" "..\$(OutDir)..\LICENSES"
|
||||
copy "$(SolutionDir)COPYING" "..\$(OutDir)..\LICENSES"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- 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.
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.IO;
|
||||
using dot10.PE;
|
||||
using dot10.DotNet;
|
||||
using dnlib.IO;
|
||||
using dnlib.PE;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||
|
@ -271,8 +271,12 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
}
|
||||
|
||||
if (options.RestoreVmCode) {
|
||||
csvm.restore();
|
||||
addResourceToBeRemoved(csvm.Resource, "CSVM data resource");
|
||||
if (csvm.restore())
|
||||
addResourceToBeRemoved(csvm.Resource, "CSVM data resource");
|
||||
else {
|
||||
Logger.e("Couldn't restore VM methods. Use --dont-rename or it will not run");
|
||||
preserveTokensAndTypes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using dot10.IO;
|
||||
using dot10.PE;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.MD;
|
||||
using dnlib.IO;
|
||||
using dnlib.PE;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.MD;
|
||||
using de4dot.blocks;
|
||||
using de4dot.code.AssemblyClient;
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using dot10.IO;
|
||||
using dot10.DotNet;
|
||||
using dnlib.IO;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using System;
|
||||
using System.Text;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||
class StringDecrypter {
|
||||
|
@ -76,10 +76,10 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
|||
public string decrypt(string es) {
|
||||
if (stringDecrypterKey == null)
|
||||
throw new ApplicationException("Trying to decrypt strings when stringDecrypterKey is null (could not find it!)");
|
||||
StringBuilder sb = new StringBuilder(es.Length);
|
||||
char[] buf = new char[es.Length];
|
||||
for (int i = 0; i < es.Length; i++)
|
||||
sb.Append(Convert.ToChar((int)(es[i] ^ stringDecrypterKey[i % stringDecrypterKey.Length])));
|
||||
return sb.ToString();
|
||||
buf[i] = (char)(es[i] ^ stringDecrypterKey[i % stringDecrypterKey.Length]);
|
||||
return new string(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||
|
@ -78,13 +78,17 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
return DotNetUtils.getResource(module, "_CSVM") as EmbeddedResource;
|
||||
}
|
||||
|
||||
public void restore() {
|
||||
public bool restore() {
|
||||
if (!Detected)
|
||||
return;
|
||||
return true;
|
||||
|
||||
int oldIndent = Logger.Instance.IndentLevel;
|
||||
try {
|
||||
restore2();
|
||||
return true;
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
finally {
|
||||
Logger.Instance.IndentLevel = oldIndent;
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using dot10.IO;
|
||||
using dot10.DotNet;
|
||||
using dnlib.IO;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||
|
@ -415,7 +415,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
continue;
|
||||
if (hasPrefix(instrs, i, Code.Constrained))
|
||||
continue;
|
||||
instrs.Insert(i, Instruction.Create(OpCodes.Constrained, thisType.Next.ToTypeDefOrRef()));
|
||||
instrs.Insert(i, OpCodes.Constrained.ToInstruction(thisType.Next.ToTypeDefOrRef()));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||
class FieldsInfo {
|
||||
|
|
|
@ -21,8 +21,8 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using de4dot.blocks;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||
partial class OpCodeHandler {
|
||||
|
@ -70,19 +70,19 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
static partial class OpCodeHandlers {
|
||||
static Instruction arithmetic_read(BinaryReader reader) {
|
||||
switch (reader.ReadByte()) {
|
||||
case 0: return Instruction.Create(OpCodes.Add);
|
||||
case 1: return Instruction.Create(OpCodes.Add_Ovf);
|
||||
case 2: return Instruction.Create(OpCodes.Add_Ovf_Un);
|
||||
case 3: return Instruction.Create(OpCodes.Sub);
|
||||
case 4: return Instruction.Create(OpCodes.Sub_Ovf);
|
||||
case 5: return Instruction.Create(OpCodes.Sub_Ovf_Un);
|
||||
case 6: return Instruction.Create(OpCodes.Mul);
|
||||
case 7: return Instruction.Create(OpCodes.Mul_Ovf);
|
||||
case 8: return Instruction.Create(OpCodes.Mul_Ovf_Un);
|
||||
case 9: return Instruction.Create(OpCodes.Div);
|
||||
case 10: return Instruction.Create(OpCodes.Div_Un);
|
||||
case 11: return Instruction.Create(OpCodes.Rem);
|
||||
case 12: return Instruction.Create(OpCodes.Rem_Un);
|
||||
case 0: return OpCodes.Add.ToInstruction();
|
||||
case 1: return OpCodes.Add_Ovf.ToInstruction();
|
||||
case 2: return OpCodes.Add_Ovf_Un.ToInstruction();
|
||||
case 3: return OpCodes.Sub.ToInstruction();
|
||||
case 4: return OpCodes.Sub_Ovf.ToInstruction();
|
||||
case 5: return OpCodes.Sub_Ovf_Un.ToInstruction();
|
||||
case 6: return OpCodes.Mul.ToInstruction();
|
||||
case 7: return OpCodes.Mul_Ovf.ToInstruction();
|
||||
case 8: return OpCodes.Mul_Ovf_Un.ToInstruction();
|
||||
case 9: return OpCodes.Div.ToInstruction();
|
||||
case 10: return OpCodes.Div_Un.ToInstruction();
|
||||
case 11: return OpCodes.Rem.ToInstruction();
|
||||
case 12: return OpCodes.Rem_Un.ToInstruction();
|
||||
default: throw new ApplicationException("Invalid opcode");
|
||||
}
|
||||
}
|
||||
|
@ -226,8 +226,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
|
||||
static Instruction dup_read(BinaryReader reader) {
|
||||
switch (reader.ReadByte()) {
|
||||
case 0: return Instruction.Create(OpCodes.Dup);
|
||||
case 1: return Instruction.Create(OpCodes.Pop);
|
||||
case 0: return OpCodes.Dup.ToInstruction();
|
||||
case 1: return OpCodes.Pop.ToInstruction();
|
||||
default: throw new ApplicationException("Invalid opcode");
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
}
|
||||
|
||||
static Instruction endfinally_read(BinaryReader reader) {
|
||||
return Instruction.Create(OpCodes.Endfinally);
|
||||
return OpCodes.Endfinally.ToInstruction();
|
||||
}
|
||||
|
||||
static Instruction ldfld_read(BinaryReader reader) {
|
||||
|
@ -350,7 +350,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
}
|
||||
|
||||
static Instruction ldlen_read(BinaryReader reader) {
|
||||
return Instruction.Create(OpCodes.Ldlen);
|
||||
return OpCodes.Ldlen.ToInstruction();
|
||||
}
|
||||
|
||||
static Instruction ldobj_read(BinaryReader reader) {
|
||||
|
@ -361,7 +361,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
}
|
||||
|
||||
static Instruction ldstr_read(BinaryReader reader) {
|
||||
return Instruction.Create(OpCodes.Ldstr, reader.ReadString());
|
||||
return OpCodes.Ldstr.ToInstruction(reader.ReadString());
|
||||
}
|
||||
|
||||
static bool ldtoken_check(UnknownHandlerInfo info) {
|
||||
|
@ -392,10 +392,10 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
static Instruction ldc_read(BinaryReader reader) {
|
||||
switch ((ElementType)reader.ReadByte()) {
|
||||
case ElementType.I4: return Instruction.CreateLdcI4(reader.ReadInt32());
|
||||
case ElementType.I8: return Instruction.Create(OpCodes.Ldc_I8, reader.ReadInt64());
|
||||
case ElementType.R4: return Instruction.Create(OpCodes.Ldc_R4, reader.ReadSingle());
|
||||
case ElementType.R8: return Instruction.Create(OpCodes.Ldc_R8, reader.ReadDouble());
|
||||
case ElementType.Object: return Instruction.Create(OpCodes.Ldnull);
|
||||
case ElementType.I8: return OpCodes.Ldc_I8.ToInstruction(reader.ReadInt64());
|
||||
case ElementType.R4: return OpCodes.Ldc_R4.ToInstruction(reader.ReadSingle());
|
||||
case ElementType.R8: return OpCodes.Ldc_R8.ToInstruction(reader.ReadDouble());
|
||||
case ElementType.Object: return OpCodes.Ldnull.ToInstruction();
|
||||
default: throw new ApplicationException("Invalid opcode");
|
||||
}
|
||||
}
|
||||
|
@ -424,12 +424,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
|
||||
static Instruction logical_read(BinaryReader reader) {
|
||||
switch (reader.ReadByte()) {
|
||||
case 0: return Instruction.Create(OpCodes.And);
|
||||
case 1: return Instruction.Create(OpCodes.Or);
|
||||
case 2: return Instruction.Create(OpCodes.Xor);
|
||||
case 3: return Instruction.Create(OpCodes.Shl);
|
||||
case 4: return Instruction.Create(OpCodes.Shr);
|
||||
case 5: return Instruction.Create(OpCodes.Shr_Un);
|
||||
case 0: return OpCodes.And.ToInstruction();
|
||||
case 1: return OpCodes.Or.ToInstruction();
|
||||
case 2: return OpCodes.Xor.ToInstruction();
|
||||
case 3: return OpCodes.Shl.ToInstruction();
|
||||
case 4: return OpCodes.Shr.ToInstruction();
|
||||
case 5: return OpCodes.Shr_Un.ToInstruction();
|
||||
default: throw new ApplicationException("Invalid opcode");
|
||||
}
|
||||
}
|
||||
|
@ -449,7 +449,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
}
|
||||
|
||||
static Instruction nop_read(BinaryReader reader) {
|
||||
return Instruction.Create(OpCodes.Nop);
|
||||
return OpCodes.Nop.ToInstruction();
|
||||
}
|
||||
|
||||
static bool ret_check(UnknownHandlerInfo info) {
|
||||
|
@ -458,7 +458,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
|
||||
static Instruction ret_read(BinaryReader reader) {
|
||||
reader.ReadInt32(); // token of current method
|
||||
return Instruction.Create(OpCodes.Ret);
|
||||
return OpCodes.Ret.ToInstruction();
|
||||
}
|
||||
|
||||
static bool rethrow_check(UnknownHandlerInfo info) {
|
||||
|
@ -466,7 +466,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
}
|
||||
|
||||
static Instruction rethrow_read(BinaryReader reader) {
|
||||
return Instruction.Create(OpCodes.Rethrow);
|
||||
return OpCodes.Rethrow.ToInstruction();
|
||||
}
|
||||
|
||||
static Instruction stloc_read(BinaryReader reader) {
|
||||
|
@ -510,13 +510,13 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
|||
}
|
||||
|
||||
static Instruction throw_read(BinaryReader reader) {
|
||||
return Instruction.Create(OpCodes.Throw);
|
||||
return OpCodes.Throw.ToInstruction();
|
||||
}
|
||||
|
||||
static Instruction neg_read(BinaryReader reader) {
|
||||
switch (reader.ReadByte()) {
|
||||
case 0: return Instruction.Create(OpCodes.Neg);
|
||||
case 1: return Instruction.Create(OpCodes.Not);
|
||||
case 0: return OpCodes.Neg.ToInstruction();
|
||||
case 1: return OpCodes.Not.ToInstruction();
|
||||
default: throw new ApplicationException("Invalid opcode");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using dot10.IO;
|
||||
using dot10.DotNet;
|
||||
using dnlib.IO;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
|
||||
|
@ -119,7 +119,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
|||
if (!getNewValue(methodToInline, ldci4.getLdcI4Value(), out newValue))
|
||||
return false;
|
||||
|
||||
block.Instructions[instrIndex - 1] = new Instr(Instruction.Create(OpCodes.Nop));
|
||||
block.Instructions[instrIndex - 1] = new Instr(OpCodes.Nop.ToInstruction());
|
||||
block.Instructions[instrIndex] = new Instr(Instruction.CreateLdcI4(newValue));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||
|
|
|
@ -21,9 +21,9 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using dot10.IO;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.IO;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||
|
@ -252,7 +252,7 @@ namespace de4dot.code.deobfuscators.Babel_NET {
|
|||
var castclass = instrs[index++];
|
||||
if (castclass.OpCode.Code != Code.Castclass)
|
||||
continue;
|
||||
var arrayType = (castclass.Operand as ITypeDefOrRef).ToSZArraySig();
|
||||
var arrayType = (castclass.Operand as ITypeDefOrRef).TryGetSZArraySig();
|
||||
if (arrayType == null)
|
||||
continue;
|
||||
if (arrayType.Next.ElementType.GetPrimitiveSize() == -1) {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
|
||||
|
|
|
@ -22,13 +22,13 @@ using System.Collections.Generic;
|
|||
using System.Runtime.InteropServices;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using dot10.IO;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.IO;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
using CR = System.Runtime.InteropServices;
|
||||
using DR = dot10.DotNet;
|
||||
using DR = dnlib.DotNet;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||
class ImageReader {
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
using ICSharpCode.SharpZipLib.Zip.Compression;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using dot10.DotNet;
|
||||
using dnlib.DotNet;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using dot10.IO;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.IO;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||
class MethodBodyReader : MethodBodyReaderBase {
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using dot10.IO;
|
||||
using dot10.DotNet;
|
||||
using dot10.DotNet.Emit;
|
||||
using dnlib.IO;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace de4dot.code.deobfuscators.Babel_NET {
|
||||
class BabelMethodreference {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user