Port Agile.NET deobfuscator
This commit is contained in:
parent
cc1e36389d
commit
583d4201f5
|
@ -202,7 +202,7 @@ namespace de4dot.blocks {
|
||||||
var sig = method.MethodSig;
|
var sig = method.MethodSig;
|
||||||
if (sig == null || !method.HasBody || !sig.IsDefault)
|
if (sig == null || !method.HasBody || !sig.IsDefault)
|
||||||
continue;
|
continue;
|
||||||
if (method.IsStatic != isStatic || method.Parameters.Count != argsTypes.Length)
|
if (method.IsStatic != isStatic || sig.Params.Count != argsTypes.Length)
|
||||||
continue;
|
continue;
|
||||||
if (sig.GenParamCount > 0)
|
if (sig.GenParamCount > 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -248,23 +248,24 @@ namespace de4dot.blocks {
|
||||||
return dll;
|
return dll;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PORT
|
public static bool hasPinvokeMethod(TypeDef type, string methodName) {
|
||||||
public static bool hasPinvokeMethod(TypeDefinition type, string methodName) {
|
|
||||||
return getPInvokeMethod(type, methodName) != null;
|
return getPInvokeMethod(type, methodName) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MethodDef getPInvokeMethod(TypeDefinition type, string methodName) {
|
public static MethodDef getPInvokeMethod(TypeDef type, string methodName) {
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return null;
|
return null;
|
||||||
|
var mname = new UTF8String(methodName);
|
||||||
foreach (var method in type.Methods) {
|
foreach (var method in type.Methods) {
|
||||||
if (method.PInvokeInfo == null)
|
if (method.ImplMap == null)
|
||||||
continue;
|
continue;
|
||||||
if (method.PInvokeInfo.EntryPoint == methodName)
|
if (UTF8String.Equals(method.ImplMap.Name, mname))
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PORT
|
||||||
public static MethodDef getPInvokeMethod(TypeDefinition type, string dll, string funcName) {
|
public static MethodDef getPInvokeMethod(TypeDefinition type, string dll, string funcName) {
|
||||||
foreach (var method in type.Methods) {
|
foreach (var method in type.Methods) {
|
||||||
if (isPinvokeMethod(method, dll, funcName))
|
if (isPinvokeMethod(method, dll, funcName))
|
||||||
|
|
|
@ -165,10 +165,10 @@ namespace de4dot.blocks.cflow {
|
||||||
|
|
||||||
var methodArgs = methodToInline.Parameters;
|
var methodArgs = methodToInline.Parameters;
|
||||||
var calledMethodArgs = DotNetUtils.getArgs(ctor);
|
var calledMethodArgs = DotNetUtils.getArgs(ctor);
|
||||||
if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count)
|
if (methodArgs.Count - popLastArgs != calledMethodArgs.Count)
|
||||||
return null;
|
return null;
|
||||||
for (int i = 1; i < calledMethodArgs.Count; i++) {
|
for (int i = 1; i < calledMethodArgs.Count; i++) {
|
||||||
if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1].Type))
|
if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i].Type))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,25 +57,25 @@
|
||||||
<Compile Include="AssemblyResolver.cs" />
|
<Compile Include="AssemblyResolver.cs" />
|
||||||
<Compile Include="DeobfuscatorContext.cs" />
|
<Compile Include="DeobfuscatorContext.cs" />
|
||||||
<Compile Include="deobfuscators\ArrayFinder.cs" />
|
<Compile Include="deobfuscators\ArrayFinder.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\CliSecureRtType.cs" />
|
<Compile Include="deobfuscators\Agile_NET\CliSecureRtType.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\CsBlowfish.cs" />
|
<Compile Include="deobfuscators\Agile_NET\CsBlowfish.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\Deobfuscator.cs" />
|
<Compile Include="deobfuscators\Agile_NET\Deobfuscator.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\MethodsDecrypter.cs" />
|
<Compile Include="deobfuscators\Agile_NET\MethodsDecrypter.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\ProxyCallFixer.cs" />
|
<Compile Include="deobfuscators\Agile_NET\ProxyCallFixer.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\ResourceDecrypter.cs" />
|
<Compile Include="deobfuscators\Agile_NET\ResourceDecrypter.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\StackFrameHelper.cs" />
|
<Compile Include="deobfuscators\Agile_NET\StackFrameHelper.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\StringDecrypter.cs" />
|
<Compile Include="deobfuscators\Agile_NET\StringDecrypter.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\vm\CilOperandInstructionRestorer.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\CilOperandInstructionRestorer.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\vm\Csvm.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\Csvm.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\vm\CsvmDataReader.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\CsvmDataReader.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\vm\CsvmMethodData.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\CsvmMethodData.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\vm\CsvmToCilMethodConverter.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\CsvmToCilMethodConverter.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\vm\FieldsInfo.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\FieldsInfo.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\vm\OpCodeHandler.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\OpCodeHandler.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\vm\OpCodeHandlers.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\OpCodeHandlers.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\vm\UnknownHandlerInfo.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\UnknownHandlerInfo.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\vm\VmOpCodeHandlerDetector.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\VmOpCodeHandlerDetector.cs" />
|
||||||
<None Include="deobfuscators\Agile_NET\vm\VmOperands.cs" />
|
<Compile Include="deobfuscators\Agile_NET\vm\VmOperands.cs" />
|
||||||
<None Include="deobfuscators\Babel_NET\AssemblyResolver.cs" />
|
<None Include="deobfuscators\Babel_NET\AssemblyResolver.cs" />
|
||||||
<None Include="deobfuscators\Babel_NET\BabelInflater.cs" />
|
<None Include="deobfuscators\Babel_NET\BabelInflater.cs" />
|
||||||
<None Include="deobfuscators\Babel_NET\BabelMethodCallInliner.cs" />
|
<None Include="deobfuscators\Babel_NET\BabelMethodCallInliner.cs" />
|
||||||
|
|
|
@ -26,7 +26,7 @@ using de4dot.PE;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
class CliSecureRtType {
|
class CliSecureRtType {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
TypeDef cliSecureRtType;
|
TypeDef cliSecureRtType;
|
||||||
MethodDef postInitializeMethod;
|
MethodDef postInitializeMethod;
|
||||||
MethodDef initializeMethod;
|
MethodDef initializeMethod;
|
||||||
|
@ -58,27 +58,11 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
get { return loadMethod; }
|
get { return loadMethod; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ModuleReference> DecryptModuleReferences {
|
public CliSecureRtType(ModuleDefMD module) {
|
||||||
get {
|
|
||||||
var list = new List<ModuleReference>();
|
|
||||||
addModuleReference(list, "_Initialize");
|
|
||||||
addModuleReference(list, "_Initialize64");
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addModuleReference(List<ModuleReference> list, string methodName) {
|
|
||||||
var method = DotNetUtils.getPInvokeMethod(cliSecureRtType, methodName);
|
|
||||||
if (method == null)
|
|
||||||
return;
|
|
||||||
list.Add(method.PInvokeInfo.Module);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CliSecureRtType(ModuleDefinition module) {
|
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CliSecureRtType(ModuleDefinition module, CliSecureRtType oldOne) {
|
public CliSecureRtType(ModuleDefMD module, CliSecureRtType oldOne) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
cliSecureRtType = lookup(oldOne.cliSecureRtType, "Could not find CliSecureRt type");
|
cliSecureRtType = lookup(oldOne.cliSecureRtType, "Could not find CliSecureRt type");
|
||||||
postInitializeMethod = lookup(oldOne.postInitializeMethod, "Could not find postInitializeMethod method");
|
postInitializeMethod = lookup(oldOne.postInitializeMethod, "Could not find postInitializeMethod method");
|
||||||
|
@ -88,7 +72,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
foundSig = oldOne.foundSig;
|
foundSig = oldOne.foundSig;
|
||||||
}
|
}
|
||||||
|
|
||||||
T lookup<T>(T def, string errorMessage) where T : MemberReference {
|
T lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
|
||||||
return DeobUtils.lookup(module, def, errorMessage);
|
return DeobUtils.lookup(module, def, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,13 +131,13 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
foreach (var type in module.Types) {
|
foreach (var type in module.Types) {
|
||||||
if (type.Fields.Count != 1)
|
if (type.Fields.Count != 1)
|
||||||
continue;
|
continue;
|
||||||
if (type.Fields[0].FieldType.FullName != "System.Byte[]")
|
if (type.Fields[0].FieldSig.GetFieldType().GetFullName() != "System.Byte[]")
|
||||||
continue;
|
continue;
|
||||||
if (type.Methods.Count != 2)
|
if (type.Methods.Count != 2)
|
||||||
continue;
|
continue;
|
||||||
if (DotNetUtils.getMethod(type, ".cctor") == null)
|
if (type.FindClassConstructor() == null)
|
||||||
continue;
|
continue;
|
||||||
var cs = DotNetUtils.getMethod(type, "cs");
|
var cs = type.FindMethod("cs");
|
||||||
if (cs == null)
|
if (cs == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -196,12 +180,13 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
var method = DotNetUtils.getPInvokeMethod(type, name);
|
var method = DotNetUtils.getPInvokeMethod(type, name);
|
||||||
if (method == null)
|
if (method == null)
|
||||||
return false;
|
return false;
|
||||||
if (method.Parameters.Count != 1)
|
var sig = method.MethodSig;
|
||||||
|
if (sig.Params.Count != 1)
|
||||||
return false;
|
return false;
|
||||||
if (method.Parameters[0].ParameterType.FullName != "System.IntPtr")
|
if (sig.Params[0].GetElementType() != ElementType.I)
|
||||||
return false;
|
return false;
|
||||||
var retType = method.MethodReturnType.ReturnType.FullName;
|
var retType = sig.RetType.GetElementType();
|
||||||
if (retType != "System.Void" && retType != "System.Int32")
|
if (retType != ElementType.Void && retType != ElementType.I4)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +194,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
bool findNativeCode(byte[] moduleBytes) {
|
bool findNativeCode(byte[] moduleBytes) {
|
||||||
var stream = moduleBytes != null ?
|
var stream = moduleBytes != null ?
|
||||||
(Stream)new MemoryStream(moduleBytes) :
|
(Stream)new MemoryStream(moduleBytes) :
|
||||||
(Stream)new FileStream(module.FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
(Stream)new FileStream(module.Location, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
using (stream) {
|
using (stream) {
|
||||||
var peImage = new PeImage(stream);
|
var peImage = new PeImage(stream);
|
||||||
return foundSig = MethodsDecrypter.detect(peImage);
|
return foundSig = MethodsDecrypter.detect(peImage);
|
||||||
|
|
|
@ -19,8 +19,9 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using dot10.PE;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using Mono.MyStuff;
|
using dot10.DotNet.MD;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using de4dot.PE;
|
using de4dot.PE;
|
||||||
|
|
||||||
|
@ -112,16 +113,17 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void init(ModuleDefinition module) {
|
public override void init(ModuleDefMD module) {
|
||||||
base.init(module);
|
base.init(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] unpackNativeFile(PeImage peImage) {
|
public override byte[] unpackNativeFile(PEImage peImage) {
|
||||||
return unpackNativeFile1(peImage) ?? unpackNativeFile2(peImage);
|
return unpackNativeFile1(peImage) ?? unpackNativeFile2(peImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Old CS versions
|
// Old CS versions
|
||||||
byte[] unpackNativeFile1(PeImage peImage) {
|
byte[] unpackNativeFile1(PEImage peImage) {
|
||||||
|
#if PORT
|
||||||
const int dataDirNum = 6; // debug dir
|
const int dataDirNum = 6; // debug dir
|
||||||
const int dotNetDirNum = 14;
|
const int dotNetDirNum = 14;
|
||||||
|
|
||||||
|
@ -139,10 +141,14 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
writeUInt32(fileData, dataDir + 4, 0);
|
writeUInt32(fileData, dataDir + 4, 0);
|
||||||
ModuleBytes = fileData;
|
ModuleBytes = fileData;
|
||||||
return fileData;
|
return fileData;
|
||||||
|
#else
|
||||||
|
return null;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// CS 1.x
|
// CS 1.x
|
||||||
byte[] unpackNativeFile2(PeImage peImage) {
|
byte[] unpackNativeFile2(PEImage peImage) {
|
||||||
|
#if PORT
|
||||||
var dir = peImage.Resources.getRoot();
|
var dir = peImage.Resources.getRoot();
|
||||||
if ((dir = dir.getDirectory("ASSEMBLY")) == null)
|
if ((dir = dir.getDirectory("ASSEMBLY")) == null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -153,6 +159,9 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return ModuleBytes = peImage.readBytes(data.RVA, (int)data.Size);
|
return ModuleBytes = peImage.readBytes(data.RVA, (int)data.Size);
|
||||||
|
#else
|
||||||
|
return null;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeUInt32(byte[] data, int offset, uint value) {
|
static void writeUInt32(byte[] data, int offset, uint value) {
|
||||||
|
@ -221,7 +230,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
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.cliSecureAttributes = lookup(module, cliSecureAttributes, "Could not find CliSecure attribute");
|
newOne.cliSecureAttributes = lookup(module, cliSecureAttributes, "Could not find CliSecure attribute");
|
||||||
|
@ -233,7 +242,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
return newOne;
|
return newOne;
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<TypeDef> lookup(ModuleDefinition module, List<TypeDef> types, string errorMsg) {
|
static List<TypeDef> lookup(ModuleDefMD module, List<TypeDef> types, string errorMsg) {
|
||||||
var list = new List<TypeDef>(types.Count);
|
var list = new List<TypeDef>(types.Count);
|
||||||
foreach (var type in types)
|
foreach (var type in types)
|
||||||
list.Add(DeobUtils.lookup(module, type, errorMsg));
|
list.Add(DeobUtils.lookup(module, type, errorMsg));
|
||||||
|
@ -274,7 +283,6 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
|
|
||||||
if (options.RestoreVmCode) {
|
if (options.RestoreVmCode) {
|
||||||
csvm.restore();
|
csvm.restore();
|
||||||
addAssemblyReferenceToBeRemoved(csvm.VmAssemblyReference, "CSVM assembly reference");
|
|
||||||
addResourceToBeRemoved(csvm.Resource, "CSVM data resource");
|
addResourceToBeRemoved(csvm.Resource, "CSVM data resource");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,11 +316,9 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
}
|
}
|
||||||
if (options.DecryptMethods) {
|
if (options.DecryptMethods) {
|
||||||
addResources("Obfuscator protection files");
|
addResources("Obfuscator protection files");
|
||||||
addModuleReferencesToBeRemoved(cliSecureRtType.DecryptModuleReferences, "Obfuscator protection files");
|
|
||||||
addModuleReferences("Obfuscator protection files");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.Attributes |= ModuleAttributes.ILOnly;
|
module.Cor20HeaderFlags |= ComImageFlags.ILOnly;
|
||||||
|
|
||||||
base.deobfuscateEnd();
|
base.deobfuscateEnd();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Mono.MyStuff;
|
using dot10.DotNet;
|
||||||
|
using dot10.DotNet.MD;
|
||||||
using de4dot.PE;
|
using de4dot.PE;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
}
|
}
|
||||||
|
|
||||||
PeImage peImage;
|
PeImage peImage;
|
||||||
Mono.Cecil.ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
CliSecureRtType csRtType;
|
CliSecureRtType csRtType;
|
||||||
CodeHeader codeHeader = new CodeHeader();
|
CodeHeader codeHeader = new CodeHeader();
|
||||||
IDecrypter decrypter;
|
IDecrypter decrypter;
|
||||||
|
@ -434,7 +435,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool decrypt(PeImage peImage, Mono.Cecil.ModuleDefinition module, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) {
|
public bool decrypt(PeImage peImage, ModuleDefMD module, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) {
|
||||||
this.peImage = peImage;
|
this.peImage = peImage;
|
||||||
this.csRtType = csRtType;
|
this.csRtType = csRtType;
|
||||||
this.module = module;
|
this.module = module;
|
||||||
|
@ -446,7 +447,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
case DecryptResult.Error:
|
case DecryptResult.Error:
|
||||||
Log.w("Using dynamic method decryption");
|
Log.w("Using dynamic method decryption");
|
||||||
byte[] moduleCctorBytes = getModuleCctorBytes(csRtType);
|
byte[] moduleCctorBytes = getModuleCctorBytes(csRtType);
|
||||||
dumpedMethods = de4dot.code.deobfuscators.MethodsDecrypter.decrypt(module.FullyQualifiedName, moduleCctorBytes);
|
dumpedMethods = de4dot.code.deobfuscators.MethodsDecrypter.decrypt(module.Location, moduleCctorBytes);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -542,7 +543,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
var dm = new DumpedMethod();
|
var dm = new DumpedMethod();
|
||||||
dm.token = 0x06000001 + (uint)i;
|
dm.token = 0x06000001 + (uint)i;
|
||||||
|
|
||||||
var method = (Mono.Cecil.MethodDef)module.LookupToken((int)dm.token);
|
var method = (MethodDef)module.ResolveMethod(MDToken.ToRID(dm.token));
|
||||||
if (method == null || method.DeclaringType == DotNetUtils.getModuleType(module))
|
if (method == null || method.DeclaringType == DotNetUtils.getModuleType(module))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -25,13 +25,11 @@ using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
class ProxyCallFixer : ProxyCallFixer1 {
|
class ProxyCallFixer : ProxyCallFixer1 {
|
||||||
IList<MemberReference> memberReferences;
|
public ProxyCallFixer(ModuleDefMD module)
|
||||||
|
|
||||||
public ProxyCallFixer(ModuleDefinition module)
|
|
||||||
: base(module) {
|
: base(module) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProxyCallFixer(ModuleDefinition module, ProxyCallFixer oldOne)
|
public ProxyCallFixer(ModuleDefMD module, ProxyCallFixer oldOne)
|
||||||
: base(module) {
|
: base(module) {
|
||||||
foreach (var method in oldOne.delegateCreatorMethods)
|
foreach (var method in oldOne.delegateCreatorMethods)
|
||||||
setDelegateCreatorMethod(lookup(method, "Could not find delegate creator method"));
|
setDelegateCreatorMethod(lookup(method, "Could not find delegate creator method"));
|
||||||
|
@ -53,14 +51,14 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
var instrs = cctor.Body.Instructions;
|
var instrs = cctor.Body.Instructions;
|
||||||
if (instrs.Count != 3)
|
if (instrs.Count != 3)
|
||||||
return null;
|
return null;
|
||||||
if (!DotNetUtils.isLdcI4(instrs[0].OpCode.Code))
|
if (!instrs[0].IsLdcI4())
|
||||||
return null;
|
return null;
|
||||||
if (instrs[1].OpCode != OpCodes.Call || !isDelegateCreatorMethod(instrs[1].Operand as MethodDef))
|
if (instrs[1].OpCode != OpCodes.Call || !isDelegateCreatorMethod(instrs[1].Operand as MethodDef))
|
||||||
return null;
|
return null;
|
||||||
if (instrs[2].OpCode != OpCodes.Ret)
|
if (instrs[2].OpCode != OpCodes.Ret)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
int delegateToken = 0x02000001 + DotNetUtils.getLdcI4Value(instrs[0]);
|
int delegateToken = 0x02000001 + instrs[0].GetLdcI4Value();
|
||||||
if (type.MDToken.ToInt32() != delegateToken) {
|
if (type.MDToken.ToInt32() != delegateToken) {
|
||||||
Log.w("Delegate token is not current type");
|
Log.w("Delegate token is not current type");
|
||||||
return null;
|
return null;
|
||||||
|
@ -69,11 +67,8 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
return new object();
|
return new object();
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
if (memberReferences == null)
|
var name = field.Name.String;
|
||||||
memberReferences = new List<MemberReference>(module.GetMemberReferences());
|
|
||||||
|
|
||||||
var name = field.Name;
|
|
||||||
callOpcode = OpCodes.Call;
|
callOpcode = OpCodes.Call;
|
||||||
if (name.EndsWith("%", StringComparison.Ordinal)) {
|
if (name.EndsWith("%", StringComparison.Ordinal)) {
|
||||||
callOpcode = OpCodes.Callvirt;
|
callOpcode = OpCodes.Callvirt;
|
||||||
|
@ -81,9 +76,10 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
}
|
}
|
||||||
byte[] value = Convert.FromBase64String(name);
|
byte[] value = Convert.FromBase64String(name);
|
||||||
int methodIndex = BitConverter.ToInt32(value, 0); // 0-based memberRef index
|
int methodIndex = BitConverter.ToInt32(value, 0); // 0-based memberRef index
|
||||||
if (methodIndex >= memberReferences.Count)
|
var mr = module.ResolveMemberRef((uint)methodIndex + 1);
|
||||||
throw new ApplicationException(string.Format("methodIndex ({0}) >= memberReferences.Count ({1})", methodIndex, memberReferences.Count));
|
if (mr == null || !mr.IsMethodRef)
|
||||||
calledMethod = memberReferences[methodIndex] as MethodReference;
|
throw new ApplicationException(string.Format("Invalid MemberRef index: {0}", methodIndex));
|
||||||
|
calledMethod = mr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,12 +20,13 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using dot10.IO;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
class ResourceDecrypter {
|
class ResourceDecrypter {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
TypeDef rsrcType;
|
TypeDef rsrcType;
|
||||||
MethodDef rsrcRrrMethod;
|
MethodDef rsrcRrrMethod;
|
||||||
MethodDef rsrcResolveMethod;
|
MethodDef rsrcResolveMethod;
|
||||||
|
@ -42,18 +43,18 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
get { return rsrcRrrMethod; }
|
get { return rsrcRrrMethod; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceDecrypter(ModuleDefinition module) {
|
public ResourceDecrypter(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceDecrypter(ModuleDefinition module, ResourceDecrypter oldOne) {
|
public ResourceDecrypter(ModuleDefMD module, ResourceDecrypter oldOne) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
rsrcType = lookup(oldOne.rsrcType, "Could not find rsrcType");
|
rsrcType = lookup(oldOne.rsrcType, "Could not find rsrcType");
|
||||||
rsrcRrrMethod = lookup(oldOne.rsrcRrrMethod, "Could not find rsrcRrrMethod");
|
rsrcRrrMethod = lookup(oldOne.rsrcRrrMethod, "Could not find rsrcRrrMethod");
|
||||||
rsrcResolveMethod = lookup(oldOne.rsrcResolveMethod, "Could not find rsrcResolveMethod");
|
rsrcResolveMethod = lookup(oldOne.rsrcResolveMethod, "Could not find rsrcResolveMethod");
|
||||||
}
|
}
|
||||||
|
|
||||||
T lookup<T>(T def, string errorMessage) where T : MemberReference {
|
T lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
|
||||||
return DeobUtils.lookup(module, def, errorMessage);
|
return DeobUtils.lookup(module, def, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,15 +100,14 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
var resource = DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(rsrcResolveMethod)) as EmbeddedResource;
|
var resource = DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(rsrcResolveMethod)) as EmbeddedResource;
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
return null;
|
return null;
|
||||||
DeobUtils.decryptAndAddResources(module, resource.Name, () => decryptResource(resource));
|
DeobUtils.decryptAndAddResources(module, resource.Name.String, () => decryptResource(resource));
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] decryptResource(EmbeddedResource resource) {
|
byte[] decryptResource(EmbeddedResource resource) {
|
||||||
using (var rsrcStream = resource.GetResourceStream()) {
|
using (var reader = resource.Data) {
|
||||||
using (var reader = new BinaryReader(rsrcStream)) {
|
|
||||||
var key = reader.ReadString();
|
var key = reader.ReadString();
|
||||||
var data = reader.ReadBytes((int)(rsrcStream.Length - rsrcStream.Position));
|
var data = reader.ReadBytes((int)(reader.Length - reader.Position));
|
||||||
var cryptoTransform = new DESCryptoServiceProvider {
|
var cryptoTransform = new DESCryptoServiceProvider {
|
||||||
Key = Encoding.ASCII.GetBytes(key),
|
Key = Encoding.ASCII.GetBytes(key),
|
||||||
IV = Encoding.ASCII.GetBytes(key),
|
IV = Encoding.ASCII.GetBytes(key),
|
||||||
|
@ -120,4 +120,3 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
class StackFrameHelper {
|
class StackFrameHelper {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
TypeDef stackFrameHelperType;
|
TypeDef stackFrameHelperType;
|
||||||
ExceptionLoggerRemover exceptionLoggerRemover = new ExceptionLoggerRemover();
|
ExceptionLoggerRemover exceptionLoggerRemover = new ExceptionLoggerRemover();
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
get { return exceptionLoggerRemover; }
|
get { return exceptionLoggerRemover; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackFrameHelper(ModuleDefinition module) {
|
public StackFrameHelper(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,17 +48,16 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
|
|
||||||
MethodDef errorMethod = null;
|
MethodDef errorMethod = null;
|
||||||
foreach (var method in type.Methods) {
|
foreach (var method in type.Methods) {
|
||||||
if (method.IsRuntimeSpecialName && method.Name == ".ctor" && !method.HasParameters)
|
if (method.Name == ".ctor")
|
||||||
continue; // .ctor is allowed
|
continue; // .ctor is allowed
|
||||||
if (method.IsRuntimeSpecialName && method.Name == ".cctor" && !method.HasParameters)
|
if (method.Name == ".cctor")
|
||||||
continue; // .cctor is allowed
|
continue; // .cctor is allowed
|
||||||
if (method.IsStatic && method.CallingConvention == MethodCallingConvention.Default &&
|
var sig = method.MethodSig;
|
||||||
method.ExplicitThis == false && method.HasThis == false &&
|
if (sig != null && method.IsStatic && method.HasBody &&
|
||||||
method.HasBody && method.IsManaged && method.IsIL && method.HasParameters &&
|
sig.Params.Count == 2 && !method.HasGenericParameters &&
|
||||||
method.Parameters.Count == 2 && !method.HasGenericParameters &&
|
|
||||||
!DotNetUtils.hasReturnValue(method) &&
|
!DotNetUtils.hasReturnValue(method) &&
|
||||||
method.Parameters[0].ParameterType.FullName == "System.Exception" &&
|
sig.Params[0].GetFullName() == "System.Exception" &&
|
||||||
method.Parameters[1].ParameterType.FullName == "System.Object[]") {
|
sig.Params[1].GetFullName() == "System.Object[]") {
|
||||||
errorMethod = method;
|
errorMethod = method;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -23,7 +23,7 @@ using dot10.DotNet;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET {
|
namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
class StringDecrypter {
|
class StringDecrypter {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
TypeDef stringDecrypterType;
|
TypeDef stringDecrypterType;
|
||||||
MethodDef stringDecrypterMethod;
|
MethodDef stringDecrypterMethod;
|
||||||
byte[] stringDecrypterKey;
|
byte[] stringDecrypterKey;
|
||||||
|
@ -41,19 +41,19 @@ namespace de4dot.code.deobfuscators.Agile_NET {
|
||||||
set { stringDecrypterMethod = value; }
|
set { stringDecrypterMethod = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringDecrypter(ModuleDefinition module, MethodDef stringDecrypterMethod) {
|
public StringDecrypter(ModuleDefMD module, MethodDef stringDecrypterMethod) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.stringDecrypterMethod = stringDecrypterMethod;
|
this.stringDecrypterMethod = stringDecrypterMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringDecrypter(ModuleDefinition module, StringDecrypter oldOne) {
|
public StringDecrypter(ModuleDefMD module, StringDecrypter oldOne) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
stringDecrypterType = lookup(oldOne.stringDecrypterType, "Could not find stringDecrypterType");
|
stringDecrypterType = lookup(oldOne.stringDecrypterType, "Could not find stringDecrypterType");
|
||||||
stringDecrypterMethod = lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod");
|
stringDecrypterMethod = lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod");
|
||||||
stringDecrypterKey = oldOne.stringDecrypterKey;
|
stringDecrypterKey = oldOne.stringDecrypterKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
T lookup<T>(T def, string errorMessage) where T : MemberReference {
|
T lookup<T>(T def, string errorMessage) where T : class, ICodedToken {
|
||||||
return DeobUtils.lookup(module, def, errorMessage);
|
return DeobUtils.lookup(module, def, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using dot10.DotNet.Emit;
|
using dot10.DotNet.Emit;
|
||||||
using Mono.Cecil.Metadata;
|
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
|
@ -43,13 +42,13 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
if (instr.Operand != null)
|
if (instr.Operand != null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TypeReference operandType = null;
|
TypeSig operandType = null;
|
||||||
switch (instr.OpCode.Code) {
|
switch (instr.OpCode.Code) {
|
||||||
case Code.Ldelema:
|
case Code.Ldelema:
|
||||||
var arrayType = MethodStack.getLoadedType(method, instrs, i, 1) as ArrayType;
|
var arrayType = MethodStack.getLoadedType(method, instrs, i, 1) as SZArraySig;
|
||||||
if (arrayType == null)
|
if (arrayType == null)
|
||||||
break;
|
break;
|
||||||
operandType = arrayType.ElementType;
|
operandType = arrayType.Next;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Code.Ldobj:
|
case Code.Ldobj:
|
||||||
|
@ -70,58 +69,58 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
instr.Operand = operandType;
|
instr.Operand = operandType.ToTypeDefOrRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
return !atLeastOneFailed;
|
return !atLeastOneFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TypeReference getPtrElementType(TypeReference type) {
|
static TypeSig getPtrElementType(TypeSig type) {
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return null;
|
return null;
|
||||||
var pt = type as PointerType;
|
if (type.IsPointer || type.IsByRef)
|
||||||
if (pt != null)
|
return type.Next;
|
||||||
return pt.ElementType;
|
|
||||||
var bt = type as ByReferenceType;
|
|
||||||
if (bt != null)
|
|
||||||
return bt.ElementType;
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValidType(TypeReference type) {
|
bool isValidType(TypeSig type) {
|
||||||
|
type = type.RemovePinnedAndModifiers();
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return false;
|
return false;
|
||||||
if (type.EType == ElementType.Void)
|
if (type.ElementType == ElementType.Void)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (type != null) {
|
while (type != null) {
|
||||||
switch (MemberReferenceHelper.getMemberReferenceType(type)) {
|
switch (type.ElementType) {
|
||||||
case CecilType.ArrayType:
|
case ElementType.SZArray:
|
||||||
case CecilType.GenericInstanceType:
|
case ElementType.Array:
|
||||||
case CecilType.PointerType:
|
case ElementType.GenericInst:
|
||||||
case CecilType.TypeDef:
|
case ElementType.Ptr:
|
||||||
case CecilType.TypeReference:
|
case ElementType.Class:
|
||||||
case CecilType.FunctionPointerType:
|
case ElementType.ValueType:
|
||||||
|
case ElementType.FnPtr:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CecilType.GenericParam:
|
case ElementType.MVar:
|
||||||
var gp = (GenericParam)type;
|
var gmvar = (GenericMVar)type;
|
||||||
if (method.DeclaringType != gp.Owner && method != gp.Owner)
|
if (gmvar.Number >= method.MethodSig.GetGenParamCount())
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CecilType.ByReferenceType:
|
case ElementType.Var:
|
||||||
case CecilType.OptionalModifierType:
|
var gvar = (GenericVar)type;
|
||||||
case CecilType.PinnedType:
|
var dt = method.DeclaringType;
|
||||||
case CecilType.RequiredModifierType:
|
if (dt == null || gvar.Number >= dt.GenericParams.Count)
|
||||||
case CecilType.SentinelType:
|
return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ElementType.ByRef:
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (type.Next == null)
|
||||||
if (!(type is TypeSpecification))
|
|
||||||
break;
|
break;
|
||||||
type = ((TypeSpecification)type).ElementType;
|
type = type.Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return type != null;
|
return type != null;
|
||||||
|
|
|
@ -26,9 +26,9 @@ using de4dot.blocks;
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
class Csvm {
|
class Csvm {
|
||||||
IDeobfuscatorContext deobfuscatorContext;
|
IDeobfuscatorContext deobfuscatorContext;
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
EmbeddedResource resource;
|
EmbeddedResource resource;
|
||||||
AssemblyNameReference vmAssemblyReference;
|
AssemblyRef vmAssemblyReference;
|
||||||
|
|
||||||
public bool Detected {
|
public bool Detected {
|
||||||
get { return resource != null && vmAssemblyReference != null; }
|
get { return resource != null && vmAssemblyReference != null; }
|
||||||
|
@ -38,22 +38,22 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
get { return Detected ? resource : null; }
|
get { return Detected ? resource : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public AssemblyNameReference VmAssemblyReference {
|
public AssemblyRef VmAssemblyReference {
|
||||||
get { return Detected ? vmAssemblyReference : null; }
|
get { return Detected ? vmAssemblyReference : null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefinition module) {
|
public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module) {
|
||||||
this.deobfuscatorContext = deobfuscatorContext;
|
this.deobfuscatorContext = deobfuscatorContext;
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefinition module, Csvm oldOne) {
|
public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module, Csvm oldOne) {
|
||||||
this.deobfuscatorContext = deobfuscatorContext;
|
this.deobfuscatorContext = deobfuscatorContext;
|
||||||
this.module = module;
|
this.module = module;
|
||||||
if (oldOne.resource != null)
|
if (oldOne.resource != null)
|
||||||
this.resource = (EmbeddedResource)module.Resources[oldOne.module.Resources.IndexOf(oldOne.resource)];
|
this.resource = (EmbeddedResource)module.Resources[oldOne.module.Resources.IndexOf(oldOne.resource)];
|
||||||
if (oldOne.vmAssemblyReference != null)
|
if (oldOne.vmAssemblyReference != null)
|
||||||
this.vmAssemblyReference = module.AssemblyReferences[oldOne.module.AssemblyReferences.IndexOf(oldOne.vmAssemblyReference)];
|
this.vmAssemblyReference = module.ResolveAssemblyRef(oldOne.vmAssemblyReference.Rid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void find() {
|
public void find() {
|
||||||
|
@ -61,13 +61,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
vmAssemblyReference = findVmAssemblyReference();
|
vmAssemblyReference = findVmAssemblyReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyNameReference findVmAssemblyReference() {
|
AssemblyRef findVmAssemblyReference() {
|
||||||
foreach (var memberRef in module.GetMemberReferences()) {
|
foreach (var memberRef in module.GetMemberRefs()) {
|
||||||
var method = memberRef as MethodReference;
|
if (!memberRef.IsMethodRef)
|
||||||
if (method == null)
|
|
||||||
continue;
|
continue;
|
||||||
if (method.FullName == "System.Object VMRuntime.Libraries.CSVMRuntime::RunMethod(System.String,System.Object[])")
|
if (memberRef.FullName == "System.Object VMRuntime.Libraries.CSVMRuntime::RunMethod(System.String,System.Object[])")
|
||||||
return method.DeclaringType.Scope as AssemblyNameReference;
|
return memberRef.DeclaringType.Scope as AssemblyRef;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -94,11 +93,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
Log.indent();
|
Log.indent();
|
||||||
|
|
||||||
var opcodeDetector = getVmOpCodeHandlerDetector();
|
var opcodeDetector = getVmOpCodeHandlerDetector();
|
||||||
var csvmMethods = new CsvmDataReader(resource.GetResourceStream()).read();
|
var csvmMethods = new CsvmDataReader(resource.Data).read();
|
||||||
var converter = new CsvmToCilMethodConverter(deobfuscatorContext, module, opcodeDetector);
|
var converter = new CsvmToCilMethodConverter(deobfuscatorContext, module, opcodeDetector);
|
||||||
var methodPrinter = new MethodPrinter();
|
var methodPrinter = new MethodPrinter();
|
||||||
foreach (var csvmMethod in csvmMethods) {
|
foreach (var csvmMethod in csvmMethods) {
|
||||||
var cilMethod = module.LookupToken(csvmMethod.Token) as MethodDef;
|
var cilMethod = module.ResolveToken(csvmMethod.Token) as MethodDef;
|
||||||
if (cilMethod == null)
|
if (cilMethod == null)
|
||||||
throw new ApplicationException(string.Format("Could not find method {0:X8}", csvmMethod.Token));
|
throw new ApplicationException(string.Format("Could not find method {0:X8}", csvmMethod.Token));
|
||||||
converter.convert(cilMethod, csvmMethod);
|
converter.convert(cilMethod, csvmMethod);
|
||||||
|
@ -117,8 +116,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
|
|
||||||
Log.v("Locals:");
|
Log.v("Locals:");
|
||||||
Log.indent();
|
Log.indent();
|
||||||
for (int i = 0; i < method.Body.Variables.Count; i++)
|
for (int i = 0; i < method.Body.LocalList.Count; i++)
|
||||||
Log.v("#{0}: {1}", i, method.Body.Variables[i].VariableType);
|
Log.v("#{0}: {1}", i, method.Body.LocalList[i].Type);
|
||||||
Log.deIndent();
|
Log.deIndent();
|
||||||
|
|
||||||
Log.v("Code:");
|
Log.v("Code:");
|
||||||
|
@ -131,7 +130,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
|
|
||||||
VmOpCodeHandlerDetector getVmOpCodeHandlerDetector() {
|
VmOpCodeHandlerDetector getVmOpCodeHandlerDetector() {
|
||||||
var vmFilename = vmAssemblyReference.Name + ".dll";
|
var vmFilename = vmAssemblyReference.Name + ".dll";
|
||||||
var vmModulePath = Path.Combine(Path.GetDirectoryName(module.FullyQualifiedName), vmFilename);
|
var vmModulePath = Path.Combine(Path.GetDirectoryName(module.Location), vmFilename);
|
||||||
Log.v("CSVM filename: {0}", vmFilename);
|
Log.v("CSVM filename: {0}", vmFilename);
|
||||||
|
|
||||||
var dataKey = "cs cached VmOpCodeHandlerDetector";
|
var dataKey = "cs cached VmOpCodeHandlerDetector";
|
||||||
|
@ -141,7 +140,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
VmOpCodeHandlerDetector detector;
|
VmOpCodeHandlerDetector detector;
|
||||||
if (dict.TryGetValue(vmModulePath, out detector))
|
if (dict.TryGetValue(vmModulePath, out detector))
|
||||||
return detector;
|
return detector;
|
||||||
dict[vmModulePath] = detector = new VmOpCodeHandlerDetector(ModuleDefinition.ReadModule(vmModulePath));
|
dict[vmModulePath] = detector = new VmOpCodeHandlerDetector(ModuleDefMD.Load(vmModulePath));
|
||||||
|
|
||||||
detector.findHandlers();
|
detector.findHandlers();
|
||||||
Log.v("CSVM opcodes:");
|
Log.v("CSVM opcodes:");
|
||||||
|
|
|
@ -20,15 +20,16 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using dot10.IO;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
class CsvmDataReader {
|
class CsvmDataReader {
|
||||||
BinaryReader reader;
|
IBinaryReader reader;
|
||||||
|
|
||||||
public CsvmDataReader(Stream stream) {
|
public CsvmDataReader(IBinaryReader reader) {
|
||||||
reader = new BinaryReader(stream);
|
this.reader = reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CsvmMethodData> read() {
|
public List<CsvmMethodData> read() {
|
||||||
|
|
|
@ -22,17 +22,16 @@ 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.Cecil.Metadata;
|
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
class CsvmToCilMethodConverter {
|
class CsvmToCilMethodConverter {
|
||||||
IDeobfuscatorContext deobfuscatorContext;
|
IDeobfuscatorContext deobfuscatorContext;
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
VmOpCodeHandlerDetector opCodeDetector;
|
VmOpCodeHandlerDetector opCodeDetector;
|
||||||
CilOperandInstructionRestorer operandRestorer = new CilOperandInstructionRestorer();
|
CilOperandInstructionRestorer operandRestorer = new CilOperandInstructionRestorer();
|
||||||
|
|
||||||
public CsvmToCilMethodConverter(IDeobfuscatorContext deobfuscatorContext, ModuleDefinition module, VmOpCodeHandlerDetector opCodeDetector) {
|
public CsvmToCilMethodConverter(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module, VmOpCodeHandlerDetector opCodeDetector) {
|
||||||
this.deobfuscatorContext = deobfuscatorContext;
|
this.deobfuscatorContext = deobfuscatorContext;
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.opCodeDetector = opCodeDetector;
|
this.opCodeDetector = opCodeDetector;
|
||||||
|
@ -44,7 +43,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
var newExceptions = readExceptions(cilMethod, csvmMethod, newInstructions);
|
var newExceptions = readExceptions(cilMethod, csvmMethod, newInstructions);
|
||||||
|
|
||||||
fixInstructionOperands(newInstructions);
|
fixInstructionOperands(newInstructions);
|
||||||
fixLocals(newInstructions, cilMethod.Body.Variables);
|
fixLocals(newInstructions, cilMethod.Body.LocalList);
|
||||||
fixArgs(newInstructions, cilMethod);
|
fixArgs(newInstructions, cilMethod);
|
||||||
|
|
||||||
DotNetUtils.restoreBody(cilMethod, newInstructions, newExceptions);
|
DotNetUtils.restoreBody(cilMethod, newInstructions, newExceptions);
|
||||||
|
@ -54,7 +53,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
restoreConstrainedPrefix(cilMethod);
|
restoreConstrainedPrefix(cilMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fixLocals(IList<Instruction> instrs, IList<VariableDefinition> locals) {
|
void fixLocals(IList<Instruction> instrs, IList<Local> locals) {
|
||||||
foreach (var instr in instrs) {
|
foreach (var instr in instrs) {
|
||||||
var op = instr.Operand as LocalOperand;
|
var op = instr.Operand as LocalOperand;
|
||||||
if (op == null)
|
if (op == null)
|
||||||
|
@ -64,7 +63,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void updateLocalInstruction(Instruction instr, VariableDefinition local, int index) {
|
static void updateLocalInstruction(Instruction instr, Local local, int index) {
|
||||||
object operand = null;
|
object operand = null;
|
||||||
OpCode opcode;
|
OpCode opcode;
|
||||||
|
|
||||||
|
@ -135,19 +134,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
if (op == null)
|
if (op == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int argIndex = op.arg;
|
updateArgInstruction(instr, method.Parameters[op.arg], op.arg);
|
||||||
if (method.HasImplicitThis)
|
|
||||||
argIndex--;
|
|
||||||
ParameterDefinition arg;
|
|
||||||
if (argIndex == -1)
|
|
||||||
arg = method.Body.ThisParameter;
|
|
||||||
else
|
|
||||||
arg = method.Parameters[argIndex];
|
|
||||||
updateArgInstruction(instr, arg, op.arg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void updateArgInstruction(Instruction instr, ParameterDefinition arg, int index) {
|
static void updateArgInstruction(Instruction instr, Parameter arg, int index) {
|
||||||
switch (instr.OpCode.Code) {
|
switch (instr.OpCode.Code) {
|
||||||
case Code.Ldarg:
|
case Code.Ldarg:
|
||||||
case Code.Ldarg_S:
|
case Code.Ldarg_S:
|
||||||
|
@ -209,12 +200,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
List<Instruction> readInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) {
|
List<Instruction> readInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) {
|
||||||
var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions));
|
var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions));
|
||||||
var instrs = new List<Instruction>();
|
var instrs = new List<Instruction>();
|
||||||
int offset = 0;
|
uint offset = 0;
|
||||||
while (reader.BaseStream.Position < reader.BaseStream.Length) {
|
while (reader.BaseStream.Position < reader.BaseStream.Length) {
|
||||||
int vmOpCode = reader.ReadUInt16();
|
int vmOpCode = reader.ReadUInt16();
|
||||||
var instr = opCodeDetector.Handlers[vmOpCode].Read(reader);
|
var instr = opCodeDetector.Handlers[vmOpCode].Read(reader);
|
||||||
instr.Offset = offset;
|
instr.Offset = offset;
|
||||||
offset += getInstructionSize(instr);
|
offset += (uint)getInstructionSize(instr);
|
||||||
instrs.Add(instr);
|
instrs.Add(instr);
|
||||||
}
|
}
|
||||||
return instrs;
|
return instrs;
|
||||||
|
@ -230,8 +221,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
return instr.OpCode.Size + (op.targetDisplacements.Length + 1) * 4;
|
return instr.OpCode.Size + (op.targetDisplacements.Length + 1) * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<VariableDefinition> readLocals(MethodDef cilMethod, CsvmMethodData csvmMethod) {
|
List<Local> readLocals(MethodDef cilMethod, CsvmMethodData csvmMethod) {
|
||||||
var locals = new List<VariableDefinition>();
|
var locals = new List<Local>();
|
||||||
var reader = new BinaryReader(new MemoryStream(csvmMethod.Locals));
|
var reader = new BinaryReader(new MemoryStream(csvmMethod.Locals));
|
||||||
|
|
||||||
if (csvmMethod.Locals.Length == 0)
|
if (csvmMethod.Locals.Length == 0)
|
||||||
|
@ -243,63 +234,58 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
throw new ApplicationException("Invalid number of locals");
|
throw new ApplicationException("Invalid number of locals");
|
||||||
|
|
||||||
for (int i = 0; i < numLocals; i++)
|
for (int i = 0; i < numLocals; i++)
|
||||||
locals.Add(new VariableDefinition(readTypeReference(reader)));
|
locals.Add(new Local(readTypeReference(reader)));
|
||||||
|
|
||||||
return locals;
|
return locals;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeReference readTypeReference(BinaryReader reader) {
|
TypeSig readTypeReference(BinaryReader reader) {
|
||||||
var etype = (ElementType)reader.ReadInt32();
|
var etype = (ElementType)reader.ReadInt32();
|
||||||
switch (etype) {
|
switch (etype) {
|
||||||
case ElementType.Void: return module.TypeSystem.Void;
|
case ElementType.Void: return module.CorLibTypes.Void;
|
||||||
case ElementType.Boolean: return module.TypeSystem.Boolean;
|
case ElementType.Boolean: return module.CorLibTypes.Boolean;
|
||||||
case ElementType.Char: return module.TypeSystem.Char;
|
case ElementType.Char: return module.CorLibTypes.Char;
|
||||||
case ElementType.I1: return module.TypeSystem.SByte;
|
case ElementType.I1: return module.CorLibTypes.SByte;
|
||||||
case ElementType.U1: return module.TypeSystem.Byte;
|
case ElementType.U1: return module.CorLibTypes.Byte;
|
||||||
case ElementType.I2: return module.TypeSystem.Int16;
|
case ElementType.I2: return module.CorLibTypes.Int16;
|
||||||
case ElementType.U2: return module.TypeSystem.UInt16;
|
case ElementType.U2: return module.CorLibTypes.UInt16;
|
||||||
case ElementType.I4: return module.TypeSystem.Int32;
|
case ElementType.I4: return module.CorLibTypes.Int32;
|
||||||
case ElementType.U4: return module.TypeSystem.UInt32;
|
case ElementType.U4: return module.CorLibTypes.UInt32;
|
||||||
case ElementType.I8: return module.TypeSystem.Int64;
|
case ElementType.I8: return module.CorLibTypes.Int64;
|
||||||
case ElementType.U8: return module.TypeSystem.UInt64;
|
case ElementType.U8: return module.CorLibTypes.UInt64;
|
||||||
case ElementType.R4: return module.TypeSystem.Single;
|
case ElementType.R4: return module.CorLibTypes.Single;
|
||||||
case ElementType.R8: return module.TypeSystem.Double;
|
case ElementType.R8: return module.CorLibTypes.Double;
|
||||||
case ElementType.String: return module.TypeSystem.String;
|
case ElementType.String: return module.CorLibTypes.String;
|
||||||
case ElementType.TypedByRef: return module.TypeSystem.TypedReference;
|
case ElementType.TypedByRef: return module.CorLibTypes.TypedReference;
|
||||||
case ElementType.I: return module.TypeSystem.IntPtr;
|
case ElementType.I: return module.CorLibTypes.IntPtr;
|
||||||
case ElementType.U: return module.TypeSystem.UIntPtr;
|
case ElementType.U: return module.CorLibTypes.UIntPtr;
|
||||||
case ElementType.Object: return module.TypeSystem.Object;
|
case ElementType.Object: return module.CorLibTypes.Object;
|
||||||
|
|
||||||
case ElementType.ValueType:
|
case ElementType.ValueType:
|
||||||
case ElementType.Var:
|
case ElementType.Var:
|
||||||
case ElementType.MVar:
|
case ElementType.MVar:
|
||||||
return (TypeReference)module.LookupToken(reader.ReadInt32());
|
return (module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef).ToTypeSig();
|
||||||
|
|
||||||
case ElementType.GenericInst:
|
case ElementType.GenericInst:
|
||||||
etype = (ElementType)reader.ReadInt32();
|
etype = (ElementType)reader.ReadInt32();
|
||||||
if (etype == ElementType.ValueType)
|
if (etype == ElementType.ValueType)
|
||||||
return (TypeReference)module.LookupToken(reader.ReadInt32());
|
return (module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef).ToTypeSig();
|
||||||
// ElementType.Class
|
// ElementType.Class
|
||||||
return module.TypeSystem.Object;
|
return module.CorLibTypes.Object;
|
||||||
|
|
||||||
case ElementType.Ptr:
|
case ElementType.Ptr:
|
||||||
case ElementType.Class:
|
case ElementType.Class:
|
||||||
case ElementType.Array:
|
case ElementType.Array:
|
||||||
case ElementType.FnPtr:
|
case ElementType.FnPtr:
|
||||||
case ElementType.SzArray:
|
case ElementType.SZArray:
|
||||||
case ElementType.ByRef:
|
case ElementType.ByRef:
|
||||||
case ElementType.CModReqD:
|
case ElementType.CModReqd:
|
||||||
case ElementType.CModOpt:
|
case ElementType.CModOpt:
|
||||||
case ElementType.Internal:
|
case ElementType.Internal:
|
||||||
case ElementType.Modifier:
|
|
||||||
case ElementType.Sentinel:
|
case ElementType.Sentinel:
|
||||||
case ElementType.Pinned:
|
case ElementType.Pinned:
|
||||||
case ElementType.Type:
|
|
||||||
case ElementType.Boxed:
|
|
||||||
case ElementType.Enum:
|
|
||||||
case ElementType.None:
|
|
||||||
default:
|
default:
|
||||||
return module.TypeSystem.Object;
|
return module.CorLibTypes.Object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +307,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
eh.HandlerStart = getInstruction(cilInstructions, reader.ReadInt32());
|
eh.HandlerStart = getInstruction(cilInstructions, reader.ReadInt32());
|
||||||
eh.HandlerEnd = getInstructionEnd(cilInstructions, reader.ReadInt32());
|
eh.HandlerEnd = getInstructionEnd(cilInstructions, reader.ReadInt32());
|
||||||
if (eh.HandlerType == ExceptionHandlerType.Catch)
|
if (eh.HandlerType == ExceptionHandlerType.Catch)
|
||||||
eh.CatchType = (TypeReference)module.LookupToken(reader.ReadInt32());
|
eh.CatchType = module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef;
|
||||||
else if (eh.HandlerType == ExceptionHandlerType.Filter)
|
else if (eh.HandlerType == ExceptionHandlerType.Filter)
|
||||||
eh.FilterStart = getInstruction(cilInstructions, reader.ReadInt32());
|
eh.FilterStart = getInstruction(cilInstructions, reader.ReadInt32());
|
||||||
|
|
||||||
|
@ -387,9 +373,9 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
throw new ApplicationException(string.Format("Unknown operand type: {0}", vmOperand.GetType()));
|
throw new ApplicationException(string.Format("Unknown operand type: {0}", vmOperand.GetType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldReference fixLoadStoreFieldInstruction(Instruction instr, int token, OpCode staticInstr, OpCode instanceInstr) {
|
IField fixLoadStoreFieldInstruction(Instruction instr, int token, OpCode staticInstr, OpCode instanceInstr) {
|
||||||
var fieldRef = (FieldReference)module.LookupToken(token);
|
var fieldRef = module.ResolveToken(token) as IField;
|
||||||
var field = deobfuscatorContext.resolve(fieldRef);
|
var field = deobfuscatorContext.resolveField(fieldRef);
|
||||||
bool isStatic;
|
bool isStatic;
|
||||||
if (field == null) {
|
if (field == null) {
|
||||||
Log.w("Could not resolve field {0:X8}. Assuming it's not static.", token);
|
Log.w("Could not resolve field {0:X8}. Assuming it's not static.", token);
|
||||||
|
@ -401,8 +387,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
return fieldRef;
|
return fieldRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemberReference getMemberReference(int token) {
|
ITokenOperand getMemberReference(int token) {
|
||||||
var memberRef = module.LookupToken(token) as MemberReference;
|
var memberRef = module.ResolveToken(token) as ITokenOperand;
|
||||||
if (memberRef == null)
|
if (memberRef == null)
|
||||||
throw new ApplicationException(string.Format("Could not find member ref: {0:X8}", token));
|
throw new ApplicationException(string.Format("Could not find member ref: {0:X8}", token));
|
||||||
return memberRef;
|
return memberRef;
|
||||||
|
@ -418,15 +404,18 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
if (instr.OpCode.Code != Code.Callvirt)
|
if (instr.OpCode.Code != Code.Callvirt)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var calledMethod = instr.Operand as MethodReference;
|
var calledMethod = instr.Operand as IMethod;
|
||||||
if (calledMethod == null || !calledMethod.HasThis)
|
if (calledMethod == null)
|
||||||
continue;
|
continue;
|
||||||
var thisType = MethodStack.getLoadedType(method, instrs, i, calledMethod.Parameters.Count) as ByReferenceType;
|
var sig = calledMethod.MethodSig;
|
||||||
|
if (sig == null || !sig.HasThis)
|
||||||
|
continue;
|
||||||
|
var thisType = MethodStack.getLoadedType(method, instrs, i, sig.Params.Count) as ByRefSig;
|
||||||
if (thisType == null)
|
if (thisType == null)
|
||||||
continue;
|
continue;
|
||||||
if (hasPrefix(instrs, i, Code.Constrained))
|
if (hasPrefix(instrs, i, Code.Constrained))
|
||||||
continue;
|
continue;
|
||||||
instrs.Insert(i, Instruction.Create(OpCodes.Constrained, thisType.ElementType));
|
instrs.Insert(i, Instruction.Create(OpCodes.Constrained, thisType.Next.ToTypeDefOrRef()));
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
|
|
||||||
public FieldsInfo(IEnumerable<FieldDef> fields) {
|
public FieldsInfo(IEnumerable<FieldDef> fields) {
|
||||||
foreach (var field in fields) {
|
foreach (var field in fields) {
|
||||||
var fieldTypeDef = field.FieldType as TypeDef;
|
var fieldTypeDef = field.FieldSig.GetFieldType().TryGetTypeDef();
|
||||||
if (fieldTypeDef != null && fieldTypeDef.IsEnum)
|
if (fieldTypeDef != null && fieldTypeDef.IsEnum)
|
||||||
addEnum();
|
addEnum();
|
||||||
else
|
else
|
||||||
add(field.FieldType);
|
add(field.FieldSig.GetFieldType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,8 +50,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(TypeReference type) {
|
void add(TypeSig type) {
|
||||||
add(type.FullName);
|
add(type.GetFullName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(string typeFullName) {
|
void add(string typeFullName) {
|
||||||
|
|
|
@ -23,7 +23,6 @@ using System.IO;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
using dot10.DotNet;
|
using dot10.DotNet;
|
||||||
using dot10.DotNet.Emit;
|
using dot10.DotNet.Emit;
|
||||||
using Mono.Cecil.Metadata;
|
|
||||||
|
|
||||||
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
partial class OpCodeHandler {
|
partial class OpCodeHandler {
|
||||||
|
@ -248,7 +247,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
new InstructionInfo2 { First = false, Second = true, Value = 12, OpCode = OpCodes.Stelem_R4 },
|
new InstructionInfo2 { First = false, Second = true, Value = 12, OpCode = OpCodes.Stelem_R4 },
|
||||||
new InstructionInfo2 { First = false, Second = true, Value = 13, OpCode = OpCodes.Stelem_R8 },
|
new InstructionInfo2 { First = false, Second = true, Value = 13, OpCode = OpCodes.Stelem_R8 },
|
||||||
new InstructionInfo2 { First = false, Second = true, Value = 28, OpCode = OpCodes.Stelem_Ref },
|
new InstructionInfo2 { First = false, Second = true, Value = 28, OpCode = OpCodes.Stelem_Ref },
|
||||||
new InstructionInfo2 { First = false, Second = false, Value = 0, OpCode = OpCodes.Stelem_Any },
|
new InstructionInfo2 { First = false, Second = false, Value = 0, OpCode = OpCodes.Stelem },
|
||||||
|
|
||||||
new InstructionInfo2 { First = true, Second = true, Value = 24, OpCode = OpCodes.Ldelem_I },
|
new InstructionInfo2 { First = true, Second = true, Value = 24, OpCode = OpCodes.Ldelem_I },
|
||||||
new InstructionInfo2 { First = true, Second = true, Value = 4, OpCode = OpCodes.Ldelem_I1 },
|
new InstructionInfo2 { First = true, Second = true, Value = 4, OpCode = OpCodes.Ldelem_I1 },
|
||||||
|
@ -261,7 +260,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
new InstructionInfo2 { First = true, Second = true, Value = 12, OpCode = OpCodes.Ldelem_R4 },
|
new InstructionInfo2 { First = true, Second = true, Value = 12, OpCode = OpCodes.Ldelem_R4 },
|
||||||
new InstructionInfo2 { First = true, Second = true, Value = 13, OpCode = OpCodes.Ldelem_R8 },
|
new InstructionInfo2 { First = true, Second = true, Value = 13, OpCode = OpCodes.Ldelem_R8 },
|
||||||
new InstructionInfo2 { First = true, Second = true, Value = 28, OpCode = OpCodes.Ldelem_Ref },
|
new InstructionInfo2 { First = true, Second = true, Value = 28, OpCode = OpCodes.Ldelem_Ref },
|
||||||
new InstructionInfo2 { First = true, Second = false, Value = 0, OpCode = OpCodes.Ldelem_Any },
|
new InstructionInfo2 { First = true, Second = false, Value = 0, OpCode = OpCodes.Ldelem },
|
||||||
};
|
};
|
||||||
static Instruction ldelem_read(BinaryReader reader) {
|
static Instruction ldelem_read(BinaryReader reader) {
|
||||||
Instruction instr = null;
|
Instruction instr = null;
|
||||||
|
@ -463,7 +462,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rethrow_check(UnknownHandlerInfo info) {
|
static bool rethrow_check(UnknownHandlerInfo info) {
|
||||||
return info.ExecuteMethod.Body.Variables.Count == 0;
|
return info.ExecuteMethod.Body.LocalList.Count == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Instruction rethrow_read(BinaryReader reader) {
|
static Instruction rethrow_read(BinaryReader reader) {
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
if (method.Body == null)
|
if (method.Body == null)
|
||||||
continue;
|
continue;
|
||||||
foreach (var instr in method.Body.Instructions) {
|
foreach (var instr in method.Body.Instructions) {
|
||||||
var fieldRef = instr.Operand as FieldReference;
|
var fieldRef = instr.Operand as IField;
|
||||||
if (fieldRef == null)
|
if (fieldRef == null)
|
||||||
continue;
|
continue;
|
||||||
var field = typeFields.find(fieldRef);
|
var field = typeFields.find(fieldRef);
|
||||||
|
@ -119,7 +119,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
throw new ApplicationException("Found another read method");
|
throw new ApplicationException("Found another read method");
|
||||||
readMethod = method;
|
readMethod = method;
|
||||||
}
|
}
|
||||||
else if (!DotNetUtils.hasReturnValue(method) && method.Parameters.Count == 1) {
|
else if (!DotNetUtils.hasReturnValue(method) && method.MethodSig.GetParamCount() == 1) {
|
||||||
if (executeMethod != null)
|
if (executeMethod != null)
|
||||||
throw new ApplicationException("Found another execute method");
|
throw new ApplicationException("Found another execute method");
|
||||||
executeMethod = method;
|
executeMethod = method;
|
||||||
|
@ -146,8 +146,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
foreach (var instr in method.Body.Instructions) {
|
foreach (var instr in method.Body.Instructions) {
|
||||||
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
|
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
|
||||||
continue;
|
continue;
|
||||||
var calledMethod = instr.Operand as MethodReference;
|
var calledMethod = instr.Operand as IMethod;
|
||||||
if (!MemberReferenceHelper.compareMethodReferenceAndDeclaringType(calledMethod, csvmInfo.PopMethod))
|
if (!MethodEqualityComparer.CompareDeclaringTypes.Equals(calledMethod, csvmInfo.PopMethod))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
|
@ -44,14 +44,14 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
}
|
}
|
||||||
|
|
||||||
class VmOpCodeHandlerDetector {
|
class VmOpCodeHandlerDetector {
|
||||||
ModuleDefinition module;
|
ModuleDefMD module;
|
||||||
List<OpCodeHandler> opCodeHandlers;
|
List<OpCodeHandler> opCodeHandlers;
|
||||||
|
|
||||||
public List<OpCodeHandler> Handlers {
|
public List<OpCodeHandler> Handlers {
|
||||||
get { return opCodeHandlers; }
|
get { return opCodeHandlers; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public VmOpCodeHandlerDetector(ModuleDefinition module) {
|
public VmOpCodeHandlerDetector(ModuleDefMD module) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,10 +88,10 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
int enumTypes = 0;
|
int enumTypes = 0;
|
||||||
int objectTypes = 0;
|
int objectTypes = 0;
|
||||||
foreach (var field in type.Fields) {
|
foreach (var field in type.Fields) {
|
||||||
var fieldType = field.FieldType as TypeDef;
|
var fieldType = field.FieldSig.GetFieldType().TryGetTypeDef();
|
||||||
if (fieldType != null && fieldType.IsEnum)
|
if (fieldType != null && fieldType.IsEnum)
|
||||||
enumTypes++;
|
enumTypes++;
|
||||||
if (field.FieldType.FullName == "System.Object")
|
if (field.FieldSig.GetFieldType().GetElementType() == ElementType.Object)
|
||||||
objectTypes++;
|
objectTypes++;
|
||||||
}
|
}
|
||||||
if (enumTypes != 1 || objectTypes != 1)
|
if (enumTypes != 1 || objectTypes != 1)
|
||||||
|
@ -109,7 +109,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isStackType(TypeDef type, TypeDef stackValueType) {
|
bool isStackType(TypeDef type, TypeDef stackValueType) {
|
||||||
if (type.Interfaces.Count != 2)
|
if (type.InterfaceImpls.Count != 2)
|
||||||
return false;
|
return false;
|
||||||
if (!implementsInterface(type, "System.Collections.ICollection"))
|
if (!implementsInterface(type, "System.Collections.ICollection"))
|
||||||
return false;
|
return false;
|
||||||
|
@ -124,11 +124,14 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
foreach (var field in type.Fields) {
|
foreach (var field in type.Fields) {
|
||||||
if (field.IsLiteral)
|
if (field.IsLiteral)
|
||||||
continue;
|
continue;
|
||||||
if (field.FieldType is ArrayType && ((ArrayType)field.FieldType).ElementType == stackValueType)
|
var fieldType = field.FieldSig.GetFieldType();
|
||||||
|
if (fieldType == null)
|
||||||
|
continue;
|
||||||
|
if (fieldType.IsSZArray && fieldType.Next.TryGetTypeDef() == stackValueType)
|
||||||
stackValueTypes++;
|
stackValueTypes++;
|
||||||
if (field.FieldType.FullName == "System.Int32")
|
if (fieldType.ElementType == ElementType.I4)
|
||||||
int32Types++;
|
int32Types++;
|
||||||
if (field.FieldType.FullName == "System.Object")
|
if (fieldType.ElementType == ElementType.Object)
|
||||||
objectTypes++;
|
objectTypes++;
|
||||||
}
|
}
|
||||||
if (stackValueTypes != 2 || int32Types != 2 || objectTypes != 1)
|
if (stackValueTypes != 2 || int32Types != 2 || objectTypes != 1)
|
||||||
|
@ -138,8 +141,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool implementsInterface(TypeDef type, string ifaceName) {
|
static bool implementsInterface(TypeDef type, string ifaceName) {
|
||||||
foreach (var iface in type.Interfaces) {
|
foreach (var iface in type.InterfaceImpls) {
|
||||||
if (iface.FullName == ifaceName)
|
if (iface.Interface.FullName == ifaceName)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -147,7 +150,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
|
|
||||||
void initStackTypeMethods(CsvmInfo csvmInfo) {
|
void initStackTypeMethods(CsvmInfo csvmInfo) {
|
||||||
foreach (var method in csvmInfo.Stack.Methods) {
|
foreach (var method in csvmInfo.Stack.Methods) {
|
||||||
if (method.Parameters.Count == 0 && method.MethodReturnType.ReturnType == csvmInfo.StackValue) {
|
var sig = method.MethodSig;
|
||||||
|
if (sig != null && sig.Params.Count == 0 && sig.RetType.TryGetTypeDef() == csvmInfo.StackValue) {
|
||||||
if (hasAdd(method))
|
if (hasAdd(method))
|
||||||
csvmInfo.PopMethod = method;
|
csvmInfo.PopMethod = method;
|
||||||
else
|
else
|
||||||
|
@ -172,7 +176,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm {
|
||||||
};
|
};
|
||||||
var cflowDeobfuscator = new CflowDeobfuscator();
|
var cflowDeobfuscator = new CflowDeobfuscator();
|
||||||
foreach (var type in module.Types) {
|
foreach (var type in module.Types) {
|
||||||
var cctor = DotNetUtils.getMethod(type, ".cctor");
|
var cctor = type.FindClassConstructor();
|
||||||
if (cctor == null)
|
if (cctor == null)
|
||||||
continue;
|
continue;
|
||||||
requiredFields[0] = type.FullName;
|
requiredFields[0] = type.FullName;
|
||||||
|
|
|
@ -37,9 +37,9 @@ namespace de4dot.cui {
|
||||||
static IList<IDeobfuscatorInfo> createDeobfuscatorInfos() {
|
static IList<IDeobfuscatorInfo> createDeobfuscatorInfos() {
|
||||||
return new List<IDeobfuscatorInfo> {
|
return new List<IDeobfuscatorInfo> {
|
||||||
new de4dot.code.deobfuscators.Unknown.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.Unknown.DeobfuscatorInfo(),
|
||||||
|
new de4dot.code.deobfuscators.Agile_NET.DeobfuscatorInfo(),
|
||||||
#if PORT
|
#if PORT
|
||||||
new de4dot.code.deobfuscators.Babel_NET.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.Babel_NET.DeobfuscatorInfo(),
|
||||||
new de4dot.code.deobfuscators.Agile_NET.DeobfuscatorInfo(),
|
|
||||||
new de4dot.code.deobfuscators.CodeFort.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.CodeFort.DeobfuscatorInfo(),
|
||||||
new de4dot.code.deobfuscators.CodeVeil.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.CodeVeil.DeobfuscatorInfo(),
|
||||||
new de4dot.code.deobfuscators.CodeWall.DeobfuscatorInfo(),
|
new de4dot.code.deobfuscators.CodeWall.DeobfuscatorInfo(),
|
||||||
|
|
2
dot10
2
dot10
|
@ -1 +1 @@
|
||||||
Subproject commit cf50ec12f7cc258eb23cad730eee638b65e8dfc8
|
Subproject commit 13f15527e9b8f99c2fddfd386714835a0f4b9d0b
|
Loading…
Reference in New Issue
Block a user