Port Agile.NET deobfuscator

This commit is contained in:
de4dot 2012-11-07 05:17:45 +01:00
parent cc1e36389d
commit 583d4201f5
20 changed files with 235 additions and 257 deletions

View File

@ -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))

View File

@ -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;
} }

View File

@ -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" />

View File

@ -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);

View File

@ -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();
} }

View File

@ -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;

View File

@ -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;
} }
} }
} }

View File

@ -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),
@ -119,5 +119,4 @@ namespace de4dot.code.deobfuscators.Agile_NET {
} }
} }
} }
}
} }

View File

@ -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

View File

@ -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);
} }

View File

@ -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;

View File

@ -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:");

View File

@ -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() {

View File

@ -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++;
} }
} }

View File

@ -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) {

View File

@ -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) {

View File

@ -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++;

View File

@ -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;

View File

@ -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

@ -1 +1 @@
Subproject commit cf50ec12f7cc258eb23cad730eee638b65e8dfc8 Subproject commit 13f15527e9b8f99c2fddfd386714835a0f4b9d0b