Decrypt embedded assemblies
This commit is contained in:
parent
3a96ae391a
commit
adaf41c769
|
@ -107,6 +107,7 @@
|
|||
<Compile Include="deobfuscators\CodeVeil\Deobfuscator.cs" />
|
||||
<Compile Include="deobfuscators\CodeVeil\ProxyDelegateFinder.cs" />
|
||||
<Compile Include="deobfuscators\CodeVeil\TamperDetection.cs" />
|
||||
<Compile Include="deobfuscators\CodeWall\AssemblyDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\CodeWall\Deobfuscator.cs" />
|
||||
<Compile Include="deobfuscators\CodeWall\MethodsDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\CodeWall\randomc\CRandomMersenne.cs" />
|
||||
|
|
206
de4dot.code/deobfuscators/CodeWall/AssemblyDecrypter.cs
Normal file
206
de4dot.code/deobfuscators/CodeWall/AssemblyDecrypter.cs
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
Copyright (C) 2011-2012 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 System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using de4dot.blocks;
|
||||
using de4dot.code.resources;
|
||||
|
||||
namespace de4dot.code.deobfuscators.CodeWall {
|
||||
class AssemblyDecrypter {
|
||||
ModuleDefinition module;
|
||||
ISimpleDeobfuscator simpleDeobfuscator;
|
||||
IDeobfuscator deob;
|
||||
List<AssemblyInfo> assemblyInfos = new List<AssemblyInfo>();
|
||||
string entryPointAssemblyKey;
|
||||
string resourcePassword;
|
||||
string resourceSalt;
|
||||
EmbeddedResource assemblyResource;
|
||||
|
||||
public class AssemblyInfo {
|
||||
public readonly byte[] data;
|
||||
public readonly string extension;
|
||||
public readonly string assemblyFullName;
|
||||
public readonly string assemblySimpleName;
|
||||
public readonly bool isEntryPointAssembly;
|
||||
|
||||
public AssemblyInfo(byte[] data, string extension, string assemblyFullName, string assemblySimpleName, bool isEntryPointAssembly) {
|
||||
this.data = data;
|
||||
this.extension = extension;
|
||||
this.assemblyFullName = assemblyFullName;
|
||||
this.assemblySimpleName = assemblySimpleName;
|
||||
this.isEntryPointAssembly = isEntryPointAssembly;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return assemblyFullName;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<AssemblyInfo> AssemblyInfos {
|
||||
get { return assemblyInfos; }
|
||||
}
|
||||
|
||||
public AssemblyDecrypter(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator, IDeobfuscator deob) {
|
||||
this.module = module;
|
||||
this.simpleDeobfuscator = simpleDeobfuscator;
|
||||
this.deob = deob;
|
||||
}
|
||||
|
||||
static readonly string[] requiredLocals = new string[] {
|
||||
"System.AppDomain",
|
||||
"System.DateTime",
|
||||
};
|
||||
public void find() {
|
||||
var method = module.EntryPoint;
|
||||
if (!checkEntryPoint(method))
|
||||
return;
|
||||
|
||||
MethodDefinition decryptAssemblyMethod;
|
||||
var mainKey = getMainResourceKey(method, out decryptAssemblyMethod);
|
||||
if (mainKey == null)
|
||||
return;
|
||||
|
||||
deobfuscateAll(decryptAssemblyMethod);
|
||||
var resource = getResource(decryptAssemblyMethod);
|
||||
if (resource == null)
|
||||
return;
|
||||
string password, salt;
|
||||
if (!getPassword(decryptAssemblyMethod, out password, out salt))
|
||||
return;
|
||||
|
||||
entryPointAssemblyKey = mainKey;
|
||||
resourcePassword = password;
|
||||
resourceSalt = salt;
|
||||
assemblyResource = resource;
|
||||
decryptAllAssemblies();
|
||||
}
|
||||
|
||||
bool checkEntryPoint(MethodDefinition method) {
|
||||
if (method == null)
|
||||
return false;
|
||||
if (!new LocalTypes(method).all(requiredLocals))
|
||||
return false;
|
||||
var handlers = DeobUtils.getAllResolveHandlers(method);
|
||||
if (handlers.Count != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void deobfuscateAll(MethodDefinition method) {
|
||||
simpleDeobfuscator.deobfuscate(method);
|
||||
simpleDeobfuscator.decryptStrings(method, deob);
|
||||
}
|
||||
|
||||
string getMainResourceKey(MethodDefinition method, out MethodDefinition decryptAssemblyMethod) {
|
||||
foreach (var calledMethod in DotNetUtils.getCalledMethods(module, method)) {
|
||||
if (!calledMethod.IsStatic || calledMethod.Body == null)
|
||||
continue;
|
||||
if (!DotNetUtils.isMethod(calledMethod, "System.Void", "(System.String[])"))
|
||||
continue;
|
||||
|
||||
deobfuscateAll(calledMethod);
|
||||
string keyInfo = getMainResourceKeyInfo(calledMethod, out decryptAssemblyMethod);
|
||||
if (keyInfo == null)
|
||||
continue;
|
||||
return BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(new ASCIIEncoding().GetBytes(keyInfo))).Replace("-", "");
|
||||
}
|
||||
|
||||
decryptAssemblyMethod = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
string getMainResourceKeyInfo(MethodDefinition method, out MethodDefinition decryptAssemblyMethod) {
|
||||
var instrs = method.Body.Instructions;
|
||||
for (int i = 0; i < instrs.Count - 1; i++) {
|
||||
var ldstr = instrs[i];
|
||||
if (ldstr.OpCode.Code != Code.Ldstr)
|
||||
continue;
|
||||
var call = instrs[i + 1];
|
||||
if (call.OpCode.Code != Code.Call)
|
||||
continue;
|
||||
var calledMethod = call.Operand as MethodDefinition;
|
||||
if (calledMethod == null)
|
||||
continue;
|
||||
|
||||
decryptAssemblyMethod = calledMethod;
|
||||
return (string)ldstr.Operand;
|
||||
}
|
||||
decryptAssemblyMethod = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
EmbeddedResource getResource(MethodDefinition method) {
|
||||
foreach (var s in DotNetUtils.getCodeStrings(method)) {
|
||||
var resource = DotNetUtils.getResource(module, s + ".resources") as EmbeddedResource;
|
||||
if (resource != null)
|
||||
return resource;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool getPassword(MethodDefinition method, out string password, out string salt) {
|
||||
var instrs = method.Body.Instructions;
|
||||
for (int i = 0; i < instrs.Count - 1; i++) {
|
||||
var ldstr1 = instrs[i];
|
||||
if (ldstr1.OpCode.Code != Code.Ldstr)
|
||||
continue;
|
||||
var ldstr2 = instrs[i + 1];
|
||||
if (ldstr2.OpCode.Code != Code.Ldstr)
|
||||
continue;
|
||||
|
||||
password = (string)ldstr1.Operand;
|
||||
salt = (string)ldstr2.Operand;
|
||||
if (password == null || salt == null)
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
password = null;
|
||||
salt = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
void decryptAllAssemblies() {
|
||||
if (assemblyResource == null)
|
||||
return;
|
||||
var resourceSet = ResourceReader.read(module, assemblyResource.GetResourceStream());
|
||||
foreach (var resourceElement in resourceSet.ResourceElements) {
|
||||
if (resourceElement.ResourceData.Code != ResourceTypeCode.ByteArray)
|
||||
throw new ApplicationException("Invalid resource");
|
||||
var resourceData = (BuiltInResourceData)resourceElement.ResourceData;
|
||||
var assemblyData = decrypt((byte[])resourceData.Data);
|
||||
var theModule = ModuleDefinition.ReadModule(new MemoryStream(assemblyData));
|
||||
bool isMain = resourceElement.Name == entryPointAssemblyKey;
|
||||
assemblyInfos.Add(new AssemblyInfo(assemblyData, DeobUtils.getExtension(theModule.Kind), theModule.Assembly.FullName, theModule.Assembly.Name.Name, isMain));
|
||||
}
|
||||
}
|
||||
|
||||
byte[] decrypt(byte[] encrypted) {
|
||||
var keyGenerator = new PasswordDeriveBytes(resourcePassword, Encoding.ASCII.GetBytes(resourceSalt));
|
||||
return DeobUtils.inflate(DeobUtils.aesDecrypt(encrypted, keyGenerator.GetBytes(32), keyGenerator.GetBytes(16)), false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,9 +29,11 @@ namespace de4dot.code.deobfuscators.CodeWall {
|
|||
public const string THE_NAME = "CodeWall";
|
||||
public const string THE_TYPE = "cw";
|
||||
const string DEFAULT_REGEX = @"!^[_<>{}$.`-]$&" + DeobfuscatorBase.DEFAULT_VALID_NAME_REGEX;
|
||||
BoolOption dumpEmbeddedAssemblies;
|
||||
|
||||
public DeobfuscatorInfo()
|
||||
: base(DEFAULT_REGEX) {
|
||||
dumpEmbeddedAssemblies = new BoolOption(null, makeArgName("embedded"), "Dump embedded assemblies", true);
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
|
@ -45,11 +47,13 @@ namespace de4dot.code.deobfuscators.CodeWall {
|
|||
public override IDeobfuscator createDeobfuscator() {
|
||||
return new Deobfuscator(new Deobfuscator.Options {
|
||||
ValidNameRegex = validNameRegex.get(),
|
||||
DumpEmbeddedAssemblies = dumpEmbeddedAssemblies.get(),
|
||||
});
|
||||
}
|
||||
|
||||
protected override IEnumerable<Option> getOptionsInternal() {
|
||||
return new List<Option>() {
|
||||
dumpEmbeddedAssemblies,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +64,7 @@ namespace de4dot.code.deobfuscators.CodeWall {
|
|||
StringDecrypter stringDecrypter;
|
||||
|
||||
internal class Options : OptionsBase {
|
||||
public bool DumpEmbeddedAssemblies { get; set; }
|
||||
}
|
||||
|
||||
public override string Type {
|
||||
|
@ -127,6 +132,21 @@ namespace de4dot.code.deobfuscators.CodeWall {
|
|||
foreach (var info in stringDecrypter.Infos)
|
||||
staticStringInliner.add(info.Method, (method, args) => stringDecrypter.decrypt(method, (int)args[0], (int)args[1], (int)args[2]));
|
||||
DeobfuscatedFile.stringDecryptersAdded();
|
||||
|
||||
dumpEmbeddedAssemblies();
|
||||
}
|
||||
|
||||
void dumpEmbeddedAssemblies() {
|
||||
if (!options.DumpEmbeddedAssemblies)
|
||||
return;
|
||||
var asmDecrypter = new AssemblyDecrypter(module, DeobfuscatedFile, this);
|
||||
asmDecrypter.find();
|
||||
foreach (var info in asmDecrypter.AssemblyInfos) {
|
||||
var asmName = info.assemblySimpleName;
|
||||
if (info.isEntryPointAssembly)
|
||||
asmName += "_real";
|
||||
DeobfuscatedFile.createAssemblyFile(info.data, asmName, info.extension);
|
||||
}
|
||||
}
|
||||
|
||||
public override void deobfuscateMethodEnd(Blocks blocks) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user