Add CO deobfuscator. Can decrypt embedded assemblies.
This commit is contained in:
parent
99bd79e418
commit
3f1b9152bd
|
@ -468,6 +468,10 @@ namespace de4dot.blocks {
|
||||||
public static IList<Instruction> getInstructions(IList<Instruction> instructions, int i, params OpCode[] opcodes) {
|
public static IList<Instruction> getInstructions(IList<Instruction> instructions, int i, params OpCode[] opcodes) {
|
||||||
if (i + opcodes.Length > instructions.Count)
|
if (i + opcodes.Length > instructions.Count)
|
||||||
return null;
|
return null;
|
||||||
|
if (opcodes.Length == 0)
|
||||||
|
return new List<Instruction>();
|
||||||
|
if (opcodes[0] != instructions[i].OpCode)
|
||||||
|
return null;
|
||||||
|
|
||||||
var list = new List<Instruction>(opcodes.Length);
|
var list = new List<Instruction>(opcodes.Length);
|
||||||
for (int j = 0; j < opcodes.Length; j++) {
|
for (int j = 0; j < opcodes.Length; j++) {
|
||||||
|
|
|
@ -749,9 +749,11 @@ namespace de4dot {
|
||||||
deobfuscate(method, "Static string decryption", (blocks) => theDeob.deobfuscateStrings(blocks));
|
deobfuscate(method, "Static string decryption", (blocks) => theDeob.deobfuscateStrings(blocks));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDeobfuscatedFile.createAssemblyFile(byte[] data, string assemblyName) {
|
void IDeobfuscatedFile.createAssemblyFile(byte[] data, string assemblyName, string extension) {
|
||||||
|
if (extension == null)
|
||||||
|
extension = ".dll";
|
||||||
var baseDir = Utils.getDirName(options.NewFilename);
|
var baseDir = Utils.getDirName(options.NewFilename);
|
||||||
var newName = Path.Combine(baseDir, assemblyName + ".dll");
|
var newName = Path.Combine(baseDir, assemblyName + extension);
|
||||||
Log.n("Creating file {0}", newName);
|
Log.n("Creating file {0}", newName);
|
||||||
using (var writer = new BinaryWriter(new FileStream(newName, FileMode.Create))) {
|
using (var writer = new BinaryWriter(new FileStream(newName, FileMode.Create))) {
|
||||||
writer.Write(data);
|
writer.Write(data);
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace de4dot {
|
||||||
return new List<IDeobfuscatorInfo> {
|
return new List<IDeobfuscatorInfo> {
|
||||||
new de4dot.deobfuscators.Unknown.DeobfuscatorInfo(),
|
new de4dot.deobfuscators.Unknown.DeobfuscatorInfo(),
|
||||||
new de4dot.deobfuscators.CliSecure.DeobfuscatorInfo(),
|
new de4dot.deobfuscators.CliSecure.DeobfuscatorInfo(),
|
||||||
|
new de4dot.deobfuscators.CryptoObfuscator.DeobfuscatorInfo(),
|
||||||
new de4dot.deobfuscators.Dotfuscator.DeobfuscatorInfo(),
|
new de4dot.deobfuscators.Dotfuscator.DeobfuscatorInfo(),
|
||||||
new de4dot.deobfuscators.Eazfuscator.DeobfuscatorInfo(),
|
new de4dot.deobfuscators.Eazfuscator.DeobfuscatorInfo(),
|
||||||
new de4dot.deobfuscators.SmartAssembly.DeobfuscatorInfo(),
|
new de4dot.deobfuscators.SmartAssembly.DeobfuscatorInfo(),
|
||||||
|
|
|
@ -191,5 +191,12 @@ namespace de4dot {
|
||||||
return false;
|
return false;
|
||||||
return left.Substring(0, right.Length).Equals(right, stringComparison);
|
return left.Substring(0, right.Length).Equals(right, stringComparison);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string getAssemblySimpleName(string name) {
|
||||||
|
int i = name.IndexOf(',');
|
||||||
|
if (i < 0)
|
||||||
|
return name;
|
||||||
|
return name.Substring(0, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,10 @@
|
||||||
<Compile Include="CommandLineParser.cs" />
|
<Compile Include="CommandLineParser.cs" />
|
||||||
<Compile Include="deobfuscators\CliSecure\Deobfuscator.cs" />
|
<Compile Include="deobfuscators\CliSecure\Deobfuscator.cs" />
|
||||||
<Compile Include="deobfuscators\CliSecure\ProxyDelegateFinder.cs" />
|
<Compile Include="deobfuscators\CliSecure\ProxyDelegateFinder.cs" />
|
||||||
|
<Compile Include="deobfuscators\CryptoObfuscator\AssemblyResolver.cs" />
|
||||||
|
<Compile Include="deobfuscators\CryptoObfuscator\Deobfuscator.cs" />
|
||||||
|
<Compile Include="deobfuscators\CryptoObfuscator\ResourceDecrypter.cs" />
|
||||||
|
<Compile Include="deobfuscators\CryptoObfuscator\ResourceResolver.cs" />
|
||||||
<Compile Include="deobfuscators\DeobfuscatorBase.cs" />
|
<Compile Include="deobfuscators\DeobfuscatorBase.cs" />
|
||||||
<Compile Include="deobfuscators\DeobfuscatorInfoBase.cs" />
|
<Compile Include="deobfuscators\DeobfuscatorInfoBase.cs" />
|
||||||
<Compile Include="deobfuscators\DeobUtils.cs" />
|
<Compile Include="deobfuscators\DeobUtils.cs" />
|
||||||
|
@ -80,7 +84,6 @@
|
||||||
<Compile Include="deobfuscators\SmartAssembly\ResourceDecrypterInfo.cs" />
|
<Compile Include="deobfuscators\SmartAssembly\ResourceDecrypterInfo.cs" />
|
||||||
<Compile Include="deobfuscators\SmartAssembly\ResourceResolver.cs" />
|
<Compile Include="deobfuscators\SmartAssembly\ResourceResolver.cs" />
|
||||||
<Compile Include="deobfuscators\SmartAssembly\ResourceResolverInfo.cs" />
|
<Compile Include="deobfuscators\SmartAssembly\ResourceResolverInfo.cs" />
|
||||||
<Compile Include="deobfuscators\SmartAssembly\SA_Utils.cs" />
|
|
||||||
<Compile Include="deobfuscators\SmartAssembly\SimpleZipInfo.cs" />
|
<Compile Include="deobfuscators\SmartAssembly\SimpleZipInfo.cs" />
|
||||||
<Compile Include="deobfuscators\SmartAssembly\StringDecrypter.cs" />
|
<Compile Include="deobfuscators\SmartAssembly\StringDecrypter.cs" />
|
||||||
<Compile Include="deobfuscators\SmartAssembly\StringDecrypterInfo.cs" />
|
<Compile Include="deobfuscators\SmartAssembly\StringDecrypterInfo.cs" />
|
||||||
|
|
144
de4dot.code/deobfuscators/CryptoObfuscator/AssemblyResolver.cs
Normal file
144
de4dot.code/deobfuscators/CryptoObfuscator/AssemblyResolver.cs
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
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 System.Text;
|
||||||
|
using Mono.Cecil;
|
||||||
|
using Mono.Cecil.Cil;
|
||||||
|
using de4dot.blocks;
|
||||||
|
|
||||||
|
namespace de4dot.deobfuscators.CryptoObfuscator {
|
||||||
|
class AssemblyResolver {
|
||||||
|
ModuleDefinition module;
|
||||||
|
ResourceDecrypter resourceDecrypter;
|
||||||
|
TypeDefinition resolverType;
|
||||||
|
List<AssemblyInfo> assemblyInfos;
|
||||||
|
|
||||||
|
public class AssemblyInfo {
|
||||||
|
public string assemblyName;
|
||||||
|
public EmbeddedResource resource;
|
||||||
|
public EmbeddedResource symbolsResource;
|
||||||
|
public AssemblyInfo(string assemblyName, EmbeddedResource resource, EmbeddedResource symbolsResource) {
|
||||||
|
this.assemblyName = assemblyName;
|
||||||
|
this.resource = resource;
|
||||||
|
this.symbolsResource = symbolsResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() {
|
||||||
|
return string.Format("{{{0} => {1}}}", assemblyName, resource.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AssemblyInfo> AssemblyInfos {
|
||||||
|
get { return assemblyInfos; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssemblyResolver(ModuleDefinition module, ResourceDecrypter resourceDecrypter) {
|
||||||
|
this.module = module;
|
||||||
|
this.resourceDecrypter = resourceDecrypter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void find() {
|
||||||
|
var cctor = DotNetUtils.getMethod(DotNetUtils.getModuleType(module), ".cctor");
|
||||||
|
if (cctor == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var tuple in DotNetUtils.getCalledMethods(module, cctor)) {
|
||||||
|
var method = tuple.Item2;
|
||||||
|
if (method.Name == ".cctor" || method.Name == ".ctor")
|
||||||
|
continue;
|
||||||
|
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()"))
|
||||||
|
continue;
|
||||||
|
if (checkType(tuple.Item1, method))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkType(TypeDefinition type, MethodDefinition initMethod) {
|
||||||
|
if (DotNetUtils.findFieldType(type, "System.Collections.Hashtable", true) == null)
|
||||||
|
return false;
|
||||||
|
if (!checkInitMethod(initMethod))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
List<AssemblyInfo> newAssemblyInfos = null;
|
||||||
|
foreach (var s in DotNetUtils.getCodeStrings(initMethod)) {
|
||||||
|
newAssemblyInfos = initializeEmbeddedAssemblies(s);
|
||||||
|
if (newAssemblyInfos != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (newAssemblyInfos == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
resolverType = type;
|
||||||
|
assemblyInfos = newAssemblyInfos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkInitMethod(MethodDefinition initMethod) {
|
||||||
|
if (!initMethod.HasBody)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var instructions = initMethod.Body.Instructions;
|
||||||
|
for (int i = 0; i < instructions.Count; i++) {
|
||||||
|
var instrs = DotNetUtils.getInstructions(instructions, i, OpCodes.Ldnull, OpCodes.Ldftn, OpCodes.Newobj);
|
||||||
|
if (instrs == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MethodReference methodRef;
|
||||||
|
var ldftn = instrs[1];
|
||||||
|
var newobj = instrs[2];
|
||||||
|
|
||||||
|
methodRef = ldftn.Operand as MethodReference;
|
||||||
|
if (methodRef == null || !MemberReferenceHelper.compareTypes(initMethod.DeclaringType, methodRef.DeclaringType))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
methodRef = newobj.Operand as MethodReference;
|
||||||
|
if (methodRef == null || methodRef.FullName != "System.Void System.ResolveEventHandler::.ctor(System.Object,System.IntPtr)")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AssemblyInfo> initializeEmbeddedAssemblies(string s) {
|
||||||
|
var sb = new StringBuilder(s.Length);
|
||||||
|
foreach (var c in s)
|
||||||
|
sb.Append((char)~c);
|
||||||
|
var tmpAssemblyInfos = sb.ToString().Split(new string[] { "##" }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (tmpAssemblyInfos.Length == 0 || (tmpAssemblyInfos.Length & 1) == 1)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var newAssemblyInfos = new List<AssemblyInfo>(tmpAssemblyInfos.Length / 2);
|
||||||
|
for (int i = 0; i < tmpAssemblyInfos.Length; i += 2) {
|
||||||
|
var assemblyName = tmpAssemblyInfos[i];
|
||||||
|
var resourceName = tmpAssemblyInfos[i + 1];
|
||||||
|
var resource = DotNetUtils.getResource(module, resourceName) as EmbeddedResource;
|
||||||
|
var symbolsResource = DotNetUtils.getResource(module, resourceName + "#") as EmbeddedResource;
|
||||||
|
if (resource == null)
|
||||||
|
return null;
|
||||||
|
newAssemblyInfos.Add(new AssemblyInfo(assemblyName, resource, symbolsResource));
|
||||||
|
}
|
||||||
|
|
||||||
|
return newAssemblyInfos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
161
de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs
Normal file
161
de4dot.code/deobfuscators/CryptoObfuscator/Deobfuscator.cs
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
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.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Mono.Cecil;
|
||||||
|
using de4dot.blocks;
|
||||||
|
|
||||||
|
namespace de4dot.deobfuscators.CryptoObfuscator {
|
||||||
|
class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
||||||
|
const string DEFAULT_REGEX = @"!^[A-Z]{1,3}(?:`\d+)?$&!^c[0-9a-f]{32}(?:`\d+)?$&" + DeobfuscatorBase.DEFAULT_VALID_NAME_REGEX;
|
||||||
|
public DeobfuscatorInfo()
|
||||||
|
: base("co", DEFAULT_REGEX) {
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string ObfuscatorType {
|
||||||
|
get { return "CryptoObfuscator"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Type {
|
||||||
|
get { return ObfuscatorType; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IDeobfuscator createDeobfuscator() {
|
||||||
|
return new Deobfuscator(new Deobfuscator.Options {
|
||||||
|
ValidNameRegex = validNameRegex.get(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IEnumerable<Option> getOptionsInternal() {
|
||||||
|
return new List<Option>() {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Deobfuscator : DeobfuscatorBase {
|
||||||
|
Options options;
|
||||||
|
string obfuscatorName = "Crypto Obfuscator";
|
||||||
|
bool foundCryptoObfuscatorAttribute = false;
|
||||||
|
bool foundObfuscatedSymbols = false;
|
||||||
|
|
||||||
|
ResourceDecrypter resourceDecrypter;
|
||||||
|
ResourceResolver resourceResolver;
|
||||||
|
AssemblyResolver assemblyResolver;
|
||||||
|
|
||||||
|
internal class Options : OptionsBase {
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Type {
|
||||||
|
get { return DeobfuscatorInfo.ObfuscatorType; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Name {
|
||||||
|
get { return obfuscatorName; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Deobfuscator(Options options)
|
||||||
|
: base(options) {
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void init(ModuleDefinition module) {
|
||||||
|
base.init(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int detect() {
|
||||||
|
scanForObfuscator();
|
||||||
|
|
||||||
|
int val = 0;
|
||||||
|
|
||||||
|
if (foundCryptoObfuscatorAttribute)
|
||||||
|
val += 100;
|
||||||
|
else if (foundObfuscatedSymbols)
|
||||||
|
val += 10;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void scanForObfuscatorInternal() {
|
||||||
|
foreach (var type in module.Types) {
|
||||||
|
if (type.FullName == "CryptoObfuscator.ProtectedWithCryptoObfuscatorAttribute") {
|
||||||
|
foundCryptoObfuscatorAttribute = true;
|
||||||
|
addAttributeToBeRemoved(type, "Obfuscator attribute");
|
||||||
|
initializeVersion(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (checkCryptoObfuscator())
|
||||||
|
foundObfuscatedSymbols = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeVersion(TypeDefinition attr) {
|
||||||
|
var s = DotNetUtils.getCustomArgAsString(getAssemblyAttribute(attr), 0);
|
||||||
|
if (s == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var val = Regex.Match(s, @"^Protected with (Crypto Obfuscator.*)$");
|
||||||
|
if (val.Groups.Count < 2)
|
||||||
|
return;
|
||||||
|
obfuscatorName = val.Groups[1].ToString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkCryptoObfuscator() {
|
||||||
|
int matched = 0;
|
||||||
|
foreach (var type in module.Types) {
|
||||||
|
if (type.Namespace != "A")
|
||||||
|
continue;
|
||||||
|
if (Regex.IsMatch(type.Name, "^c[0-9a-f]{32}$"))
|
||||||
|
return true;
|
||||||
|
else if (Regex.IsMatch(type.Name, "^A[A-Z]*$")) {
|
||||||
|
if (++matched >= 10)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void deobfuscateBegin() {
|
||||||
|
base.deobfuscateBegin();
|
||||||
|
|
||||||
|
resourceDecrypter = new ResourceDecrypter(module);
|
||||||
|
resourceResolver = new ResourceResolver(module, resourceDecrypter);
|
||||||
|
assemblyResolver = new AssemblyResolver(module, resourceDecrypter);
|
||||||
|
resourceResolver.find();
|
||||||
|
assemblyResolver.find();
|
||||||
|
|
||||||
|
dumpEmbeddedAssemblies();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpEmbeddedAssemblies() {
|
||||||
|
foreach (var info in assemblyResolver.AssemblyInfos) {
|
||||||
|
dumpEmbeddedFile(info.resource, info.assemblyName, true);
|
||||||
|
|
||||||
|
if (info.symbolsResource != null)
|
||||||
|
dumpEmbeddedFile(info.symbolsResource, info.assemblyName, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpEmbeddedFile(EmbeddedResource resource, string assemblyName, bool isAssembly) {
|
||||||
|
string extension = isAssembly ? ".dll" : ".pdb";
|
||||||
|
DeobfuscatedFile.createAssemblyFile(resourceDecrypter.decrypt(resource.GetResourceStream()), Utils.getAssemblySimpleName(assemblyName), extension);
|
||||||
|
addResourceToBeRemoved(resource, string.Format("Embedded assembly{0}: {1}", isAssembly ? "" : " (pdb)", assemblyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
103
de4dot.code/deobfuscators/CryptoObfuscator/ResourceDecrypter.cs
Normal file
103
de4dot.code/deobfuscators/CryptoObfuscator/ResourceDecrypter.cs
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
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.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using Mono.Cecil;
|
||||||
|
|
||||||
|
namespace de4dot.deobfuscators.CryptoObfuscator {
|
||||||
|
class ResourceDecrypter {
|
||||||
|
const int BUFLEN = 0x8000;
|
||||||
|
ModuleDefinition module;
|
||||||
|
byte[] buffer1 = new byte[BUFLEN];
|
||||||
|
byte[] buffer2 = new byte[BUFLEN];
|
||||||
|
|
||||||
|
public ResourceDecrypter(ModuleDefinition module) {
|
||||||
|
this.module = module;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] decrypt(Stream resourceStream) {
|
||||||
|
byte flags = (byte)resourceStream.ReadByte();
|
||||||
|
Stream sourceStream = resourceStream;
|
||||||
|
|
||||||
|
if ((flags & 1) != 0) {
|
||||||
|
var memStream = new MemoryStream((int)resourceStream.Length);
|
||||||
|
using (var provider = new DESCryptoServiceProvider()) {
|
||||||
|
var iv = new byte[8];
|
||||||
|
sourceStream.Read(iv, 0, 8);
|
||||||
|
provider.IV = iv;
|
||||||
|
provider.Key = getKey(sourceStream);
|
||||||
|
|
||||||
|
using (var transform = provider.CreateDecryptor()) {
|
||||||
|
while (true) {
|
||||||
|
int count = sourceStream.Read(buffer1, 0, buffer1.Length);
|
||||||
|
if (count <= 0)
|
||||||
|
break;
|
||||||
|
int count2 = transform.TransformBlock(buffer1, 0, count, buffer2, 0);
|
||||||
|
memStream.Write(buffer2, 0, count2);
|
||||||
|
}
|
||||||
|
var finalData = transform.TransformFinalBlock(buffer1, 0, 0);
|
||||||
|
memStream.Write(finalData, 0, finalData.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sourceStream = memStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & 2) != 0) {
|
||||||
|
var memStream = new MemoryStream((int)resourceStream.Length);
|
||||||
|
sourceStream.Position = 0;
|
||||||
|
var inflater = new DeflateStream(sourceStream, CompressionMode.Decompress);
|
||||||
|
while (true) {
|
||||||
|
int count = inflater.Read(buffer1, 0, buffer1.Length);
|
||||||
|
if (count <= 0)
|
||||||
|
break;
|
||||||
|
memStream.Write(buffer1, 0, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceStream = memStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceStream is MemoryStream) {
|
||||||
|
var memStream = (MemoryStream)sourceStream;
|
||||||
|
return memStream.ToArray();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int len = (int)(sourceStream.Length - sourceStream.Position);
|
||||||
|
byte[] data = new byte[len];
|
||||||
|
sourceStream.Read(data, 0, len);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] getKey(Stream resourceStream) {
|
||||||
|
byte[] key = new byte[8];
|
||||||
|
resourceStream.Read(key, 0, key.Length);
|
||||||
|
for (int i = 0; i < key.Length; i++) {
|
||||||
|
if (key[i] != 0)
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
key = module.Assembly.Name.PublicKeyToken;
|
||||||
|
if (key == null)
|
||||||
|
throw new ApplicationException("PublicKeyToken is null, can't decrypt resources");
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
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 Mono.Cecil;
|
||||||
|
using Mono.Cecil.Cil;
|
||||||
|
using de4dot.blocks;
|
||||||
|
|
||||||
|
namespace de4dot.deobfuscators.CryptoObfuscator {
|
||||||
|
class ResourceResolver {
|
||||||
|
ModuleDefinition module;
|
||||||
|
ResourceDecrypter resourceDecrypter;
|
||||||
|
TypeDefinition resolverType;
|
||||||
|
|
||||||
|
public ResourceResolver(ModuleDefinition module, ResourceDecrypter resourceDecrypter) {
|
||||||
|
this.module = module;
|
||||||
|
this.resourceDecrypter = resourceDecrypter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void find() {
|
||||||
|
var cctor = DotNetUtils.getMethod(DotNetUtils.getModuleType(module), ".cctor");
|
||||||
|
if (cctor == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var tuple in DotNetUtils.getCalledMethods(module, cctor)) {
|
||||||
|
var method = tuple.Item2;
|
||||||
|
if (method.Name == ".cctor" || method.Name == ".ctor")
|
||||||
|
continue;
|
||||||
|
if (!method.IsStatic || !DotNetUtils.isMethod(method, "System.Void", "()"))
|
||||||
|
continue;
|
||||||
|
if (checkType(tuple.Item1, method))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkType(TypeDefinition type, MethodDefinition initMethod) {
|
||||||
|
if (!initMethod.HasBody)
|
||||||
|
return false;
|
||||||
|
if (DotNetUtils.findFieldType(type, "System.Reflection.Assembly", true) == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var instructions = initMethod.Body.Instructions;
|
||||||
|
for (int i = 0; i < instructions.Count; i++) {
|
||||||
|
var instrs = DotNetUtils.getInstructions(instructions, i, OpCodes.Ldnull, OpCodes.Ldftn, OpCodes.Newobj);
|
||||||
|
if (instrs == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MethodReference methodRef;
|
||||||
|
var ldftn = instrs[1];
|
||||||
|
var newobj = instrs[2];
|
||||||
|
|
||||||
|
methodRef = ldftn.Operand as MethodReference;
|
||||||
|
if (methodRef == null || !MemberReferenceHelper.compareTypes(type, methodRef.DeclaringType))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
methodRef = newobj.Operand as MethodReference;
|
||||||
|
if (methodRef == null || methodRef.FullName != "System.Void System.ResolveEventHandler::.ctor(System.Object,System.IntPtr)")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
resolverType = type;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
namespace de4dot.deobfuscators {
|
namespace de4dot.deobfuscators {
|
||||||
interface IDeobfuscatedFile : ISimpleDeobfuscator {
|
interface IDeobfuscatedFile : ISimpleDeobfuscator {
|
||||||
void createAssemblyFile(byte[] data, string assemblyName);
|
void createAssemblyFile(byte[] data, string assemblyName, string extension = null);
|
||||||
void stringDecryptersAdded();
|
void stringDecryptersAdded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace de4dot.deobfuscators.SmartAssembly {
|
||||||
info.assemblyName = Encoding.UTF8.GetString(Convert.FromBase64String(encName));
|
info.assemblyName = Encoding.UTF8.GetString(Convert.FromBase64String(encName));
|
||||||
info.resourceName = rsrcName;
|
info.resourceName = rsrcName;
|
||||||
info.resource = DotNetUtils.getResource(module, rsrcName) as EmbeddedResource;
|
info.resource = DotNetUtils.getResource(module, rsrcName) as EmbeddedResource;
|
||||||
info.simpleName = SA_Utils.getAssemblySimpleName(info.assemblyName);
|
info.simpleName = Utils.getAssemblySimpleName(info.assemblyName);
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace de4dot.deobfuscators.SmartAssembly {
|
||||||
if (s == null || calledMethod == null)
|
if (s == null || calledMethod == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
resource = DotNetUtils.getResource(module, SA_Utils.getAssemblySimpleName(s)) as EmbeddedResource;
|
resource = DotNetUtils.getResource(module, Utils.getAssemblySimpleName(s)) as EmbeddedResource;
|
||||||
if (resource != null)
|
if (resource != null)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace de4dot.deobfuscators.SmartAssembly {
|
|
||||||
static class SA_Utils {
|
|
||||||
public static string getAssemblySimpleName(string name) {
|
|
||||||
int i = name.IndexOf(',');
|
|
||||||
if (i < 0)
|
|
||||||
return name;
|
|
||||||
return name.Substring(0, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -90,8 +90,6 @@ namespace de4dot.deobfuscators.Unknown {
|
||||||
return "CodeFort";
|
return "CodeFort";
|
||||||
if (type.FullName == "____KILL")
|
if (type.FullName == "____KILL")
|
||||||
return "DeployLX CodeVeil";
|
return "DeployLX CodeVeil";
|
||||||
if (type.FullName == "CryptoObfuscator.ProtectedWithCryptoObfuscatorAttribute")
|
|
||||||
return "Crypto Obfuscator";
|
|
||||||
if (type.FullName.Contains("ObfuscatedByGoliath"))
|
if (type.FullName.Contains("ObfuscatedByGoliath"))
|
||||||
return "Goliath .NET Obfuscator";
|
return "Goliath .NET Obfuscator";
|
||||||
if (type.FullName == "Xenocode.Client.Attributes.AssemblyAttributes.ProcessedByXenocode")
|
if (type.FullName == "Xenocode.Client.Attributes.AssemblyAttributes.ProcessedByXenocode")
|
||||||
|
@ -109,21 +107,6 @@ namespace de4dot.deobfuscators.Unknown {
|
||||||
if (type.FullName == "YanoAttribute")
|
if (type.FullName == "YanoAttribute")
|
||||||
return "Yano Obfuscator";
|
return "Yano Obfuscator";
|
||||||
}
|
}
|
||||||
return checkCryptoObfuscator();
|
|
||||||
}
|
|
||||||
|
|
||||||
string checkCryptoObfuscator() {
|
|
||||||
int matched = 0;
|
|
||||||
foreach (var type in module.Types) {
|
|
||||||
if (type.Namespace != "A")
|
|
||||||
continue;
|
|
||||||
if (Regex.IsMatch(type.Name, "^c[0-9a-f]{32}$"))
|
|
||||||
return "Crypto Obfuscator";
|
|
||||||
else if (Regex.IsMatch(type.Name, "^A[A-Z]*$")) {
|
|
||||||
if (++matched >= 10)
|
|
||||||
return "Crypto Obfuscator";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user