Port .NET Reactor v4.x deobfuscator
This commit is contained in:
parent
413a032e0a
commit
d52a1014ef
|
@ -81,36 +81,33 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PORT
|
|
||||||
public class CallCounter {
|
public class CallCounter {
|
||||||
Dictionary<de4dot.blocks.OLD_REMOVE.MethodReferenceAndDeclaringTypeKey, int> calls = new Dictionary<de4dot.blocks.OLD_REMOVE.MethodReferenceAndDeclaringTypeKey, int>();
|
Dictionary<IMethod, int> calls = new Dictionary<IMethod, int>(MethodEqualityComparer.CompareDeclaringTypes);
|
||||||
|
|
||||||
public void add(MethodReference calledMethod) {
|
public void add(IMethod calledMethod) {
|
||||||
int count;
|
int count;
|
||||||
var key = new de4dot.blocks.OLD_REMOVE.MethodReferenceAndDeclaringTypeKey(calledMethod);
|
calls.TryGetValue(calledMethod, out count);
|
||||||
calls.TryGetValue(key, out count);
|
calls[calledMethod] = count + 1;
|
||||||
calls[key] = count + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference most() {
|
public IMethod most() {
|
||||||
int numCalls;
|
int numCalls;
|
||||||
return most(out numCalls);
|
return most(out numCalls);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference most(out int numCalls) {
|
public IMethod most(out int numCalls) {
|
||||||
MethodReference method = null;
|
IMethod method = null;
|
||||||
int callCount = 0;
|
int callCount = 0;
|
||||||
foreach (var key in calls.Keys) {
|
foreach (var key in calls.Keys) {
|
||||||
if (calls[key] > callCount) {
|
if (calls[key] > callCount) {
|
||||||
callCount = calls[key];
|
callCount = calls[key];
|
||||||
method = key.MethodReference;
|
method = key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
numCalls = callCount;
|
numCalls = callCount;
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PORT
|
#if PORT
|
||||||
public class MethodCalls {
|
public class MethodCalls {
|
||||||
|
@ -300,13 +297,13 @@ namespace de4dot.blocks {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public static MethodDef getMethod(ModuleDefinition module, MethodReference method) {
|
public static MethodDef getMethod(ModuleDefMD module, IMethod method) {
|
||||||
if (method == null)
|
if (method == null)
|
||||||
return null;
|
return null;
|
||||||
return getMethod(module, method, method.DeclaringType);
|
return getMethod(module, method, method.DeclaringType);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
public static MethodDef getMethod2(ModuleDefMD module, IMethod method) {
|
public static MethodDef getMethod2(ModuleDefMD module, IMethod method) {
|
||||||
if (method == null)
|
if (method == null)
|
||||||
|
@ -1090,29 +1087,22 @@ namespace de4dot.blocks {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PORT
|
public static IList<TypeSig> replaceGenericParameters(GenericInstSig typeOwner, MethodSpec methodOwner, IList<TypeSig> types) {
|
||||||
// Doesn't fix everything (eg. T[] aren't replaced with eg. int[], but T -> int will be fixed)
|
if (typeOwner == null && methodOwner == null)
|
||||||
public static IList<TypeReference> replaceGenericParameters(GenericInstanceType typeOwner, GenericInstanceMethod methodOwner, IList<TypeReference> types) {
|
return types;
|
||||||
//TODO: You should use MemberRefInstance.cs
|
|
||||||
for (int i = 0; i < types.Count; i++)
|
for (int i = 0; i < types.Count; i++)
|
||||||
types[i] = getGenericArgument(typeOwner, methodOwner, types[i]);
|
types[i] = getGenericArgument(typeOwner, methodOwner, types[i]);
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeReference getGenericArgument(GenericInstanceType typeOwner, GenericInstanceMethod methodOwner, TypeReference type) {
|
public static TypeSig getGenericArgument(GenericInstSig typeOwner, MethodSpec methodOwner, TypeSig type) {
|
||||||
var gp = type as GenericParameter;
|
var typeArgs = typeOwner == null ? null : typeOwner.GenericArguments;
|
||||||
if (gp == null)
|
var genMethodArgs = methodOwner == null || methodOwner.GenericInstMethodSig == null ?
|
||||||
return type;
|
null : methodOwner.GenericInstMethodSig.GenericArguments;
|
||||||
|
return GenericArgsSubstitutor.create(type, typeArgs, genMethodArgs);
|
||||||
if (typeOwner != null && MemberReferenceHelper.compareTypes(typeOwner.ElementType, gp.Owner as TypeReference))
|
|
||||||
return typeOwner.GenericArguments[gp.Position];
|
|
||||||
|
|
||||||
if (methodOwner != null && MemberReferenceHelper.compareMethodReferenceAndDeclaringType(methodOwner.ElementMethod, gp.Owner as MethodReference))
|
|
||||||
return methodOwner.GenericArguments[gp.Position];
|
|
||||||
|
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PORT
|
||||||
public static Instruction getInstruction(IList<Instruction> instructions, ref int index) {
|
public static Instruction getInstruction(IList<Instruction> instructions, ref int index) {
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
if (index < 0 || index >= instructions.Count)
|
if (index < 0 || index >= instructions.Count)
|
||||||
|
|
|
@ -48,6 +48,13 @@ namespace de4dot.blocks {
|
||||||
return new GenericArgsSubstitutor(genericArgs).create(type);
|
return new GenericArgsSubstitutor(genericArgs).create(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TypeSig create(TypeSig type, IList<TypeSig> genericArgs, IList<TypeSig> genericMethodArgs) {
|
||||||
|
if (type == null || ((genericArgs == null || genericArgs.Count == 0) &&
|
||||||
|
(genericMethodArgs == null || genericMethodArgs.Count == 0)))
|
||||||
|
return type;
|
||||||
|
return new GenericArgsSubstitutor(genericArgs, genericMethodArgs).create(type);
|
||||||
|
}
|
||||||
|
|
||||||
public static IField create(IField field, GenericInstSig git) {
|
public static IField create(IField field, GenericInstSig git) {
|
||||||
if (git == null)
|
if (git == null)
|
||||||
return field;
|
return field;
|
||||||
|
|
|
@ -153,6 +153,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\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" />
|
||||||
|
@ -163,19 +164,19 @@
|
||||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\LibAssemblyResolver.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v3\LibAssemblyResolver.cs" />
|
||||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\MemoryPatcher.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v3\MemoryPatcher.cs" />
|
||||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\NativeLibSaver.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v3\NativeLibSaver.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\AntiStrongName.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\AntiStrongName.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\AssemblyResolver.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\AssemblyResolver.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\BooleanDecrypter.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\BooleanDecrypter.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\Deobfuscator.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\Deobfuscator.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\EmptyClass.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\EmptyClass.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\EncryptedResource.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\EncryptedResource.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\MetadataTokenObfuscator.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\MetadataTokenObfuscator.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\MethodsDecrypter.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\MethodsDecrypter.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\NativeFileDecrypter.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\NativeFileDecrypter.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\NativeImageUnpacker.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\NativeImageUnpacker.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\ProxyCallFixer.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\ProxyCallFixer.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\ResourceResolver.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\ResourceResolver.cs" />
|
||||||
<None Include="deobfuscators\dotNET_Reactor\v4\StringDecrypter.cs" />
|
<Compile Include="deobfuscators\dotNET_Reactor\v4\StringDecrypter.cs" />
|
||||||
<None Include="deobfuscators\Eazfuscator_NET\AssemblyResolver.cs" />
|
<None Include="deobfuscators\Eazfuscator_NET\AssemblyResolver.cs" />
|
||||||
<None Include="deobfuscators\Eazfuscator_NET\CodeCompilerMethodCallRestorer.cs" />
|
<None Include="deobfuscators\Eazfuscator_NET\CodeCompilerMethodCallRestorer.cs" />
|
||||||
<None Include="deobfuscators\Eazfuscator_NET\DecrypterType.cs" />
|
<None Include="deobfuscators\Eazfuscator_NET\DecrypterType.cs" />
|
||||||
|
|
|
@ -505,10 +505,15 @@ namespace de4dot.code.deobfuscators {
|
||||||
var calledMethod = instr.Operand as IMethod;
|
var calledMethod = instr.Operand as IMethod;
|
||||||
if (calledMethod == null)
|
if (calledMethod == null)
|
||||||
continue;
|
continue;
|
||||||
IList<TypeSig> calledMethodArgs = DotNetUtils.getArgs(calledMethod);
|
var calledMethodDefOrRef = calledMethod as IMethodDefOrRef;
|
||||||
#if PORT
|
var calledMethodSpec = calledMethod as MethodSpec;
|
||||||
calledMethodArgs = DotNetUtils.replaceGenericParameters(calledMethod.DeclaringType as GenericInstanceType, calledMethod as GenericInstanceMethod, calledMethodArgs);
|
if (calledMethodSpec != null)
|
||||||
#endif
|
calledMethodDefOrRef = calledMethodSpec.Method;
|
||||||
|
if (calledMethodDefOrRef == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
IList<TypeSig> calledMethodArgs = DotNetUtils.getArgs(calledMethodDefOrRef);
|
||||||
|
calledMethodArgs = DotNetUtils.replaceGenericParameters(calledMethodDefOrRef.DeclaringType.ToGenericInstSig(), calledMethodSpec, calledMethodArgs);
|
||||||
for (int j = 0; j < pushedArgs.NumValidArgs; j++) {
|
for (int j = 0; j < pushedArgs.NumValidArgs; j++) {
|
||||||
var pushInstr = pushedArgs.getEnd(j);
|
var pushInstr = pushedArgs.getEnd(j);
|
||||||
if (pushInstr.OpCode.Code != Code.Ldfld && pushInstr.OpCode.Code != Code.Ldsfld)
|
if (pushInstr.OpCode.Code != Code.Ldfld && pushInstr.OpCode.Code != Code.Ldsfld)
|
||||||
|
@ -592,6 +597,8 @@ namespace de4dot.code.deobfuscators {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type.Next == null)
|
||||||
|
break;
|
||||||
type = type.Next;
|
type = type.Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
136
de4dot.code/deobfuscators/dotNET_Reactor/MyPEImage.cs
Normal file
136
de4dot.code/deobfuscators/dotNET_Reactor/MyPEImage.cs
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
using System;
|
||||||
|
using dot10.IO;
|
||||||
|
using dot10.PE;
|
||||||
|
using dot10.DotNet.MD;
|
||||||
|
|
||||||
|
namespace de4dot.code.deobfuscators.dotNET_Reactor {
|
||||||
|
sealed class MyPEImage : IDisposable {
|
||||||
|
IPEImage peImage;
|
||||||
|
byte[] peImageData;
|
||||||
|
IImageStream peStream;
|
||||||
|
DotNetFile dnFile;
|
||||||
|
ImageSectionHeader dotNetSection;
|
||||||
|
bool ownPeImage;
|
||||||
|
|
||||||
|
public IPEImage PEImage {
|
||||||
|
get { return peImage; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint Length {
|
||||||
|
get { return (uint)peStream.Length; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyPEImage(IPEImage peImage) {
|
||||||
|
initialize(peImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyPEImage(byte[] peImageData) {
|
||||||
|
this.ownPeImage = true;
|
||||||
|
this.peImageData = peImageData;
|
||||||
|
initialize(new PEImage(peImageData));
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(IPEImage peImage) {
|
||||||
|
this.peImage = peImage;
|
||||||
|
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) {
|
||||||
|
foreach (var section in peImage.ImageSectionHeaders) {
|
||||||
|
if (section.VirtualAddress <= rva && rva < section.VirtualAddress + Math.Max(section.VirtualSize, section.SizeOfRawData))
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isInside(ImageSectionHeader section, uint offset, uint length) {
|
||||||
|
return offset >= section.PointerToRawData && offset + length <= section.PointerToRawData + section.SizeOfRawData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offsetWriteUInt32(uint offset, uint val) {
|
||||||
|
peImageData[offset + 0] = (byte)val;
|
||||||
|
peImageData[offset + 1] = (byte)(val >> 8);
|
||||||
|
peImageData[offset + 2] = (byte)(val >> 16);
|
||||||
|
peImageData[offset + 3] = (byte)(val >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offsetWriteUInt16(uint offset, ushort val) {
|
||||||
|
peImageData[offset + 0] = (byte)val;
|
||||||
|
peImageData[offset + 1] = (byte)(val >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint offsetReadUInt32(uint offset) {
|
||||||
|
peStream.Position = offset;
|
||||||
|
return peStream.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ushort offsetReadUInt16(uint offset) {
|
||||||
|
peStream.Position = offset;
|
||||||
|
return peStream.ReadUInt16();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte offsetReadByte(uint offset) {
|
||||||
|
peStream.Position = offset;
|
||||||
|
return peStream.ReadByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] offsetReadBytes(uint offset, int size) {
|
||||||
|
peStream.Position = offset;
|
||||||
|
return peStream.ReadBytes(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offsetWrite(uint offset, byte[] data) {
|
||||||
|
Array.Copy(data, 0, peImageData, offset, data.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect(uint offset1, uint length1, uint offset2, uint length2) {
|
||||||
|
return !(offset1 + length1 <= offset2 || offset2 + length2 <= offset1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersect(uint offset, uint length, IFileSection location) {
|
||||||
|
return intersect(offset, length, (uint)location.StartOffset, (uint)(location.EndOffset - location.StartOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool dotNetSafeWriteOffset(uint offset, byte[] data) {
|
||||||
|
if (dnFile != null) {
|
||||||
|
uint length = (uint)data.Length;
|
||||||
|
|
||||||
|
if (!isInside(dotNetSection, offset, length))
|
||||||
|
return false;
|
||||||
|
if (intersect(offset, length, dnFile.MetaData.ImageCor20Header))
|
||||||
|
return false;
|
||||||
|
if (intersect(offset, length, (uint)dnFile.MetaData.TablesStream.FileOffset, dnFile.MetaData.TablesStream.HeaderLength))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
offsetWrite(offset, data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool dotNetSafeWrite(uint rva, byte[] data) {
|
||||||
|
return dotNetSafeWriteOffset((uint)peImage.ToFileOffset((RVA)rva), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
if (ownPeImage) {
|
||||||
|
if (dnFile != null)
|
||||||
|
dnFile.Dispose();
|
||||||
|
if (peImage != null)
|
||||||
|
peImage.Dispose();
|
||||||
|
}
|
||||||
|
if (peStream != null)
|
||||||
|
peStream.Dispose();
|
||||||
|
|
||||||
|
dnFile = null;
|
||||||
|
peImage = null;
|
||||||
|
peStream = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,131 +28,6 @@ using dot10.DotNet;
|
||||||
using dot10.DotNet.MD;
|
using dot10.DotNet.MD;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v3 {
|
namespace de4dot.code.deobfuscators.dotNET_Reactor.v3 {
|
||||||
sealed class MyPEImage : IDisposable {
|
|
||||||
IPEImage peImage;
|
|
||||||
byte[] peImageData;
|
|
||||||
IImageStream peStream;
|
|
||||||
DotNetFile dnFile;
|
|
||||||
ImageSectionHeader dotNetSection;
|
|
||||||
bool ownPeImage;
|
|
||||||
|
|
||||||
public IPEImage PEImage {
|
|
||||||
get { return peImage; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Length {
|
|
||||||
get { return (uint)peStream.Length; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public MyPEImage(IPEImage peImage) {
|
|
||||||
initialize(peImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MyPEImage(byte[] peImageData) {
|
|
||||||
this.ownPeImage = true;
|
|
||||||
this.peImageData = peImageData;
|
|
||||||
initialize(new PEImage(peImageData));
|
|
||||||
}
|
|
||||||
|
|
||||||
void initialize(IPEImage peImage) {
|
|
||||||
this.peImage = peImage;
|
|
||||||
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) {
|
|
||||||
foreach (var section in peImage.ImageSectionHeaders) {
|
|
||||||
if (section.VirtualAddress <= rva && rva < section.VirtualAddress + Math.Max(section.VirtualSize, section.SizeOfRawData))
|
|
||||||
return section;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isInside(ImageSectionHeader section, uint offset, uint length) {
|
|
||||||
return offset >= section.PointerToRawData && offset + length <= section.PointerToRawData + section.SizeOfRawData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void offsetWriteUInt32(uint offset, uint val) {
|
|
||||||
peImageData[offset + 0] = (byte)val;
|
|
||||||
peImageData[offset + 1] = (byte)(val >> 8);
|
|
||||||
peImageData[offset + 2] = (byte)(val >> 16);
|
|
||||||
peImageData[offset + 3] = (byte)(val >> 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void offsetWriteUInt16(uint offset, ushort val) {
|
|
||||||
peImageData[offset + 0] = (byte)val;
|
|
||||||
peImageData[offset + 1] = (byte)(val >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint offsetReadUInt32(uint offset) {
|
|
||||||
peStream.Position = offset;
|
|
||||||
return peStream.ReadUInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ushort offsetReadUInt16(uint offset) {
|
|
||||||
peStream.Position = offset;
|
|
||||||
return peStream.ReadUInt16();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] offsetReadBytes(uint offset, int size) {
|
|
||||||
peStream.Position = offset;
|
|
||||||
return peStream.ReadBytes(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void offsetWrite(uint offset, byte[] data) {
|
|
||||||
Array.Copy(data, 0, peImageData, offset, data.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool intersect(uint offset1, uint length1, uint offset2, uint length2) {
|
|
||||||
return !(offset1 + length1 <= offset2 || offset2 + length2 <= offset1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool intersect(uint offset, uint length, IFileSection location) {
|
|
||||||
return intersect(offset, length, (uint)location.StartOffset, (uint)(location.EndOffset - location.StartOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool dotNetSafeWriteOffset(uint offset, byte[] data) {
|
|
||||||
if (dnFile != null) {
|
|
||||||
uint length = (uint)data.Length;
|
|
||||||
|
|
||||||
if (!isInside(dotNetSection, offset, length))
|
|
||||||
return false;
|
|
||||||
if (intersect(offset, length, dnFile.MetaData.ImageCor20Header))
|
|
||||||
return false;
|
|
||||||
if (intersect(offset, length, (uint)dnFile.MetaData.TablesStream.FileOffset, dnFile.MetaData.TablesStream.HeaderLength))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
offsetWrite(offset, data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool dotNetSafeWrite(uint rva, byte[] data) {
|
|
||||||
return dotNetSafeWriteOffset((uint)peImage.ToFileOffset((RVA)rva), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() {
|
|
||||||
if (ownPeImage) {
|
|
||||||
if (dnFile != null)
|
|
||||||
dnFile.Dispose();
|
|
||||||
if (peImage != null)
|
|
||||||
peImage.Dispose();
|
|
||||||
}
|
|
||||||
if (peStream != null)
|
|
||||||
peStream.Dispose();
|
|
||||||
|
|
||||||
dnFile = null;
|
|
||||||
peImage = null;
|
|
||||||
peStream = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class IniFile {
|
class IniFile {
|
||||||
Dictionary<string, string> nameToValue = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
Dictionary<string, string> nameToValue = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
|
|
@ -57,13 +57,14 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
foreach (var method in type.Methods) {
|
foreach (var method in type.Methods) {
|
||||||
if (!method.IsStatic || method.Body == null)
|
if (!method.IsStatic || method.Body == null)
|
||||||
continue;
|
continue;
|
||||||
if (method.Parameters.Count != 2)
|
var sig = method.MethodSig;
|
||||||
|
if (sig == null || sig.Params.Count != 2)
|
||||||
continue;
|
continue;
|
||||||
if (!checkType(method.MethodReturnType.ReturnType.FullName, "System.String"))
|
if (!checkType(sig.RetType, ElementType.String))
|
||||||
continue;
|
continue;
|
||||||
if (!checkType(method.Parameters[0].ParameterType.FullName, "System.String"))
|
if (!checkType(sig.Params[0], ElementType.String))
|
||||||
continue;
|
continue;
|
||||||
if (!checkType(method.Parameters[1].ParameterType.FullName, "System.String"))
|
if (!checkType(sig.Params[1], ElementType.String))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var localTypes = new LocalTypes(method);
|
var localTypes = new LocalTypes(method);
|
||||||
|
@ -77,8 +78,8 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool checkType(string type, string expectedType) {
|
static bool checkType(TypeSig type, ElementType expectedType) {
|
||||||
return type == "System.Object" || type == expectedType;
|
return type != null && (type.ElementType == ElementType.Object || type.ElementType == expectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool remove(Blocks blocks) {
|
public bool remove(Blocks blocks) {
|
||||||
|
@ -129,7 +130,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
int i = instructions.Count - NUM_INSTRS;
|
int i = instructions.Count - NUM_INSTRS;
|
||||||
if (instructions[i].OpCode.Code != Code.Ldtoken)
|
if (instructions[i].OpCode.Code != Code.Ldtoken)
|
||||||
continue;
|
continue;
|
||||||
if (!(instructions[i].Operand is TypeReference))
|
if (!(instructions[i].Operand is ITypeDefOrRef))
|
||||||
continue;
|
continue;
|
||||||
if (!checkCall(instructions[i + 1], "System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)"))
|
if (!checkCall(instructions[i + 1], "System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)"))
|
||||||
continue;
|
continue;
|
||||||
|
@ -163,19 +164,19 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
static bool checkCall(Instr instr, string methodFullName) {
|
static bool checkCall(Instr instr, string methodFullName) {
|
||||||
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
|
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
|
||||||
return false;
|
return false;
|
||||||
var calledMethod = instr.Operand as MethodReference;
|
var calledMethod = instr.Operand as IMethod;
|
||||||
if (calledMethod == null)
|
if (calledMethod == null)
|
||||||
return false;
|
return false;
|
||||||
return calledMethod.FullName == methodFullName;
|
return calledMethod.FullName == methodFullName;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool checkCall(Instr instr, MethodReference expectedMethod) {
|
static bool checkCall(Instr instr, IMethod expectedMethod) {
|
||||||
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
|
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
|
||||||
return false;
|
return false;
|
||||||
var calledMethod = instr.Operand as MethodReference;
|
var calledMethod = instr.Operand as IMethod;
|
||||||
if (calledMethod == null)
|
if (calledMethod == null)
|
||||||
return false;
|
return false;
|
||||||
return MemberReferenceHelper.compareMethodReferenceAndDeclaringType(calledMethod, expectedMethod);
|
return MethodEqualityComparer.CompareDeclaringTypes.Equals(calledMethod, expectedMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
|
using dot10.IO;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
|
@ -39,7 +39,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssemblyResolver {
|
class AssemblyResolver {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
TypeDef assemblyResolverType;
|
TypeDef assemblyResolverType;
|
||||||
MethodDef assemblyResolverInitMethod;
|
MethodDef assemblyResolverInitMethod;
|
||||||
MethodDef assemblyResolverMethod;
|
MethodDef assemblyResolverMethod;
|
||||||
|
@ -56,11 +56,11 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
get { return assemblyResolverInitMethod; }
|
get { return assemblyResolverInitMethod; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public AssemblyResolver(ModuleDefinition module) {
|
public AssemblyResolver(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AssemblyResolver(ModuleDefinition module, AssemblyResolver oldOne) {
|
public AssemblyResolver(ModuleDefMD module, AssemblyResolver oldOne) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.assemblyResolverType = lookup(oldOne.assemblyResolverType, "Could not find assembly resolver type");
|
this.assemblyResolverType = lookup(oldOne.assemblyResolverType, "Could not find assembly resolver type");
|
||||||
this.assemblyResolverMethod = lookup(oldOne.assemblyResolverMethod, "Could not find assembly resolver method");
|
this.assemblyResolverMethod = lookup(oldOne.assemblyResolverMethod, "Could not find assembly resolver method");
|
||||||
|
@ -75,7 +75,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
if (checkMethod(simpleDeobfuscator, module.EntryPoint))
|
if (checkMethod(simpleDeobfuscator, module.EntryPoint))
|
||||||
return;
|
return;
|
||||||
if (module.EntryPoint != null) {
|
if (module.EntryPoint != null) {
|
||||||
if (checkMethod(simpleDeobfuscator, DotNetUtils.getMethod(module.EntryPoint.DeclaringType, ".cctor")))
|
if (checkMethod(simpleDeobfuscator, module.EntryPoint.DeclaringType.FindStaticConstructor()))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
var resource = rsrc as EmbeddedResource;
|
var resource = rsrc as EmbeddedResource;
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
continue;
|
continue;
|
||||||
if (!Utils.StartsWith(resource.Name, prefix, StringComparison.Ordinal))
|
if (!Utils.StartsWith(resource.Name.String, prefix, StringComparison.Ordinal))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
result.Add(resource);
|
result.Add(resource);
|
||||||
|
@ -193,8 +193,8 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
static int unknownNameCounter = 0;
|
static int unknownNameCounter = 0;
|
||||||
static string getAssemblyName(EmbeddedResource resource) {
|
static string getAssemblyName(EmbeddedResource resource) {
|
||||||
try {
|
try {
|
||||||
var resourceModule = ModuleDefinition.ReadModule(new MemoryStream(resource.GetResourceData()));
|
var resourceModule = ModuleDefMD.Load(resource.Data.ReadAllBytes());
|
||||||
return resourceModule.Assembly.Name.FullName;
|
return resourceModule.Assembly.FullName;
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
return string.Format("unknown_name_{0}", unknownNameCounter++);
|
return string.Format("unknown_name_{0}", unknownNameCounter++);
|
||||||
|
|
|
@ -23,7 +23,7 @@ using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
class BooleanDecrypter {
|
class BooleanDecrypter {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
EncryptedResource encryptedResource;
|
EncryptedResource encryptedResource;
|
||||||
byte[] fileData;
|
byte[] fileData;
|
||||||
byte[] decryptedData;
|
byte[] decryptedData;
|
||||||
|
@ -44,12 +44,12 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
get { return encryptedResource.Resource; }
|
get { return encryptedResource.Resource; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanDecrypter(ModuleDefinition module) {
|
public BooleanDecrypter(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.encryptedResource = new EncryptedResource(module);
|
this.encryptedResource = new EncryptedResource(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanDecrypter(ModuleDefinition module, BooleanDecrypter oldOne) {
|
public BooleanDecrypter(ModuleDefMD module, BooleanDecrypter oldOne) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.encryptedResource = new EncryptedResource(module, oldOne.encryptedResource);
|
this.encryptedResource = new EncryptedResource(module, oldOne.encryptedResource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,10 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using dot10.PE;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using dot10.DotNet.Emit;
|
using dot10.DotNet.Emit;
|
||||||
using dot10.DotNet.Writer;
|
using dot10.DotNet.Writer;
|
||||||
using Mono.MyStuff;
|
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.PE;
|
using de4dot.PE;
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
this.RenamingOptions &= ~RenamingOptions.RemoveNamespaceIfOneType;
|
this.RenamingOptions &= ~RenamingOptions.RemoveNamespaceIfOneType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] unpackNativeFile(PeImage peImage) {
|
public override byte[] unpackNativeFile(IPEImage peImage) {
|
||||||
var data = new NativeImageUnpacker(peImage).unpack();
|
var data = new NativeImageUnpacker(peImage).unpack();
|
||||||
if (data == null)
|
if (data == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -168,7 +168,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void init(ModuleDefinition module) {
|
public override void init(ModuleDefMD module) {
|
||||||
base.init(module);
|
base.init(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (options.DumpNativeMethods) {
|
if (options.DumpNativeMethods) {
|
||||||
using (var fileStream = new FileStream(module.FullyQualifiedName + ".native", FileMode.Create, FileAccess.Write, FileShare.Read)) {
|
using (var fileStream = new FileStream(module.Location + ".native", FileMode.Create, FileAccess.Write, FileShare.Read)) {
|
||||||
var sortedTokens = new List<uint>(tokenToNativeCode.Keys);
|
var sortedTokens = new List<uint>(tokenToNativeCode.Keys);
|
||||||
sortedTokens.Sort();
|
sortedTokens.Sort();
|
||||||
var writer = new BinaryWriter(fileStream);
|
var writer = new BinaryWriter(fileStream);
|
||||||
|
@ -404,7 +404,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IDeobfuscator moduleReloaded(ModuleDefinition module) {
|
public override IDeobfuscator moduleReloaded(ModuleDefMD module) {
|
||||||
var newOne = new Deobfuscator(options);
|
var newOne = new Deobfuscator(options);
|
||||||
newOne.setModule(module);
|
newOne.setModule(module);
|
||||||
newOne.fileData = fileData;
|
newOne.fileData = fileData;
|
||||||
|
@ -567,7 +567,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
var instr = instructions[i];
|
var instr = instructions[i];
|
||||||
if (instr.OpCode.Code != Code.Ldtoken)
|
if (instr.OpCode.Code != Code.Ldtoken)
|
||||||
continue;
|
continue;
|
||||||
if (!MemberReferenceHelper.compareTypes(type, instr.Operand as TypeReference))
|
if (!new SigComparer().Equals(type, instr.Operand as ITypeDefOrRef))
|
||||||
continue;
|
continue;
|
||||||
instructions[i] = new Instr(Instruction.Create(OpCodes.Ldtoken, blocks.Method.DeclaringType));
|
instructions[i] = new Instr(Instruction.Create(OpCodes.Ldtoken, blocks.Method.DeclaringType));
|
||||||
}
|
}
|
||||||
|
@ -607,12 +607,14 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnWriterEvent(ModuleWriter writer, ModuleWriterEvent evt) {
|
public override void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
|
||||||
if (evt != ModuleWriterEvent.EndWriteChunks)
|
if (evt != ModuleWriterEvent.EndWriteChunks)
|
||||||
return;
|
return;
|
||||||
if (!options.DecryptMethods)
|
if (!options.DecryptMethods)
|
||||||
return;
|
return;
|
||||||
|
#if PORT
|
||||||
methodsDecrypter.encryptNativeMethods(writer);
|
methodsDecrypter.encryptNativeMethods(writer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ using de4dot.blocks;
|
||||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
// Detect some empty class that is called from most .ctor's
|
// Detect some empty class that is called from most .ctor's
|
||||||
class EmptyClass {
|
class EmptyClass {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
MethodDef emptyMethod;
|
MethodDef emptyMethod;
|
||||||
|
|
||||||
public MethodDef Method {
|
public MethodDef Method {
|
||||||
|
@ -34,7 +34,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
get { return emptyMethod != null ? emptyMethod.DeclaringType : null; }
|
get { return emptyMethod != null ? emptyMethod.DeclaringType : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmptyClass(ModuleDefinition module) {
|
public EmptyClass(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
class EncryptedResource {
|
class EncryptedResource {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
MethodDef resourceDecrypterMethod;
|
MethodDef resourceDecrypterMethod;
|
||||||
EmbeddedResource encryptedDataResource;
|
EmbeddedResource encryptedDataResource;
|
||||||
byte[] key, iv;
|
byte[] key, iv;
|
||||||
|
@ -49,15 +49,15 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
get { return encryptedDataResource != null; }
|
get { return encryptedDataResource != null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public EncryptedResource(ModuleDefinition module) {
|
public EncryptedResource(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EncryptedResource(ModuleDefinition module, EncryptedResource oldOne) {
|
public EncryptedResource(ModuleDefMD module, EncryptedResource oldOne) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
resourceDecrypterMethod = lookup(oldOne.resourceDecrypterMethod, "Could not find resource decrypter method");
|
resourceDecrypterMethod = lookup(oldOne.resourceDecrypterMethod, "Could not find resource decrypter method");
|
||||||
if (oldOne.encryptedDataResource != null)
|
if (oldOne.encryptedDataResource != null)
|
||||||
encryptedDataResource = DotNetUtils.getResource(module, oldOne.encryptedDataResource.Name) as EmbeddedResource;
|
encryptedDataResource = DotNetUtils.getResource(module, oldOne.encryptedDataResource.Name.String) as EmbeddedResource;
|
||||||
key = oldOne.key;
|
key = oldOne.key;
|
||||||
iv = oldOne.iv;
|
iv = oldOne.iv;
|
||||||
|
|
||||||
|
@ -117,10 +117,10 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
if (iv == null)
|
if (iv == null)
|
||||||
throw new ApplicationException("Could not find resource decrypter IV");
|
throw new ApplicationException("Could not find resource decrypter IV");
|
||||||
if (usesPublicKeyToken()) {
|
if (usesPublicKeyToken()) {
|
||||||
var publicKeyToken = module.Assembly.Name.PublicKeyToken;
|
var publicKeyToken = module.Assembly.PublicKeyToken;
|
||||||
if (publicKeyToken != null && publicKeyToken.Length > 0) {
|
if (publicKeyToken != null && publicKeyToken.Data.Length > 0) {
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
iv[i * 2 + 1] = publicKeyToken[i];
|
iv[i * 2 + 1] = publicKeyToken.Data[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,9 +133,9 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
pktIndex = 0;
|
pktIndex = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!DotNetUtils.isLdcI4(instr))
|
if (!instr.IsLdcI4())
|
||||||
continue;
|
continue;
|
||||||
int val = DotNetUtils.getLdcI4Value(instr);
|
int val = instr.GetLdcI4Value();
|
||||||
if (val != pktIndexes[pktIndex++]) {
|
if (val != pktIndexes[pktIndex++]) {
|
||||||
pktIndex = 0;
|
pktIndex = 0;
|
||||||
continue;
|
continue;
|
||||||
|
@ -176,7 +176,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
public void updateResource(byte[] encryptedData) {
|
public void updateResource(byte[] encryptedData) {
|
||||||
for (int i = 0; i < module.Resources.Count; i++) {
|
for (int i = 0; i < module.Resources.Count; i++) {
|
||||||
if (module.Resources[i] == encryptedDataResource) {
|
if (module.Resources[i] == encryptedDataResource) {
|
||||||
encryptedDataResource = new EmbeddedResource(encryptedDataResource.Name, encryptedDataResource.Attributes, encryptedData);
|
encryptedDataResource = new EmbeddedResource(encryptedDataResource.Name, encryptedData, encryptedDataResource.Attributes);
|
||||||
module.Resources[i] = encryptedDataResource;
|
module.Resources[i] = encryptedDataResource;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
// Find the class that returns a RuntimeTypeHandle/RuntimeFieldHandle. The value passed to
|
// Find the class that returns a RuntimeTypeHandle/RuntimeFieldHandle. The value passed to
|
||||||
// its methods is the original metadata token, which will be different when we save the file.
|
// its methods is the original metadata token, which will be different when we save the file.
|
||||||
class MetadataTokenObfuscator {
|
class MetadataTokenObfuscator {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
TypeDef type;
|
TypeDef type;
|
||||||
MethodDef typeMethod;
|
MethodDef typeMethod;
|
||||||
MethodDef fieldMethod;
|
MethodDef fieldMethod;
|
||||||
|
@ -34,7 +34,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
get { return type; }
|
get { return type; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MetadataTokenObfuscator(ModuleDefinition module) {
|
public MetadataTokenObfuscator(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
find();
|
find();
|
||||||
}
|
}
|
||||||
|
@ -51,13 +51,14 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
|
|
||||||
MethodDef fieldMethod = null, typeMethod = null;
|
MethodDef fieldMethod = null, typeMethod = null;
|
||||||
foreach (var method in type.Methods) {
|
foreach (var method in type.Methods) {
|
||||||
if (method.Parameters.Count != 1)
|
var sig = method.MethodSig;
|
||||||
|
if (sig == null || sig.Params.Count != 1)
|
||||||
continue;
|
continue;
|
||||||
if (method.Parameters[0].ParameterType.FullName != "System.Int32")
|
if (sig.Params[0].GetElementType() != ElementType.I4)
|
||||||
continue;
|
continue;
|
||||||
if (method.MethodReturnType.ReturnType.FullName == "System.RuntimeTypeHandle")
|
if (sig.RetType.GetFullName() == "System.RuntimeTypeHandle")
|
||||||
typeMethod = method;
|
typeMethod = method;
|
||||||
else if (method.MethodReturnType.ReturnType.FullName == "System.RuntimeFieldHandle")
|
else if (sig.RetType.GetFullName() == "System.RuntimeFieldHandle")
|
||||||
fieldMethod = method;
|
fieldMethod = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,10 +85,10 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
var call = instrs[i + 1];
|
var call = instrs[i + 1];
|
||||||
if (call.OpCode.Code != Code.Call)
|
if (call.OpCode.Code != Code.Call)
|
||||||
continue;
|
continue;
|
||||||
var method = call.Operand as MethodReference;
|
var method = call.Operand as IMethod;
|
||||||
if (method == null)
|
if (method == null)
|
||||||
continue;
|
continue;
|
||||||
if (!MemberReferenceHelper.compareTypes(type, method.DeclaringType))
|
if (!new SigComparer().Equals(type, method.DeclaringType))
|
||||||
continue;
|
continue;
|
||||||
var methodDef = DotNetUtils.getMethod(module, method);
|
var methodDef = DotNetUtils.getMethod(module, method);
|
||||||
if (methodDef == null)
|
if (methodDef == null)
|
||||||
|
@ -95,9 +96,9 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
if (methodDef != typeMethod && methodDef != fieldMethod)
|
if (methodDef != typeMethod && methodDef != fieldMethod)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int token = (int)instrs[i].Operand;
|
uint token = (uint)(int)instrs[i].Operand;
|
||||||
instrs[i] = new Instr(Instruction.Create(OpCodes.Nop));
|
instrs[i] = new Instr(Instruction.Create(OpCodes.Nop));
|
||||||
instrs[i + 1] = new Instr(new Instruction(OpCodes.Ldtoken, module.LookupToken(token) as MemberReference));
|
instrs[i + 1] = new Instr(new Instruction(OpCodes.Ldtoken, module.ResolveToken(token) as IMethod));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,13 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using dot10.DotNet.Emit;
|
using dot10.DotNet.Emit;
|
||||||
using Mono.MyStuff;
|
using dot10.DotNet.Writer;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.PE;
|
using de4dot.PE;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
class MethodsDecrypter {
|
class MethodsDecrypter {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
EncryptedResource encryptedResource;
|
EncryptedResource encryptedResource;
|
||||||
Dictionary<uint, byte[]> tokenToNativeMethod = new Dictionary<uint, byte[]>();
|
Dictionary<uint, byte[]> tokenToNativeMethod = new Dictionary<uint, byte[]>();
|
||||||
Dictionary<MethodDef, byte[]> methodToNativeMethod = new Dictionary<MethodDef, byte[]>();
|
Dictionary<MethodDef, byte[]> methodToNativeMethod = new Dictionary<MethodDef, byte[]>();
|
||||||
|
@ -55,12 +55,12 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
get { return encryptedResource.Resource; }
|
get { return encryptedResource.Resource; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodsDecrypter(ModuleDefinition module) {
|
public MethodsDecrypter(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.encryptedResource = new EncryptedResource(module);
|
this.encryptedResource = new EncryptedResource(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodsDecrypter(ModuleDefinition module, MethodsDecrypter oldOne) {
|
public MethodsDecrypter(ModuleDefMD module, MethodsDecrypter oldOne) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.encryptedResource = new EncryptedResource(module, oldOne.encryptedResource);
|
this.encryptedResource = new EncryptedResource(module, oldOne.encryptedResource);
|
||||||
this.tokenToNativeMethod = oldOne.tokenToNativeMethod;
|
this.tokenToNativeMethod = oldOne.tokenToNativeMethod;
|
||||||
|
@ -73,29 +73,28 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
"System.IntPtr",
|
"System.IntPtr",
|
||||||
// "System.Reflection.Assembly", //TODO: Not in unknown DNR version with jitter support
|
// "System.Reflection.Assembly", //TODO: Not in unknown DNR version with jitter support
|
||||||
};
|
};
|
||||||
var checkedMethods = new Dictionary<MethodReferenceAndDeclaringTypeKey, bool>();
|
var checkedMethods = new Dictionary<IMethod, bool>(MethodEqualityComparer.CompareDeclaringTypes);
|
||||||
var callCounter = new CallCounter();
|
var callCounter = new CallCounter();
|
||||||
int typesLeft = 30;
|
int typesLeft = 30;
|
||||||
foreach (var type in module.GetTypes()) {
|
foreach (var type in module.GetTypes()) {
|
||||||
var cctor = DotNetUtils.getMethod(type, ".cctor");
|
var cctor = type.FindStaticConstructor();
|
||||||
if (cctor == null || cctor.Body == null)
|
if (cctor == null || cctor.Body == null)
|
||||||
continue;
|
continue;
|
||||||
if (typesLeft-- <= 0)
|
if (typesLeft-- <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
foreach (var method in DotNetUtils.getCalledMethods(module, cctor)) {
|
foreach (var method in DotNetUtils.getCalledMethods(module, cctor)) {
|
||||||
var key = new MethodReferenceAndDeclaringTypeKey(method);
|
if (!checkedMethods.ContainsKey(method)) {
|
||||||
if (!checkedMethods.ContainsKey(key)) {
|
checkedMethods[method] = false;
|
||||||
checkedMethods[key] = false;
|
|
||||||
if (method.DeclaringType.BaseType == null || method.DeclaringType.BaseType.FullName != "System.Object")
|
if (method.DeclaringType.BaseType == null || method.DeclaringType.BaseType.FullName != "System.Object")
|
||||||
continue;
|
continue;
|
||||||
if (!DotNetUtils.isMethod(method, "System.Void", "()"))
|
if (!DotNetUtils.isMethod(method, "System.Void", "()"))
|
||||||
continue;
|
continue;
|
||||||
if (!encryptedResource.couldBeResourceDecrypter(method, additionalTypes))
|
if (!encryptedResource.couldBeResourceDecrypter(method, additionalTypes))
|
||||||
continue;
|
continue;
|
||||||
checkedMethods[key] = true;
|
checkedMethods[method] = true;
|
||||||
}
|
}
|
||||||
else if (!checkedMethods[key])
|
else if (!checkedMethods[method])
|
||||||
continue;
|
continue;
|
||||||
callCounter.add(method);
|
callCounter.add(method);
|
||||||
}
|
}
|
||||||
|
@ -278,10 +277,10 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
if (instructions[i].OpCode.Code != Code.Ldind_I8)
|
if (instructions[i].OpCode.Code != Code.Ldind_I8)
|
||||||
continue;
|
continue;
|
||||||
var ldci4 = instructions[i + 1];
|
var ldci4 = instructions[i + 1];
|
||||||
if (!DotNetUtils.isLdcI4(ldci4))
|
if (!ldci4.IsLdcI4())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return DotNetUtils.getLdcI4Value(ldci4);
|
return ldci4.GetLdcI4Value();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -289,7 +288,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
public void reloaded() {
|
public void reloaded() {
|
||||||
foreach (var pair in tokenToNativeMethod) {
|
foreach (var pair in tokenToNativeMethod) {
|
||||||
int token = (int)pair.Key;
|
int token = (int)pair.Key;
|
||||||
var method = module.LookupToken(token) as MethodDef;
|
var method = module.ResolveToken(token) as MethodDef;
|
||||||
if (method == null)
|
if (method == null)
|
||||||
throw new ApplicationException(string.Format("Could not find method {0:X8}", token));
|
throw new ApplicationException(string.Format("Could not find method {0:X8}", token));
|
||||||
methodToNativeMethod[method] = pair.Value;
|
methodToNativeMethod[method] = pair.Value;
|
||||||
|
@ -297,7 +296,8 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
tokenToNativeMethod = null;
|
tokenToNativeMethod = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void encryptNativeMethods(ModuleWriter moduleWriter) {
|
#if PORT
|
||||||
|
public void encryptNativeMethods(ModuleWriterBase moduleWriter) {
|
||||||
if (methodToNativeMethod.Count == 0)
|
if (methodToNativeMethod.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -340,12 +340,14 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
xorEncrypt(encryptedData);
|
xorEncrypt(encryptedData);
|
||||||
encryptedResource.updateResource(encryptedResource.encrypt(encryptedData));
|
encryptedResource.updateResource(encryptedResource.encrypt(encryptedData));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public static MethodDef findDnrCompileMethod(TypeDef type) {
|
public static MethodDef findDnrCompileMethod(TypeDef type) {
|
||||||
foreach (var method in type.Methods) {
|
foreach (var method in type.Methods) {
|
||||||
if (!method.IsStatic || method.Body == null)
|
if (!method.IsStatic || method.Body == null)
|
||||||
continue;
|
continue;
|
||||||
if (method.Parameters.Count != 6)
|
var sig = method.MethodSig;
|
||||||
|
if (sig == null || sig.Params.Count != 6)
|
||||||
continue;
|
continue;
|
||||||
if (!DotNetUtils.isMethod(method, "System.UInt32", "(System.UInt64&,System.IntPtr,System.IntPtr,System.UInt32,System.IntPtr&,System.UInt32&)"))
|
if (!DotNetUtils.isMethod(method, "System.UInt32", "(System.UInt64&,System.IntPtr,System.IntPtr,System.UInt32,System.IntPtr&,System.UInt32&)"))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -20,31 +20,26 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using ICSharpCode.SharpZipLib.Zip.Compression;
|
using ICSharpCode.SharpZipLib.Zip.Compression;
|
||||||
using de4dot.PE;
|
using dot10.PE;
|
||||||
|
using dot10.IO;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
class NativeImageUnpacker {
|
class NativeImageUnpacker {
|
||||||
PeImage peImage;
|
MyPEImage peImage;
|
||||||
bool isNet1x;
|
bool isNet1x;
|
||||||
|
|
||||||
public NativeImageUnpacker(PeImage peImage) {
|
public NativeImageUnpacker(IPEImage peImage) {
|
||||||
this.peImage = peImage;
|
this.peImage = new MyPEImage(peImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] unpack() {
|
public byte[] unpack() {
|
||||||
var resources = peImage.Resources;
|
if (peImage.PEImage.Win32Resources == null)
|
||||||
var dir = resources.getRoot();
|
|
||||||
if ((dir = dir.getDirectory(10)) == null)
|
|
||||||
return null;
|
return null;
|
||||||
if ((dir = dir.getDirectory("__")) == null)
|
var dataEntry = peImage.PEImage.Win32Resources.Find(10, "__", 0);
|
||||||
return null;
|
|
||||||
var dataEntry = dir.getData(0);
|
|
||||||
if (dataEntry == null)
|
if (dataEntry == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var encryptedData = peImage.readBytes(dataEntry.RVA, (int)dataEntry.Size);
|
var encryptedData = dataEntry.Data.ReadAllBytes();
|
||||||
if (encryptedData.Length != dataEntry.Size)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var keyData = getKeyData();
|
var keyData = getKeyData();
|
||||||
if (keyData == null)
|
if (keyData == null)
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
class ProxyCallFixer : ProxyCallFixer3 {
|
class ProxyCallFixer : ProxyCallFixer3 {
|
||||||
ISimpleDeobfuscator simpleDeobfuscator;
|
ISimpleDeobfuscator simpleDeobfuscator;
|
||||||
|
|
||||||
public ProxyCallFixer(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator)
|
public ProxyCallFixer(ModuleDefMD module, ISimpleDeobfuscator simpleDeobfuscator)
|
||||||
: base(module) {
|
: base(module) {
|
||||||
this.simpleDeobfuscator = simpleDeobfuscator;
|
this.simpleDeobfuscator = simpleDeobfuscator;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
static MethodDef checkType(TypeDef type) {
|
static MethodDef checkType(TypeDef type) {
|
||||||
if (!new FieldTypes(type).exactly(requiredFields))
|
if (!new FieldTypes(type).exactly(requiredFields))
|
||||||
return null;
|
return null;
|
||||||
if (DotNetUtils.getMethod(type, ".cctor") == null)
|
if (type.FindStaticConstructor() == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return checkMethods(type);
|
return checkMethods(type);
|
||||||
|
@ -85,7 +85,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
var instrs = method.Body.Instructions;
|
var instrs = method.Body.Instructions;
|
||||||
for (int i = 0; i < instrs.Count - 1; i++) {
|
for (int i = 0; i < instrs.Count - 1; i++) {
|
||||||
var ldci4 = instrs[i];
|
var ldci4 = instrs[i];
|
||||||
if (!DotNetUtils.isLdcI4(ldci4))
|
if (!ldci4.IsLdcI4())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var call = instrs[i + 1];
|
var call = instrs[i + 1];
|
||||||
|
@ -95,13 +95,13 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
if (calledMethod == null || !isDelegateCreatorMethod(calledMethod))
|
if (calledMethod == null || !isDelegateCreatorMethod(calledMethod))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return module.LookupToken(0x02000000 + DotNetUtils.getLdcI4Value(ldci4)) as TypeDef;
|
return module.ResolveToken(0x02000000 + ldci4.GetLdcI4Value()) as TypeDef;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void getCallInfo(object context, FieldDef field, out MethodReference calledMethod, out OpCode callOpcode) {
|
protected override void getCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode) {
|
||||||
calledMethod = module.LookupToken(0x06000000 + field.MDToken.ToInt32()) as MethodReference;
|
calledMethod = module.ResolveToken(0x06000000 + field.MDToken.ToInt32()) as IMethod;
|
||||||
callOpcode = OpCodes.Call;
|
callOpcode = OpCodes.Call;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
class ResourceResolver {
|
class ResourceResolver {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
EncryptedResource encryptedResource;
|
EncryptedResource encryptedResource;
|
||||||
MethodDef initMethod;
|
MethodDef initMethod;
|
||||||
|
|
||||||
|
@ -45,12 +45,12 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
get { return encryptedResource.FoundResource; }
|
get { return encryptedResource.FoundResource; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceResolver(ModuleDefinition module) {
|
public ResourceResolver(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.encryptedResource = new EncryptedResource(module);
|
this.encryptedResource = new EncryptedResource(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceResolver(ModuleDefinition module, ResourceResolver oldOne) {
|
public ResourceResolver(ModuleDefMD module, ResourceResolver oldOne) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.encryptedResource = new EncryptedResource(module, oldOne.encryptedResource);
|
this.encryptedResource = new EncryptedResource(module, oldOne.encryptedResource);
|
||||||
}
|
}
|
||||||
|
@ -106,31 +106,31 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodDef findInitMethod(ISimpleDeobfuscator simpleDeobfuscator) {
|
MethodDef findInitMethod(ISimpleDeobfuscator simpleDeobfuscator) {
|
||||||
var ctor = DotNetUtils.getMethod(Type, ".ctor");
|
var ctor = Type.FindMethod(".ctor");
|
||||||
foreach (var method in Type.Methods) {
|
foreach (var method in Type.Methods) {
|
||||||
if (!method.IsStatic || method.Body == null)
|
if (!method.IsStatic || method.Body == null)
|
||||||
continue;
|
continue;
|
||||||
if (!DotNetUtils.isMethod(method, "System.Void", "()"))
|
if (!DotNetUtils.isMethod(method, "System.Void", "()"))
|
||||||
continue;
|
continue;
|
||||||
if (method.Body.Variables.Count > 1)
|
if (method.Body.LocalList.Count > 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
simpleDeobfuscator.deobfuscate(method);
|
simpleDeobfuscator.deobfuscate(method);
|
||||||
bool stsfldUsed = false, newobjUsed = false;
|
bool stsfldUsed = false, newobjUsed = false;
|
||||||
foreach (var instr in method.Body.Instructions) {
|
foreach (var instr in method.Body.Instructions) {
|
||||||
if (instr.OpCode.Code == Code.Stsfld) {
|
if (instr.OpCode.Code == Code.Stsfld) {
|
||||||
var field = instr.Operand as FieldReference;
|
var field = instr.Operand as IField;
|
||||||
if (field == null || field.FieldType.FullName != "System.Boolean")
|
if (field == null || field.FieldSig.GetFieldType().GetElementType() != ElementType.Boolean)
|
||||||
continue;
|
continue;
|
||||||
if (!MemberReferenceHelper.compareTypes(Type, field.DeclaringType))
|
if (!new SigComparer().Equals(Type, field.DeclaringType))
|
||||||
continue;
|
continue;
|
||||||
stsfldUsed = true;
|
stsfldUsed = true;
|
||||||
}
|
}
|
||||||
else if (instr.OpCode.Code == Code.Newobj) {
|
else if (instr.OpCode.Code == Code.Newobj) {
|
||||||
var calledCtor = instr.Operand as MethodReference;
|
var calledCtor = instr.Operand as IMethod;
|
||||||
if (calledCtor == null)
|
if (calledCtor == null)
|
||||||
continue;
|
continue;
|
||||||
if (!MemberReferenceHelper.compareMethodReferenceAndDeclaringType(calledCtor, ctor))
|
if (!MethodEqualityComparer.CompareDeclaringTypes.Equals(calledCtor, ctor))
|
||||||
continue;
|
continue;
|
||||||
newobjUsed = true;
|
newobjUsed = true;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
public EmbeddedResource mergeResources() {
|
public EmbeddedResource mergeResources() {
|
||||||
if (encryptedResource.Resource == null)
|
if (encryptedResource.Resource == null)
|
||||||
return null;
|
return null;
|
||||||
DeobUtils.decryptAndAddResources(module, encryptedResource.Resource.Name, () => {
|
DeobUtils.decryptAndAddResources(module, encryptedResource.Resource.Name.String, () => {
|
||||||
return QuickLZ.decompress(encryptedResource.decrypt());
|
return QuickLZ.decompress(encryptedResource.decrypt());
|
||||||
});
|
});
|
||||||
return encryptedResource.Resource;
|
return encryptedResource.Resource;
|
||||||
|
|
|
@ -27,7 +27,7 @@ using de4dot.PE;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
class StringDecrypter {
|
class StringDecrypter {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
EncryptedResource encryptedResource;
|
EncryptedResource encryptedResource;
|
||||||
List<DecrypterInfo> decrypterInfos = new List<DecrypterInfo>();
|
List<DecrypterInfo> decrypterInfos = new List<DecrypterInfo>();
|
||||||
MethodDef otherStringDecrypter;
|
MethodDef otherStringDecrypter;
|
||||||
|
@ -74,12 +74,12 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
get { return otherStringDecrypter; }
|
get { return otherStringDecrypter; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringDecrypter(ModuleDefinition module) {
|
public StringDecrypter(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.encryptedResource = new EncryptedResource(module);
|
this.encryptedResource = new EncryptedResource(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringDecrypter(ModuleDefinition module, StringDecrypter oldOne) {
|
public StringDecrypter(ModuleDefMD module, StringDecrypter oldOne) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.stringDecrypterVersion = oldOne.stringDecrypterVersion;
|
this.stringDecrypterVersion = oldOne.stringDecrypterVersion;
|
||||||
this.encryptedResource = new EncryptedResource(module, oldOne.encryptedResource);
|
this.encryptedResource = new EncryptedResource(module, oldOne.encryptedResource);
|
||||||
|
@ -137,12 +137,15 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
foreach (var method in type.Methods) {
|
foreach (var method in type.Methods) {
|
||||||
if (!method.IsStatic || !method.HasBody)
|
if (!method.IsStatic || !method.HasBody)
|
||||||
continue;
|
continue;
|
||||||
if (method.MethodReturnType.ReturnType.FullName != "System.String")
|
var sig = method.MethodSig;
|
||||||
|
if (sig == null)
|
||||||
continue;
|
continue;
|
||||||
if (method.Parameters.Count != 1)
|
if (sig.RetType.GetElementType() != ElementType.String)
|
||||||
continue;
|
continue;
|
||||||
if (method.Parameters[0].ParameterType.FullName != "System.Object" &&
|
if (sig.Params.Count != 1)
|
||||||
method.Parameters[0].ParameterType.FullName != "System.String")
|
continue;
|
||||||
|
if (sig.Params[0].GetElementType() != ElementType.Object &&
|
||||||
|
sig.Params[0].GetElementType() != ElementType.String)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
otherStringDecrypter = method;
|
otherStringDecrypter = method;
|
||||||
|
@ -176,7 +179,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||||
foreach (var calledMethod in DotNetUtils.getCalledMethods(module, method)) {
|
foreach (var calledMethod in DotNetUtils.getCalledMethods(module, method)) {
|
||||||
if (calledMethod.DeclaringType != method.DeclaringType)
|
if (calledMethod.DeclaringType != method.DeclaringType)
|
||||||
continue;
|
continue;
|
||||||
if (calledMethod.MethodReturnType.ReturnType.FullName != "System.Byte[]")
|
if (calledMethod.MethodSig.GetRetType().GetFullName() != "System.Byte[]")
|
||||||
continue;
|
continue;
|
||||||
var localTypes = new LocalTypes(calledMethod);
|
var localTypes = new LocalTypes(calledMethod);
|
||||||
if (!localTypes.all(requiredTypes))
|
if (!localTypes.all(requiredTypes))
|
||||||
|
|
|
@ -47,8 +47,8 @@ namespace de4dot.cui {
|
||||||
new de4dot.code.deobfuscators.DeepSea.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.DeepSea.DeobfuscatorInfo(),
|
||||||
new de4dot.code.deobfuscators.Dotfuscator.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.Dotfuscator.DeobfuscatorInfo(),
|
||||||
new de4dot.code.deobfuscators.dotNET_Reactor.v3.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.dotNET_Reactor.v3.DeobfuscatorInfo(),
|
||||||
#if PORT
|
|
||||||
new de4dot.code.deobfuscators.dotNET_Reactor.v4.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.dotNET_Reactor.v4.DeobfuscatorInfo(),
|
||||||
|
#if PORT
|
||||||
new de4dot.code.deobfuscators.Eazfuscator_NET.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.Eazfuscator_NET.DeobfuscatorInfo(),
|
||||||
new de4dot.code.deobfuscators.Goliath_NET.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.Goliath_NET.DeobfuscatorInfo(),
|
||||||
new de4dot.code.deobfuscators.ILProtector.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.ILProtector.DeobfuscatorInfo(),
|
||||||
|
|
2
dot10
2
dot10
|
@ -1 +1 @@
|
||||||
Subproject commit 4f392d624e7a9e23133801f2d18b0948e13e4411
|
Subproject commit 361768bfd38e6749d027ea8bf244b0a777c5d0d4
|
Loading…
Reference in New Issue
Block a user