Add static methods decrypter and refactor into multiple classes
This commit is contained in:
parent
a0509d2735
commit
f424e8eabf
|
@ -56,8 +56,13 @@
|
||||||
<Compile Include="AssemblyResolver.cs" />
|
<Compile Include="AssemblyResolver.cs" />
|
||||||
<Compile Include="CommandLineParser.cs" />
|
<Compile Include="CommandLineParser.cs" />
|
||||||
<Compile Include="deobfuscators\ArrayFinder.cs" />
|
<Compile Include="deobfuscators\ArrayFinder.cs" />
|
||||||
|
<Compile Include="deobfuscators\CliSecure\CliSecureRtType.cs" />
|
||||||
<Compile Include="deobfuscators\CliSecure\Deobfuscator.cs" />
|
<Compile Include="deobfuscators\CliSecure\Deobfuscator.cs" />
|
||||||
|
<Compile Include="deobfuscators\CliSecure\MethodsDecrypter.cs" />
|
||||||
<Compile Include="deobfuscators\CliSecure\ProxyDelegateFinder.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\AntiDebugger.cs" />
|
||||||
<Compile Include="deobfuscators\CryptoObfuscator\AssemblyResolver.cs" />
|
<Compile Include="deobfuscators\CryptoObfuscator\AssemblyResolver.cs" />
|
||||||
<Compile Include="deobfuscators\CryptoObfuscator\Deobfuscator.cs" />
|
<Compile Include="deobfuscators\CryptoObfuscator\Deobfuscator.cs" />
|
||||||
|
|
118
de4dot.code/deobfuscators/CliSecure/CliSecureRtType.cs
Normal file
118
de4dot.code/deobfuscators/CliSecure/CliSecureRtType.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,23 +18,24 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Security.Cryptography;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using Mono.Cecil;
|
using Mono.Cecil;
|
||||||
using Mono.Cecil.Cil;
|
using Mono.Cecil.Cil;
|
||||||
|
using Mono.MyStuff;
|
||||||
using de4dot.blocks;
|
using de4dot.blocks;
|
||||||
|
|
||||||
namespace de4dot.deobfuscators.CliSecure {
|
namespace de4dot.deobfuscators.CliSecure {
|
||||||
class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
||||||
public const string THE_NAME = "CliSecure";
|
public const string THE_NAME = "CliSecure";
|
||||||
const string DEFAULT_REGEX = @"[a-zA-Z_0-9>}$]$";
|
const string DEFAULT_REGEX = @"[a-zA-Z_0-9>}$]$";
|
||||||
|
BoolOption decryptMethods;
|
||||||
BoolOption fixResources;
|
BoolOption fixResources;
|
||||||
BoolOption removeStackFrameHelper;
|
BoolOption removeStackFrameHelper;
|
||||||
|
|
||||||
public DeobfuscatorInfo()
|
public DeobfuscatorInfo()
|
||||||
: base(DEFAULT_REGEX) {
|
: base(DEFAULT_REGEX) {
|
||||||
|
decryptMethods = new BoolOption(null, makeArgName("methods"), "Decrypt methods", true);
|
||||||
fixResources = new BoolOption(null, makeArgName("rsrc"), "Decrypt resources", true);
|
fixResources = new BoolOption(null, makeArgName("rsrc"), "Decrypt resources", true);
|
||||||
removeStackFrameHelper = new BoolOption(null, makeArgName("stack"), "Remove all StackFrameHelper code", true);
|
removeStackFrameHelper = new BoolOption(null, makeArgName("stack"), "Remove all StackFrameHelper code", true);
|
||||||
}
|
}
|
||||||
|
@ -50,6 +51,7 @@ namespace de4dot.deobfuscators.CliSecure {
|
||||||
public override IDeobfuscator createDeobfuscator() {
|
public override IDeobfuscator createDeobfuscator() {
|
||||||
return new Deobfuscator(new Deobfuscator.Options {
|
return new Deobfuscator(new Deobfuscator.Options {
|
||||||
ValidNameRegex = validNameRegex.get(),
|
ValidNameRegex = validNameRegex.get(),
|
||||||
|
DecryptMethods = decryptMethods.get(),
|
||||||
FixResources = fixResources.get(),
|
FixResources = fixResources.get(),
|
||||||
RemoveStackFrameHelper = removeStackFrameHelper.get(),
|
RemoveStackFrameHelper = removeStackFrameHelper.get(),
|
||||||
});
|
});
|
||||||
|
@ -57,6 +59,7 @@ namespace de4dot.deobfuscators.CliSecure {
|
||||||
|
|
||||||
protected override IEnumerable<Option> getOptionsInternal() {
|
protected override IEnumerable<Option> getOptionsInternal() {
|
||||||
return new List<Option>() {
|
return new List<Option>() {
|
||||||
|
decryptMethods,
|
||||||
fixResources,
|
fixResources,
|
||||||
removeStackFrameHelper,
|
removeStackFrameHelper,
|
||||||
};
|
};
|
||||||
|
@ -65,25 +68,17 @@ namespace de4dot.deobfuscators.CliSecure {
|
||||||
|
|
||||||
class Deobfuscator : DeobfuscatorBase {
|
class Deobfuscator : DeobfuscatorBase {
|
||||||
Options options;
|
Options options;
|
||||||
bool foundCliSecureAttribute = false;
|
|
||||||
bool foundProxyDelegateMethod = false;
|
|
||||||
|
|
||||||
MethodDefinition decryptStringMethod;
|
|
||||||
byte[] decryptStringBuffer;
|
|
||||||
|
|
||||||
|
TypeDefinition cliSecureAttribute;
|
||||||
ProxyDelegateFinder proxyDelegateFinder;
|
ProxyDelegateFinder proxyDelegateFinder;
|
||||||
|
CliSecureRtType cliSecureRtType;
|
||||||
|
StringDecrypter stringDecrypter;
|
||||||
|
|
||||||
TypeDefinition cliSecureRtType;
|
ResourceDecrypter resourceDecrypter;
|
||||||
MethodDefinition postInitializeMethod;
|
StackFrameHelper stackFrameHelper;
|
||||||
MethodDefinition initializeMethod;
|
|
||||||
TypeDefinition stackFrameHelperType;
|
|
||||||
|
|
||||||
ExceptionLoggerRemover exceptionLoggerRemover = new ExceptionLoggerRemover();
|
|
||||||
|
|
||||||
MethodDefinition rsrcRrrMethod;
|
|
||||||
MethodDefinition rsrcDecryptMethod;
|
|
||||||
|
|
||||||
internal class Options : OptionsBase {
|
internal class Options : OptionsBase {
|
||||||
|
public bool DecryptMethods { get; set; }
|
||||||
public bool FixResources { get; set; }
|
public bool FixResources { get; set; }
|
||||||
public bool RemoveStackFrameHelper { get; set; }
|
public bool RemoveStackFrameHelper { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -108,215 +103,96 @@ namespace de4dot.deobfuscators.CliSecure {
|
||||||
protected override int detectInternal() {
|
protected override int detectInternal() {
|
||||||
int val = 0;
|
int val = 0;
|
||||||
|
|
||||||
if (cliSecureRtType != null || foundCliSecureAttribute)
|
if (cliSecureRtType.Detected || cliSecureAttribute != null)
|
||||||
val += 100;
|
val += 100;
|
||||||
if (decryptStringBuffer != null)
|
if (stringDecrypter.Detected)
|
||||||
val += 10;
|
val += 10;
|
||||||
if (foundProxyDelegateMethod)
|
if (proxyDelegateFinder.Detected)
|
||||||
val += 10;
|
val += 10;
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void scanForObfuscator() {
|
protected override void scanForObfuscator() {
|
||||||
proxyDelegateFinder = new ProxyDelegateFinder(module);
|
|
||||||
findCliSecureAttribute();
|
findCliSecureAttribute();
|
||||||
findCliSecureRtType();
|
cliSecureRtType = new CliSecureRtType(module);
|
||||||
findStringDecryptBuffer();
|
cliSecureRtType.find();
|
||||||
findDelegateCreatorType();
|
stringDecrypter = new StringDecrypter(module, cliSecureRtType.StringDecrypterMethod);
|
||||||
|
stringDecrypter.find();
|
||||||
|
proxyDelegateFinder = new ProxyDelegateFinder(module);
|
||||||
|
proxyDelegateFinder.findDelegateCreator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void findCliSecureAttribute() {
|
void findCliSecureAttribute() {
|
||||||
foreach (var type in module.Types) {
|
foreach (var type in module.Types) {
|
||||||
if (type.FullName == "SecureTeam.Attributes.ObfuscatedByCliSecureAttribute") {
|
if (type.FullName == "SecureTeam.Attributes.ObfuscatedByCliSecureAttribute") {
|
||||||
this.addAttributeToBeRemoved(type, "Obfuscator attribute");
|
cliSecureAttribute = type;
|
||||||
foundCliSecureAttribute = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void findCliSecureRtType() {
|
public override bool getDecryptedModule(ref byte[] newFileData, ref Dictionary<uint, DumpedMethod> dumpedMethods) {
|
||||||
if (cliSecureRtType != null)
|
if (!options.DecryptMethods)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
foreach (var type in module.Types) {
|
byte[] fileData;
|
||||||
if (type.Namespace != "")
|
using (var fileStream = new FileStream(module.FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read)) {
|
||||||
continue;
|
fileData = new byte[(int)fileStream.Length];
|
||||||
var typeName = type.FullName;
|
fileStream.Read(fileData, 0, fileData.Length);
|
||||||
|
}
|
||||||
|
var peImage = new PE.PeImage(fileData);
|
||||||
|
|
||||||
MethodDefinition cs = null;
|
if (!new MethodsDecrypter().decrypt(peImage, ref dumpedMethods))
|
||||||
MethodDefinition initialize = null;
|
return false;
|
||||||
MethodDefinition postInitialize = null;
|
|
||||||
MethodDefinition load = null;
|
|
||||||
|
|
||||||
int methods = 0;
|
newFileData = fileData;
|
||||||
foreach (var method in type.Methods) {
|
return true;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void findStringDecryptBuffer() {
|
public override IDeobfuscator moduleReloaded(ModuleDefinition module) {
|
||||||
foreach (var type in module.Types) {
|
var newOne = new Deobfuscator(options);
|
||||||
if (type.FullName == "<D234>" || type.FullName == "<ClassD234>") {
|
newOne.setModule(module);
|
||||||
addTypeToBeRemoved(type, "Obfuscator string decrypter type");
|
newOne.cliSecureAttribute = DeobUtils.lookup(module, cliSecureAttribute, "Could not find CliSecure attribute");
|
||||||
foreach (var field in type.Fields) {
|
newOne.cliSecureRtType = new CliSecureRtType(module, cliSecureRtType);
|
||||||
if (field.FullName == "<D234> <D234>::345" || field.FullName == "<ClassD234>/D234 <ClassD234>::345") {
|
newOne.stringDecrypter = new StringDecrypter(module, stringDecrypter);
|
||||||
decryptStringBuffer = field.InitialValue;
|
newOne.proxyDelegateFinder = new ProxyDelegateFinder(module, proxyDelegateFinder);
|
||||||
break;
|
return newOne;
|
||||||
}
|
|
||||||
}
|
|
||||||
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 void deobfuscateBegin() {
|
public override void deobfuscateBegin() {
|
||||||
base.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) {
|
foreach (var type in module.Types) {
|
||||||
if (type.FullName == "InitializeDelegate" && DotNetUtils.derivesFromDelegate(type))
|
if (type.FullName == "InitializeDelegate" && DotNetUtils.derivesFromDelegate(type))
|
||||||
this.addTypeToBeRemoved(type, "Obfuscator type");
|
this.addTypeToBeRemoved(type, "Obfuscator type");
|
||||||
else if (findResourceDecrypter(type)) {
|
|
||||||
// Nothing
|
|
||||||
}
|
|
||||||
if (options.RemoveStackFrameHelper)
|
|
||||||
findStackFrameHelper(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyDelegateFinder.find();
|
proxyDelegateFinder.find();
|
||||||
|
|
||||||
if (decryptStringMethod != null)
|
staticStringDecrypter.add(stringDecrypter.StringDecrypterMethod, (method, args) => stringDecrypter.decrypt((string)args[0]));
|
||||||
staticStringDecrypter.add(decryptStringMethod, (method, args) => decryptString((string)args[0]));
|
|
||||||
|
|
||||||
addCctorInitCallToBeRemoved(initializeMethod);
|
addCctorInitCallToBeRemoved(cliSecureRtType.InitializeMethod);
|
||||||
addCctorInitCallToBeRemoved(postInitializeMethod);
|
addCctorInitCallToBeRemoved(cliSecureRtType.PostInitializeMethod);
|
||||||
if (options.FixResources)
|
if (options.FixResources)
|
||||||
addCctorInitCallToBeRemoved(rsrcRrrMethod);
|
addCctorInitCallToBeRemoved(resourceDecrypter.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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void decryptResources() {
|
void decryptResources() {
|
||||||
if (rsrcDecryptMethod == null)
|
var rsrc = resourceDecrypter.mergeResources();
|
||||||
|
if (rsrc == null)
|
||||||
return;
|
return;
|
||||||
var resource = getResource(DotNetUtils.getCodeStrings(rsrcDecryptMethod)) as EmbeddedResource;
|
addResourceToBeRemoved(rsrc, "Encrypted resource");
|
||||||
if (resource == null)
|
addTypeToBeRemoved(resourceDecrypter.Type, "Obfuscator resource decrypter type");
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void deobfuscateMethodEnd(Blocks blocks) {
|
public override void deobfuscateMethodEnd(Blocks blocks) {
|
||||||
|
@ -329,10 +205,12 @@ namespace de4dot.deobfuscators.CliSecure {
|
||||||
if (options.FixResources)
|
if (options.FixResources)
|
||||||
decryptResources();
|
decryptResources();
|
||||||
removeProxyDelegates(proxyDelegateFinder);
|
removeProxyDelegates(proxyDelegateFinder);
|
||||||
if (exceptionLoggerRemover.NumRemovedExceptionLoggers > 0)
|
if (options.RemoveStackFrameHelper) {
|
||||||
addTypeToBeRemoved(stackFrameHelperType, "StackFrameHelper type");
|
if (stackFrameHelper.ExceptionLoggerRemover.NumRemovedExceptionLoggers > 0)
|
||||||
|
addTypeToBeRemoved(stackFrameHelper.Type, "StackFrameHelper type");
|
||||||
|
}
|
||||||
if (Operations.DecryptStrings != OpDecryptString.None)
|
if (Operations.DecryptStrings != OpDecryptString.None)
|
||||||
addTypeToBeRemoved(cliSecureRtType, "Obfuscator type");
|
addTypeToBeRemoved(cliSecureRtType.Type, "Obfuscator type");
|
||||||
addResources("Obfuscator protection files");
|
addResources("Obfuscator protection files");
|
||||||
addModuleReferences("Obfuscator protection files");
|
addModuleReferences("Obfuscator protection files");
|
||||||
|
|
||||||
|
@ -341,22 +219,13 @@ namespace de4dot.deobfuscators.CliSecure {
|
||||||
|
|
||||||
public override IEnumerable<string> getStringDecrypterMethods() {
|
public override IEnumerable<string> getStringDecrypterMethods() {
|
||||||
var list = new List<string>();
|
var list = new List<string>();
|
||||||
if (decryptStringMethod != null)
|
if (stringDecrypter.StringDecrypterMethod != null)
|
||||||
list.Add(decryptStringMethod.MetadataToken.ToInt32().ToString("X8"));
|
list.Add(stringDecrypter.StringDecrypterMethod.MetadataToken.ToInt32().ToString("X8"));
|
||||||
return list;
|
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) {
|
void removeStackFrameHelperCode(Blocks blocks) {
|
||||||
if (exceptionLoggerRemover.remove(blocks))
|
if (stackFrameHelper.ExceptionLoggerRemover.remove(blocks))
|
||||||
Log.v("Removed StackFrameHelper code");
|
Log.v("Removed StackFrameHelper code");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
169
de4dot.code/deobfuscators/CliSecure/MethodsDecrypter.cs
Normal file
169
de4dot.code/deobfuscators/CliSecure/MethodsDecrypter.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,28 @@ namespace de4dot.deobfuscators.CliSecure {
|
||||||
|
|
||||||
public ProxyDelegateFinder(ModuleDefinition module)
|
public ProxyDelegateFinder(ModuleDefinition module)
|
||||||
: base(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) {
|
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) {
|
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;
|
var name = field.Name;
|
||||||
callOpcode = OpCodes.Call;
|
callOpcode = OpCodes.Call;
|
||||||
if (name.EndsWith("%", StringComparison.Ordinal)) {
|
if (name.EndsWith("%", StringComparison.Ordinal)) {
|
||||||
|
|
101
de4dot.code/deobfuscators/CliSecure/ResourceDecrypter.cs
Normal file
101
de4dot.code/deobfuscators/CliSecure/ResourceDecrypter.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
75
de4dot.code/deobfuscators/CliSecure/StackFrameHelper.cs
Normal file
75
de4dot.code/deobfuscators/CliSecure/StackFrameHelper.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
83
de4dot.code/deobfuscators/CliSecure/StringDecrypter.cs
Normal file
83
de4dot.code/deobfuscators/CliSecure/StringDecrypter.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user