Add static methods decrypter and refactor into multiple classes

This commit is contained in:
de4dot 2011-11-06 12:19:26 +01:00
parent a0509d2735
commit f424e8eabf
8 changed files with 645 additions and 201 deletions

View File

@ -56,8 +56,13 @@
<Compile Include="AssemblyResolver.cs" />
<Compile Include="CommandLineParser.cs" />
<Compile Include="deobfuscators\ArrayFinder.cs" />
<Compile Include="deobfuscators\CliSecure\CliSecureRtType.cs" />
<Compile Include="deobfuscators\CliSecure\Deobfuscator.cs" />
<Compile Include="deobfuscators\CliSecure\MethodsDecrypter.cs" />
<Compile Include="deobfuscators\CliSecure\ProxyDelegateFinder.cs" />
<Compile Include="deobfuscators\CliSecure\ResourceDecrypter.cs" />
<Compile Include="deobfuscators\CliSecure\StackFrameHelper.cs" />
<Compile Include="deobfuscators\CliSecure\StringDecrypter.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\AntiDebugger.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\AssemblyResolver.cs" />
<Compile Include="deobfuscators\CryptoObfuscator\Deobfuscator.cs" />

View File

@ -0,0 +1,118 @@
/*
Copyright (C) 2011 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using Mono.Cecil;
namespace de4dot.deobfuscators.CliSecure {
class CliSecureRtType {
ModuleDefinition module;
TypeDefinition cliSecureRtType;
MethodDefinition postInitializeMethod;
MethodDefinition initializeMethod;
MethodDefinition stringDecrypterMethod;
MethodDefinition loadMethod;
public bool Detected {
get { return cliSecureRtType != null; }
}
public TypeDefinition Type {
get { return cliSecureRtType; }
}
public MethodDefinition StringDecrypterMethod {
get { return stringDecrypterMethod; }
}
public MethodDefinition PostInitializeMethod {
get { return postInitializeMethod; }
}
public MethodDefinition InitializeMethod {
get { return initializeMethod; }
}
public MethodDefinition LoadMethod {
get { return loadMethod; }
}
public CliSecureRtType(ModuleDefinition module) {
this.module = module;
}
public CliSecureRtType(ModuleDefinition module, CliSecureRtType oldOne) {
this.module = module;
cliSecureRtType = lookup(oldOne.cliSecureRtType, "Could not find CliSecureRt type");
postInitializeMethod = lookup(oldOne.postInitializeMethod, "Could not find postInitializeMethod method");
initializeMethod = lookup(oldOne.initializeMethod, "Could not find initializeMethod method");
stringDecrypterMethod = lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod method");
loadMethod = lookup(oldOne.loadMethod, "Could not find loadMethod method");
}
T lookup<T>(T def, string errorMessage) where T : MemberReference {
return DeobUtils.lookup(module, def, errorMessage);
}
public void find() {
if (cliSecureRtType != null)
return;
foreach (var type in module.Types) {
if (type.Namespace != "")
continue;
var typeName = type.FullName;
MethodDefinition cs = null;
MethodDefinition initialize = null;
MethodDefinition postInitialize = null;
MethodDefinition load = null;
int methods = 0;
foreach (var method in type.Methods) {
if (method.FullName == "System.String " + typeName + "::cs(System.String)") {
cs = method;
methods++;
}
else if (method.FullName == "System.Void " + typeName + "::Initialize()") {
initialize = method;
methods++;
}
else if (method.FullName == "System.Void " + typeName + "::PostInitialize()") {
postInitialize = method;
methods++;
}
else if (method.FullName == "System.IntPtr " + typeName + "::Load()") {
load = method;
methods++;
}
}
if (methods < 2)
continue;
stringDecrypterMethod = cs;
initializeMethod = initialize;
postInitializeMethod = postInitialize;
loadMethod = load;
cliSecureRtType = type;
return;
}
}
}
}

View File

@ -18,23 +18,24 @@
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.MyStuff;
using de4dot.blocks;
namespace de4dot.deobfuscators.CliSecure {
class DeobfuscatorInfo : DeobfuscatorInfoBase {
public const string THE_NAME = "CliSecure";
const string DEFAULT_REGEX = @"[a-zA-Z_0-9>}$]$";
BoolOption decryptMethods;
BoolOption fixResources;
BoolOption removeStackFrameHelper;
public DeobfuscatorInfo()
: base(DEFAULT_REGEX) {
decryptMethods = new BoolOption(null, makeArgName("methods"), "Decrypt methods", true);
fixResources = new BoolOption(null, makeArgName("rsrc"), "Decrypt resources", true);
removeStackFrameHelper = new BoolOption(null, makeArgName("stack"), "Remove all StackFrameHelper code", true);
}
@ -50,6 +51,7 @@ namespace de4dot.deobfuscators.CliSecure {
public override IDeobfuscator createDeobfuscator() {
return new Deobfuscator(new Deobfuscator.Options {
ValidNameRegex = validNameRegex.get(),
DecryptMethods = decryptMethods.get(),
FixResources = fixResources.get(),
RemoveStackFrameHelper = removeStackFrameHelper.get(),
});
@ -57,6 +59,7 @@ namespace de4dot.deobfuscators.CliSecure {
protected override IEnumerable<Option> getOptionsInternal() {
return new List<Option>() {
decryptMethods,
fixResources,
removeStackFrameHelper,
};
@ -65,25 +68,17 @@ namespace de4dot.deobfuscators.CliSecure {
class Deobfuscator : DeobfuscatorBase {
Options options;
bool foundCliSecureAttribute = false;
bool foundProxyDelegateMethod = false;
MethodDefinition decryptStringMethod;
byte[] decryptStringBuffer;
TypeDefinition cliSecureAttribute;
ProxyDelegateFinder proxyDelegateFinder;
CliSecureRtType cliSecureRtType;
StringDecrypter stringDecrypter;
TypeDefinition cliSecureRtType;
MethodDefinition postInitializeMethod;
MethodDefinition initializeMethod;
TypeDefinition stackFrameHelperType;
ExceptionLoggerRemover exceptionLoggerRemover = new ExceptionLoggerRemover();
MethodDefinition rsrcRrrMethod;
MethodDefinition rsrcDecryptMethod;
ResourceDecrypter resourceDecrypter;
StackFrameHelper stackFrameHelper;
internal class Options : OptionsBase {
public bool DecryptMethods { get; set; }
public bool FixResources { get; set; }
public bool RemoveStackFrameHelper { get; set; }
}
@ -108,215 +103,96 @@ namespace de4dot.deobfuscators.CliSecure {
protected override int detectInternal() {
int val = 0;
if (cliSecureRtType != null || foundCliSecureAttribute)
if (cliSecureRtType.Detected || cliSecureAttribute != null)
val += 100;
if (decryptStringBuffer != null)
if (stringDecrypter.Detected)
val += 10;
if (foundProxyDelegateMethod)
if (proxyDelegateFinder.Detected)
val += 10;
return val;
}
protected override void scanForObfuscator() {
proxyDelegateFinder = new ProxyDelegateFinder(module);
findCliSecureAttribute();
findCliSecureRtType();
findStringDecryptBuffer();
findDelegateCreatorType();
cliSecureRtType = new CliSecureRtType(module);
cliSecureRtType.find();
stringDecrypter = new StringDecrypter(module, cliSecureRtType.StringDecrypterMethod);
stringDecrypter.find();
proxyDelegateFinder = new ProxyDelegateFinder(module);
proxyDelegateFinder.findDelegateCreator();
}
void findCliSecureAttribute() {
foreach (var type in module.Types) {
if (type.FullName == "SecureTeam.Attributes.ObfuscatedByCliSecureAttribute") {
this.addAttributeToBeRemoved(type, "Obfuscator attribute");
foundCliSecureAttribute = true;
cliSecureAttribute = type;
break;
}
}
}
void findCliSecureRtType() {
if (cliSecureRtType != null)
return;
public override bool getDecryptedModule(ref byte[] newFileData, ref Dictionary<uint, DumpedMethod> dumpedMethods) {
if (!options.DecryptMethods)
return false;
foreach (var type in module.Types) {
if (type.Namespace != "")
continue;
var typeName = type.FullName;
MethodDefinition cs = null;
MethodDefinition initialize = null;
MethodDefinition postInitialize = null;
MethodDefinition load = null;
int methods = 0;
foreach (var method in type.Methods) {
if (method.FullName == "System.String " + typeName + "::cs(System.String)") {
cs = method;
methods++;
}
else if (method.FullName == "System.Void " + typeName + "::Initialize()") {
initialize = method;
methods++;
}
else if (method.FullName == "System.Void " + typeName + "::PostInitialize()") {
postInitialize = method;
methods++;
}
else if (method.FullName == "System.IntPtr " + typeName + "::Load()") {
load = method;
methods++;
}
}
if (methods < 2)
continue;
decryptStringMethod = cs;
initializeMethod = initialize;
postInitializeMethod = postInitialize;
cliSecureRtType = type;
if (load != null)
findPossibleNamesToRemove(load);
return;
byte[] fileData;
using (var fileStream = new FileStream(module.FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read)) {
fileData = new byte[(int)fileStream.Length];
fileStream.Read(fileData, 0, fileData.Length);
}
var peImage = new PE.PeImage(fileData);
if (!new MethodsDecrypter().decrypt(peImage, ref dumpedMethods))
return false;
newFileData = fileData;
return true;
}
void findStringDecryptBuffer() {
foreach (var type in module.Types) {
if (type.FullName == "<D234>" || type.FullName == "<ClassD234>") {
addTypeToBeRemoved(type, "Obfuscator string decrypter type");
foreach (var field in type.Fields) {
if (field.FullName == "<D234> <D234>::345" || field.FullName == "<ClassD234>/D234 <ClassD234>::345") {
decryptStringBuffer = field.InitialValue;
break;
}
}
break;
}
}
}
void findDelegateCreatorType() {
foreach (var type in module.Types) {
var methodName = "System.Void " + type.FullName + "::icgd(System.Int32)";
foreach (var method in type.Methods) {
if (method.FullName == methodName) {
proxyDelegateFinder.setDelegateCreatorMethod(method);
foundProxyDelegateMethod = true;
return;
}
}
}
public override IDeobfuscator moduleReloaded(ModuleDefinition module) {
var newOne = new Deobfuscator(options);
newOne.setModule(module);
newOne.cliSecureAttribute = DeobUtils.lookup(module, cliSecureAttribute, "Could not find CliSecure attribute");
newOne.cliSecureRtType = new CliSecureRtType(module, cliSecureRtType);
newOne.stringDecrypter = new StringDecrypter(module, stringDecrypter);
newOne.proxyDelegateFinder = new ProxyDelegateFinder(module, proxyDelegateFinder);
return newOne;
}
public override void deobfuscateBegin() {
base.deobfuscateBegin();
addAttributeToBeRemoved(cliSecureAttribute, "Obfuscator attribute");
addTypeToBeRemoved(stringDecrypter.StringDecrypterType, "Obfuscator string decrypter type");
findPossibleNamesToRemove(cliSecureRtType.LoadMethod);
resourceDecrypter = new ResourceDecrypter(module);
resourceDecrypter.find();
stackFrameHelper = new StackFrameHelper(module);
stackFrameHelper.find();
foreach (var type in module.Types) {
if (type.FullName == "InitializeDelegate" && DotNetUtils.derivesFromDelegate(type))
this.addTypeToBeRemoved(type, "Obfuscator type");
else if (findResourceDecrypter(type)) {
// Nothing
}
if (options.RemoveStackFrameHelper)
findStackFrameHelper(type);
}
proxyDelegateFinder.find();
if (decryptStringMethod != null)
staticStringDecrypter.add(decryptStringMethod, (method, args) => decryptString((string)args[0]));
staticStringDecrypter.add(stringDecrypter.StringDecrypterMethod, (method, args) => stringDecrypter.decrypt((string)args[0]));
addCctorInitCallToBeRemoved(initializeMethod);
addCctorInitCallToBeRemoved(postInitializeMethod);
addCctorInitCallToBeRemoved(cliSecureRtType.InitializeMethod);
addCctorInitCallToBeRemoved(cliSecureRtType.PostInitializeMethod);
if (options.FixResources)
addCctorInitCallToBeRemoved(rsrcRrrMethod);
}
bool findResourceDecrypter(TypeDefinition type) {
MethodDefinition rrrMethod = null;
MethodDefinition decryptMethod = null;
foreach (var method in type.Methods) {
if (method.Name == "rrr" && DotNetUtils.isMethod(method, "System.Void", "()"))
rrrMethod = method;
else if (DotNetUtils.isMethod(method, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)"))
decryptMethod = method;
}
if (rrrMethod == null || decryptMethod == null)
return false;
var methodCalls = DotNetUtils.getMethodCallCounts(rrrMethod);
if (methodCalls.count("System.Void System.ResolveEventHandler::.ctor(System.Object,System.IntPtr)") != 1)
return false;
rsrcRrrMethod = rrrMethod;
rsrcDecryptMethod = decryptMethod;
return true;
addCctorInitCallToBeRemoved(resourceDecrypter.RsrcRrrMethod);
}
void decryptResources() {
if (rsrcDecryptMethod == null)
var rsrc = resourceDecrypter.mergeResources();
if (rsrc == null)
return;
var resource = getResource(DotNetUtils.getCodeStrings(rsrcDecryptMethod)) as EmbeddedResource;
if (resource == null)
return;
DeobUtils.decryptAndAddResources(module, resource.Name, () => decryptResource(resource));
addResourceToBeRemoved(resource, "Encrypted resource");
if (rsrcDecryptMethod != null)
addTypeToBeRemoved(rsrcDecryptMethod.DeclaringType, "Obfuscator resource decrypter type");
}
byte[] decryptResource(EmbeddedResource resource) {
using (var rsrcStream = resource.GetResourceStream()) {
using (var reader = new BinaryReader(rsrcStream)) {
var key = reader.ReadString();
var data = reader.ReadBytes((int)(rsrcStream.Length - rsrcStream.Position));
var cryptoTransform = new DESCryptoServiceProvider {
Key = Encoding.ASCII.GetBytes(key),
IV = Encoding.ASCII.GetBytes(key),
}.CreateDecryptor();
var memStream = new MemoryStream(data);
using (var reader2 = new BinaryReader(new CryptoStream(memStream, cryptoTransform, CryptoStreamMode.Read))) {
return reader2.ReadBytes((int)memStream.Length);
}
}
}
}
void findStackFrameHelper(TypeDefinition type) {
if (!type.HasMethods)
return;
if (type.Methods.Count > 3)
return;
MethodDefinition errorMethod = null;
foreach (var method in type.Methods) {
if (method.IsRuntimeSpecialName && method.Name == ".ctor" && method.HasParameters == false)
continue; // .ctor is allowed
if (method.IsRuntimeSpecialName && method.Name == ".cctor" && method.HasParameters == false)
continue; // .cctor is allowed
if (method.IsStatic && method.CallingConvention == MethodCallingConvention.Default &&
method.ExplicitThis == false && method.HasThis == false &&
method.HasBody && method.IsManaged && method.IsIL && method.HasParameters &&
method.Parameters.Count == 2 && method.HasGenericParameters == false &&
!DotNetUtils.hasReturnValue(method) &&
MemberReferenceHelper.verifyType(method.Parameters[0].ParameterType, "mscorlib", "System.Exception") &&
MemberReferenceHelper.verifyType(method.Parameters[1].ParameterType, "mscorlib", "System.Object", "[]")) {
errorMethod = method;
}
else
return;
}
if (errorMethod != null) {
if (stackFrameHelperType != null)
throw new ApplicationException("Found another StackFrameHelper");
stackFrameHelperType = type;
exceptionLoggerRemover.add(errorMethod);
}
addResourceToBeRemoved(rsrc, "Encrypted resource");
addTypeToBeRemoved(resourceDecrypter.Type, "Obfuscator resource decrypter type");
}
public override void deobfuscateMethodEnd(Blocks blocks) {
@ -329,10 +205,12 @@ namespace de4dot.deobfuscators.CliSecure {
if (options.FixResources)
decryptResources();
removeProxyDelegates(proxyDelegateFinder);
if (exceptionLoggerRemover.NumRemovedExceptionLoggers > 0)
addTypeToBeRemoved(stackFrameHelperType, "StackFrameHelper type");
if (options.RemoveStackFrameHelper) {
if (stackFrameHelper.ExceptionLoggerRemover.NumRemovedExceptionLoggers > 0)
addTypeToBeRemoved(stackFrameHelper.Type, "StackFrameHelper type");
}
if (Operations.DecryptStrings != OpDecryptString.None)
addTypeToBeRemoved(cliSecureRtType, "Obfuscator type");
addTypeToBeRemoved(cliSecureRtType.Type, "Obfuscator type");
addResources("Obfuscator protection files");
addModuleReferences("Obfuscator protection files");
@ -341,22 +219,13 @@ namespace de4dot.deobfuscators.CliSecure {
public override IEnumerable<string> getStringDecrypterMethods() {
var list = new List<string>();
if (decryptStringMethod != null)
list.Add(decryptStringMethod.MetadataToken.ToInt32().ToString("X8"));
if (stringDecrypter.StringDecrypterMethod != null)
list.Add(stringDecrypter.StringDecrypterMethod.MetadataToken.ToInt32().ToString("X8"));
return list;
}
string decryptString(string es) {
if (decryptStringBuffer == null)
throw new ApplicationException("Trying to decrypt strings when decryptStringBuffer is null (could not find it!)");
StringBuilder sb = new StringBuilder(es.Length);
for (int i = 0; i < es.Length; i++)
sb.Append(Convert.ToChar((int)(es[i] ^ decryptStringBuffer[i % decryptStringBuffer.Length])));
return sb.ToString();
}
void removeStackFrameHelperCode(Blocks blocks) {
if (exceptionLoggerRemover.remove(blocks))
if (stackFrameHelper.ExceptionLoggerRemover.remove(blocks))
Log.v("Removed StackFrameHelper code");
}
}

View File

@ -0,0 +1,169 @@
/*
Copyright (C) 2011 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using Mono.MyStuff;
namespace de4dot.deobfuscators.CliSecure {
class CodeHeader {
public byte[] signature;
public byte[] decryptionKey;
public uint totalCodeSize;
public uint numMethods;
public uint methodDefTableOffset;
public uint methodDefElemSize;
}
struct MethodInfo {
public uint codeOffs, codeSize, flags, localVarSigTok;
public MethodInfo(uint codeOffs, uint codeSize, uint flags, uint localVarSigTok) {
this.codeOffs = codeOffs;
this.codeSize = codeSize;
this.flags = flags;
this.localVarSigTok = localVarSigTok;
}
public override string ToString() {
return string.Format("{0:X8} {1:X8} {2:X8} {3:X8}", codeOffs, codeSize, flags, localVarSigTok);
}
}
class MethodsDecrypter {
static byte[] SIGNATURE = new byte[16] { 0x08, 0x44, 0x65, 0xE1, 0x8C, 0x82, 0x13, 0x4C, 0x9C, 0x85, 0xB4, 0x17, 0xDA, 0x51, 0xAD, 0x25 };
PE.PeImage peImage;
CodeHeader codeHeader = new CodeHeader();
uint endOfMetadata;
public bool decrypt(PE.PeImage peImage, ref Dictionary<uint, DumpedMethod> dumpedMethods) {
this.peImage = peImage;
endOfMetadata = peImage.rvaToOffset(peImage.Cor20Header.metadataDirectory.virtualAddress + peImage.Cor20Header.metadataDirectory.size);
uint offset = endOfMetadata;
if (!readCodeHeader(offset))
return false;
var methodInfos = getMethodInfos(offset + 0x30 + codeHeader.totalCodeSize);
var metadataTables = peImage.Cor20Header.createMetadataTables();
var methodDefTable = metadataTables.getMetadataType(PE.MetadataIndex.iMethodDef);
offset = methodDefTable.fileOffset - methodDefTable.totalSize;
foreach (var methodInfo in methodInfos) {
offset += methodDefTable.totalSize;
if (methodInfo.flags == 0 || methodInfo.localVarSigTok == 0)
continue;
uint rva = peImage.offsetReadUInt32(offset);
peImage.writeUint16(rva, (ushort)methodInfo.flags);
peImage.writeUint32(rva + 8, methodInfo.localVarSigTok);
}
dumpedMethods = new Dictionary<uint, DumpedMethod>();
offset = methodDefTable.fileOffset;
for (int i = 0; i < methodInfos.Count; i++, offset += methodDefTable.totalSize) {
var methodInfo = methodInfos[i];
if (methodInfo.codeOffs == 0)
continue;
var dm = new DumpedMethod();
dm.token = 0x06000001 + (uint)i;
uint rva = peImage.offsetReadUInt32(offset);
dm.mdImplFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[1].offset);
dm.mdFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[2].offset);
dm.mdName = peImage.offsetRead(offset + (uint)methodDefTable.fields[3].offset, methodDefTable.fields[3].size);
dm.mdSignature = peImage.offsetRead(offset + (uint)methodDefTable.fields[4].offset, methodDefTable.fields[4].size);
dm.mdParamList = peImage.offsetRead(offset + (uint)methodDefTable.fields[5].offset, methodDefTable.fields[5].size);
dm.code = getDecryptedCode(methodInfo);
if ((peImage.readByte(rva) & 3) == 2) {
dm.mhFlags = 2;
dm.mhMaxStack = 8;
dm.mhCodeSize = (uint)dm.code.Length;
dm.mhLocalVarSigTok = 0;
}
else {
dm.mhFlags = peImage.readUInt16(rva);
dm.mhMaxStack = peImage.readUInt16(rva + 2);
dm.mhCodeSize = (uint)dm.code.Length;
dm.mhLocalVarSigTok = peImage.readUInt32(rva + 8);
}
dumpedMethods[dm.token] = dm;
}
return true;
}
byte[] getDecryptedCode(MethodInfo methodInfo) {
byte[] data = peImage.offsetReadBytes(endOfMetadata + methodInfo.codeOffs, (int)methodInfo.codeSize);
for (int i = 0; i < data.Length; i++) {
byte b = data[i];
b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - 0x30 + i) % 16];
b ^= codeHeader.decryptionKey[(methodInfo.codeOffs - 0x30 + i + 7) % 16];
data[i] = b;
}
int codeOffset, codeSize;
if ((data[0] & 3) == 2) {
codeOffset = 1;
codeSize = data[0] >> 2;
}
else {
codeOffset = 4 * (data[1] >> 4);
codeSize = BitConverter.ToInt32(data, 4);
}
var code = new byte[codeSize];
Array.Copy(data, codeOffset, code, 0, codeSize);
return code;
}
bool readCodeHeader(uint offset) {
codeHeader.signature = peImage.offsetReadBytes(offset, 16);
if (!Utils.compare(SIGNATURE, codeHeader.signature))
return false;
codeHeader.decryptionKey = peImage.offsetReadBytes(offset + 0x10, 16);
codeHeader.totalCodeSize = peImage.offsetReadUInt32(offset + 0x20);
codeHeader.numMethods = peImage.offsetReadUInt32(offset + 0x24);
codeHeader.methodDefTableOffset = peImage.offsetReadUInt32(offset + 0x28);
codeHeader.methodDefElemSize = peImage.offsetReadUInt32(offset + 0x2C);
if (codeHeader.totalCodeSize > 0x10000000)
throw new ApplicationException("Invalid total code size");
if (codeHeader.numMethods > 512*1024)
throw new ApplicationException("Invalid num methods");
return true;
}
List<MethodInfo> getMethodInfos(uint offset) {
var methodInfos = new List<MethodInfo>((int)codeHeader.numMethods);
for (int i = 0; i < (int)codeHeader.numMethods; i++, offset += 16) {
uint codeOffs = peImage.offsetReadUInt32(offset);
uint codeSize = peImage.offsetReadUInt32(offset + 4);
uint flags = peImage.offsetReadUInt32(offset + 8);
uint localVarSigTok = peImage.offsetReadUInt32(offset + 12);
methodInfos.Add(new MethodInfo(codeOffs, codeSize, flags, localVarSigTok));
}
return methodInfos;
}
}
}

View File

@ -29,7 +29,28 @@ namespace de4dot.deobfuscators.CliSecure {
public ProxyDelegateFinder(ModuleDefinition module)
: base(module) {
this.memberReferences = new List<MemberReference>(module.GetMemberReferences());
}
public ProxyDelegateFinder(ModuleDefinition module, ProxyDelegateFinder oldOne)
: base(module) {
foreach (var method in oldOne.delegateCreatorMethods)
setDelegateCreatorMethod(lookup(method, "Could not find delegate creator method"));
}
T lookup<T>(T def, string errorMessage) where T : MemberReference {
return DeobUtils.lookup(module, def, errorMessage);
}
public void findDelegateCreator() {
foreach (var type in module.Types) {
var methodName = "System.Void " + type.FullName + "::icgd(System.Int32)";
foreach (var method in type.Methods) {
if (method.FullName == methodName) {
setDelegateCreatorMethod(method);
return;
}
}
}
}
protected override object checkCctor(TypeDefinition type, MethodDefinition cctor) {
@ -53,6 +74,9 @@ namespace de4dot.deobfuscators.CliSecure {
}
protected override void getCallInfo(object context, FieldDefinition field, out MethodReference calledMethod, out OpCode callOpcode) {
if (memberReferences == null)
memberReferences = new List<MemberReference>(module.GetMemberReferences());
var name = field.Name;
callOpcode = OpCodes.Call;
if (name.EndsWith("%", StringComparison.Ordinal)) {

View File

@ -0,0 +1,101 @@
/*
Copyright (C) 2011 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Mono.Cecil;
using de4dot.blocks;
namespace de4dot.deobfuscators.CliSecure {
class ResourceDecrypter {
ModuleDefinition module;
TypeDefinition rsrcType;
MethodDefinition rsrcRrrMethod;
MethodDefinition rsrcDecryptMethod;
public TypeDefinition Type {
get { return rsrcType; }
}
public MethodDefinition RsrcRrrMethod {
get { return rsrcRrrMethod; }
}
public ResourceDecrypter(ModuleDefinition module) {
this.module = module;
}
public void find() {
findResourceType();
}
void findResourceType() {
foreach (var type in module.Types) {
MethodDefinition rrrMethod = null;
MethodDefinition decryptMethod = null;
foreach (var method in type.Methods) {
if (method.Name == "rrr" && DotNetUtils.isMethod(method, "System.Void", "()"))
rrrMethod = method;
else if (DotNetUtils.isMethod(method, "System.Reflection.Assembly", "(System.Object,System.ResolveEventArgs)"))
decryptMethod = method;
}
if (rrrMethod == null || decryptMethod == null)
continue;
var methodCalls = DotNetUtils.getMethodCallCounts(rrrMethod);
if (methodCalls.count("System.Void System.ResolveEventHandler::.ctor(System.Object,System.IntPtr)") != 1)
continue;
rsrcType = type;
rsrcRrrMethod = rrrMethod;
rsrcDecryptMethod = decryptMethod;
return;
}
}
public EmbeddedResource mergeResources() {
if (rsrcDecryptMethod == null)
return null;
var resource = DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(rsrcDecryptMethod)) as EmbeddedResource;
if (resource == null)
return null;
DeobUtils.decryptAndAddResources(module, resource.Name, () => decryptResource(resource));
return resource;
}
byte[] decryptResource(EmbeddedResource resource) {
using (var rsrcStream = resource.GetResourceStream()) {
using (var reader = new BinaryReader(rsrcStream)) {
var key = reader.ReadString();
var data = reader.ReadBytes((int)(rsrcStream.Length - rsrcStream.Position));
var cryptoTransform = new DESCryptoServiceProvider {
Key = Encoding.ASCII.GetBytes(key),
IV = Encoding.ASCII.GetBytes(key),
}.CreateDecryptor();
var memStream = new MemoryStream(data);
using (var reader2 = new BinaryReader(new CryptoStream(memStream, cryptoTransform, CryptoStreamMode.Read))) {
return reader2.ReadBytes((int)memStream.Length);
}
}
}
}
}
}

View File

@ -0,0 +1,75 @@
/*
Copyright (C) 2011 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using Mono.Cecil;
using de4dot.blocks;
namespace de4dot.deobfuscators.CliSecure {
class StackFrameHelper {
ModuleDefinition module;
TypeDefinition stackFrameHelperType;
ExceptionLoggerRemover exceptionLoggerRemover = new ExceptionLoggerRemover();
public TypeDefinition Type {
get { return stackFrameHelperType; }
}
public ExceptionLoggerRemover ExceptionLoggerRemover {
get { return exceptionLoggerRemover; }
}
public StackFrameHelper(ModuleDefinition module) {
this.module = module;
}
public void find() {
foreach (var type in module.Types) {
if (!type.HasMethods)
continue;
if (type.Methods.Count > 3)
continue;
MethodDefinition errorMethod = null;
foreach (var method in type.Methods) {
if (method.IsRuntimeSpecialName && method.Name == ".ctor" && !method.HasParameters)
continue; // .ctor is allowed
if (method.IsRuntimeSpecialName && method.Name == ".cctor" && !method.HasParameters)
continue; // .cctor is allowed
if (method.IsStatic && method.CallingConvention == MethodCallingConvention.Default &&
method.ExplicitThis == false && method.HasThis == false &&
method.HasBody && method.IsManaged && method.IsIL && method.HasParameters &&
method.Parameters.Count == 2 && !method.HasGenericParameters &&
!DotNetUtils.hasReturnValue(method) &&
method.Parameters[0].ParameterType.FullName == "System.Exception" &&
method.Parameters[1].ParameterType.FullName == "System.Object[]") {
errorMethod = method;
}
else
break;
}
if (errorMethod != null) {
stackFrameHelperType = type;
exceptionLoggerRemover.add(errorMethod);
return;
}
}
}
}
}

View File

@ -0,0 +1,83 @@
/*
Copyright (C) 2011 de4dot@gmail.com
This file is part of de4dot.
de4dot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
de4dot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Text;
using Mono.Cecil;
namespace de4dot.deobfuscators.CliSecure {
class StringDecrypter {
ModuleDefinition module;
TypeDefinition stringDecrypterType;
MethodDefinition stringDecrypterMethod;
byte[] stringDecrypterKey;
public bool Detected {
get { return stringDecrypterKey != null; }
}
public TypeDefinition StringDecrypterType {
get { return stringDecrypterType; }
}
public MethodDefinition StringDecrypterMethod {
get { return stringDecrypterMethod; }
}
public StringDecrypter(ModuleDefinition module, MethodDefinition stringDecrypterMethod) {
this.module = module;
this.stringDecrypterMethod = stringDecrypterMethod;
}
public StringDecrypter(ModuleDefinition module, StringDecrypter oldOne) {
this.module = module;
stringDecrypterType = lookup(oldOne.stringDecrypterType, "Could not find stringDecrypterType");
stringDecrypterMethod = lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod");
stringDecrypterKey = oldOne.stringDecrypterKey;
}
T lookup<T>(T def, string errorMessage) where T : MemberReference {
return DeobUtils.lookup(module, def, errorMessage);
}
public void find() {
foreach (var type in module.Types) {
if (type.FullName == "<D234>" || type.FullName == "<ClassD234>") {
stringDecrypterType = type;
foreach (var field in type.Fields) {
if (field.FullName == "<D234> <D234>::345" || field.FullName == "<ClassD234>/D234 <ClassD234>::345") {
stringDecrypterKey = field.InitialValue;
break;
}
}
break;
}
}
}
public string decrypt(string es) {
if (stringDecrypterKey == null)
throw new ApplicationException("Trying to decrypt strings when stringDecrypterKey is null (could not find it!)");
StringBuilder sb = new StringBuilder(es.Length);
for (int i = 0; i < es.Length; i++)
sb.Append(Convert.ToChar((int)(es[i] ^ stringDecrypterKey[i % stringDecrypterKey.Length])));
return sb.ToString();
}
}
}