Port Goliath.NET deobfuscator

This commit is contained in:
de4dot 2012-11-18 03:02:12 +01:00
parent c596f5ddfc
commit 1c4b3a7382
16 changed files with 80 additions and 71 deletions

View File

@ -26,7 +26,7 @@ namespace de4dot.blocks {
Dictionary<ScopeAndTokenKey, TValue> tokenToValue = new Dictionary<ScopeAndTokenKey, TValue>();
Dictionary<ScopeAndTokenKey, TypeDef> tokenToKey = new Dictionary<ScopeAndTokenKey, TypeDef>();
Dictionary<IType, TValue> refToValue = new Dictionary<IType, TValue>(TypeEqualityComparer.Instance);
Dictionary<IType, TypeDef> refToKey = new Dictionary<IType, TypeDef>();
Dictionary<IType, TypeDef> refToKey = new Dictionary<IType, TypeDef>(TypeEqualityComparer.Instance);
public int Count {
get { return tokenToValue.Count; }

View File

@ -169,10 +169,10 @@ namespace de4dot.blocks.cflow {
var methodArgs = methodToInline.Parameters;
var calledMethodArgs = DotNetUtils.getArgs(ctor);
if (methodArgs.Count - popLastArgs != calledMethodArgs.Count)
if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count)
return null;
for (int i = 1; i < calledMethodArgs.Count; i++) {
if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i].Type))
if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1].Type))
return null;
}

View File

@ -188,16 +188,16 @@
<Compile Include="deobfuscators\Eazfuscator_NET\StringDecrypter.cs" />
<Compile Include="deobfuscators\Eazfuscator_NET\VersionDetector.cs" />
<Compile Include="deobfuscators\ExceptionLoggerRemover.cs" />
<None Include="deobfuscators\Goliath_NET\ArrayDecrypter.cs" />
<None Include="deobfuscators\Goliath_NET\ArrayValueInliner.cs" />
<None Include="deobfuscators\Goliath_NET\DecrypterBase.cs" />
<None Include="deobfuscators\Goliath_NET\Deobfuscator.cs" />
<None Include="deobfuscators\Goliath_NET\IntegerDecrypter.cs" />
<None Include="deobfuscators\Goliath_NET\LocalsRestorer.cs" />
<None Include="deobfuscators\Goliath_NET\LogicalExpressionFixer.cs" />
<None Include="deobfuscators\Goliath_NET\ProxyCallFixer.cs" />
<None Include="deobfuscators\Goliath_NET\StringDecrypter.cs" />
<None Include="deobfuscators\Goliath_NET\StrongNameChecker.cs" />
<Compile Include="deobfuscators\Goliath_NET\ArrayDecrypter.cs" />
<Compile Include="deobfuscators\Goliath_NET\ArrayValueInliner.cs" />
<Compile Include="deobfuscators\Goliath_NET\DecrypterBase.cs" />
<Compile Include="deobfuscators\Goliath_NET\Deobfuscator.cs" />
<Compile Include="deobfuscators\Goliath_NET\IntegerDecrypter.cs" />
<Compile Include="deobfuscators\Goliath_NET\LocalsRestorer.cs" />
<Compile Include="deobfuscators\Goliath_NET\LogicalExpressionFixer.cs" />
<Compile Include="deobfuscators\Goliath_NET\ProxyCallFixer.cs" />
<Compile Include="deobfuscators\Goliath_NET\StringDecrypter.cs" />
<Compile Include="deobfuscators\Goliath_NET\StrongNameChecker.cs" />
<Compile Include="deobfuscators\IDeobfuscatedFile.cs" />
<Compile Include="deobfuscators\IDeobfuscator.cs" />
<Compile Include="deobfuscators\IDeobfuscatorInfo.cs" />

View File

@ -23,7 +23,7 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.Goliath_NET {
class ArrayDecrypter : DecrypterBase {
public ArrayDecrypter(ModuleDefinition module)
public ArrayDecrypter(ModuleDefMD module)
: base(module) {
}

View File

@ -26,9 +26,9 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.Goliath_NET {
class ArrayValueInliner : ValueInlinerBase<byte[]> {
InitializedDataCreator initializedDataCreator;
ModuleDefinition module;
ModuleDefMD module;
public ArrayValueInliner(ModuleDefinition module, InitializedDataCreator initializedDataCreator) {
public ArrayValueInliner(ModuleDefMD module, InitializedDataCreator initializedDataCreator) {
this.module = module;
this.initializedDataCreator = initializedDataCreator;
}
@ -39,7 +39,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
int num = callResult.callEndIndex - callResult.callStartIndex + 1;
var arrayData = (byte[])callResult.returnValue;
initializedDataCreator.addInitializeArrayCode(block, callResult.callStartIndex, num, module.TypeSystem.Byte, arrayData);
initializedDataCreator.addInitializeArrayCode(block, callResult.callStartIndex, num, module.CorLibTypes.Byte.TypeDefOrRef, arrayData);
Logger.v("Decrypted array: {0} bytes", arrayData.Length);
}
}

View File

@ -26,7 +26,7 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.Goliath_NET {
abstract class DecrypterBase {
protected ModuleDefinition module;
protected ModuleDefMD module;
EmbeddedResource encryptedResource;
TypeDef decrypterType;
TypeDef delegateType;
@ -75,7 +75,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
}
}
public DecrypterBase(ModuleDefinition module) {
public DecrypterBase(ModuleDefMD module) {
this.module = module;
}
@ -93,12 +93,11 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
var resource = tmp as EmbeddedResource;
if (resource == null)
continue;
if (!resource.Name.EndsWith(".resources", StringComparison.Ordinal))
if (!resource.Name.String.EndsWith(".resources", StringComparison.Ordinal))
continue;
string ns, name;
splitTypeName(resource.Name.Substring(0, resource.Name.Length - 10), out ns, out name);
var typeRef = new TypeReference(ns, name, module, module);
var type = DotNetUtils.getType(module, typeRef);
splitTypeName(resource.Name.String.Substring(0, resource.Name.String.Length - 10), out ns, out name);
var type = new TypeRefUser(module, ns, name, module).Resolve();
if (type == null)
continue;
if (!checkDecrypterType(type))
@ -132,7 +131,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
delegateType = null;
foreach (var type in module.GetTypes()) {
var cctor = DotNetUtils.getMethod(type, ".cctor");
var cctor = type.FindStaticConstructor();
if (cctor == null)
continue;
@ -158,9 +157,10 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
continue;
if (!method.IsStatic || method.Body == null)
continue;
if (method.Parameters.Count != 0)
var sig = method.MethodSig;
if (sig == null || sig.Params.Count != 0)
continue;
if (method.MethodReturnType.ReturnType.FullName == "System.Void")
if (sig.RetType.GetElementType() == ElementType.Void)
continue;
var info = getDecrypterInfo(method, field);
if (info == null)
@ -181,13 +181,13 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
if (field != delegateField)
return null;
if (!DotNetUtils.isLdcI4(instrs[index]))
if (!instrs[index].IsLdcI4())
return null;
int offset = DotNetUtils.getLdcI4Value(instrs[index++]);
int offset = instrs[index++].GetLdcI4Value();
if (instrs[index].OpCode.Code != Code.Call && instrs[index].OpCode.Code != Code.Callvirt)
return null;
var calledMethod = instrs[index++].Operand as MethodReference;
var calledMethod = instrs[index++].Operand as IMethod;
if (calledMethod.Name != "Invoke")
return null;
@ -206,7 +206,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
bool checkCctor(MethodDef cctor) {
var ldtokenType = getLdtokenType(cctor);
if (!MemberReferenceHelper.compareTypes(ldtokenType, cctor.DeclaringType))
if (!new SigComparer().Equals(ldtokenType, cctor.DeclaringType))
return false;
MethodDef initMethod = null;
@ -222,13 +222,13 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
return true;
}
static TypeReference getLdtokenType(MethodDef method) {
static ITypeDefOrRef getLdtokenType(MethodDef method) {
if (method == null || method.Body == null)
return null;
foreach (var instr in method.Body.Instructions) {
if (instr.OpCode.Code != Code.Ldtoken)
continue;
return instr.Operand as TypeReference;
return instr.Operand as ITypeDefOrRef;
}
return null;
}
@ -236,7 +236,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
bool checkDelegateType(TypeDef type) {
if (!DotNetUtils.derivesFromDelegate(type))
return false;
var invoke = DotNetUtils.getMethod(type, "Invoke");
var invoke = type.FindMethod("Invoke");
if (invoke == null)
return false;
return checkDelegateInvokeMethod(invoke);
@ -249,7 +249,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
if (encryptedData.Length < KEY_LEN)
throw new ApplicationException("Invalid encrypted data length");
var decryptedData = new byte[encryptedData.Length - KEY_LEN];
var pkt = module.Assembly.Name.PublicKeyToken;
var pkt = PublicKey.GetRawData(PublicKeyBase.ToPublicKeyToken(module.Assembly.PublicKey));
if (pkt == null || pkt.Length == 0)
pkt = new byte[8];
@ -279,7 +279,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
var ldtokenType = getLdtokenType(method);
if (ldtokenType == null)
continue;
if (!MemberReferenceHelper.compareTypes(ldtokenType, delegateType))
if (!new SigComparer().Equals(ldtokenType, delegateType))
continue;
delegateInitType = type;

View File

@ -23,7 +23,7 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.Goliath_NET {
class IntegerDecrypter : DecrypterBase {
public IntegerDecrypter(ModuleDefinition module)
public IntegerDecrypter(ModuleDefMD module)
: base(module) {
}

View File

@ -24,14 +24,14 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.Goliath_NET {
class LocalsRestorer {
ModuleDefinition module;
ModuleDefMD module;
TypeDefinitionDict<Info> typeToInfo = new TypeDefinitionDict<Info>();
class Info {
public TypeDef type;
public TypeReference localType;
public TypeSig localType;
public bool referenced = false;
public Info(TypeDef type, TypeReference localType) {
public Info(TypeDef type, TypeSig localType) {
this.type = type;
this.localType = localType;
}
@ -48,7 +48,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
}
}
public LocalsRestorer(ModuleDefinition module) {
public LocalsRestorer(ModuleDefMD module) {
this.module = module;
}
@ -68,16 +68,17 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
var ctor = type.Methods[0];
if (ctor.Name != ".ctor" || ctor.Body == null || ctor.IsStatic)
return;
if (ctor.Parameters.Count != 1)
var sig = ctor.MethodSig;
if (sig == null || sig.Params.Count != 1)
return;
var ctorParam = ctor.Parameters[0];
var ctorParam = sig.Params[0];
if (type.Fields.Count != 1)
return;
var typeField = type.Fields[0];
if (typeField.IsStatic)
return;
if (!MemberReferenceHelper.compareTypes(ctorParam.ParameterType, typeField.FieldType))
if (!new SigComparer().Equals(ctorParam, typeField.FieldType))
return;
typeToInfo.add(ctor.DeclaringType, new Info(ctor.DeclaringType, typeField.FieldType));
@ -91,13 +92,13 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
for (int i = 0; i < instrs.Count; i++) {
var instr = instrs[i];
int indexToRemove;
TypeReference type;
VariableDefinition local = null;
ITypeDefOrRef type;
Local local = null;
if (instr.OpCode.Code == Code.Newobj) {
if (i + 1 >= instrs.Count)
continue;
var ctor = instr.Operand as MethodReference;
var ctor = instr.Operand as IMethod;
if (ctor == null || ctor.DeclaringType == null)
continue;
if (ctor.Name != ".ctor")
@ -119,7 +120,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
if (!ldloc.isLdloc())
continue;
var field = instr.Operand as FieldReference;
var field = instr.Operand as IField;
if (field == null || field.DeclaringType == null)
continue;
@ -139,9 +140,10 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
info.referenced = true;
instrsToRemove.Add(indexToRemove);
if (local != null)
local.VariableType = info.localType;
local.Type = info.localType;
}
block.remove(instrsToRemove);
if (instrsToRemove.Count > 0)
block.remove(instrsToRemove);
}
}
}

View File

@ -25,7 +25,7 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.Goliath_NET {
class ProxyCallFixer : ProxyCallFixer2 {
public ProxyCallFixer(ModuleDefinition module)
public ProxyCallFixer(ModuleDefMD module)
: base(module) {
}
@ -89,33 +89,36 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
var field = instrs[index++].Operand as FieldDef;
if (field == null || !field.IsStatic)
return false;
if (!MemberReferenceHelper.compareTypes(method.DeclaringType, field.DeclaringType))
if (!new SigComparer().Equals(method.DeclaringType, field.DeclaringType))
return false;
if (!DotNetUtils.isBrtrue(instrs[index++]))
if (!instrs[index++].IsBrtrue())
return false;
if (instrs[index++].OpCode.Code != Code.Ldnull)
return false;
if (instrs[index].OpCode.Code != Code.Ldftn)
return false;
var calledMethod = instrs[index++].Operand as MethodReference;
var calledMethod = instrs[index++].Operand as IMethod;
if (calledMethod == null)
return false;
if (instrs[index++].OpCode.Code != Code.Newobj)
return false;
if (instrs[index].OpCode.Code != Code.Stsfld)
return false;
if (!MemberReferenceHelper.compareFieldReference(field, instrs[index++].Operand as FieldReference))
if (!new SigComparer().Equals(field, instrs[index++].Operand as IField))
return false;
if (instrs[index].OpCode.Code != Code.Ldsfld)
return false;
if (!MemberReferenceHelper.compareFieldReference(field, instrs[index++].Operand as FieldReference))
if (!new SigComparer().Equals(field, instrs[index++].Operand as IField))
return false;
for (int i = 0; i < method.Parameters.Count; i++) {
var sig = method.MethodSig;
if (sig == null)
return false;
for (int i = 0; i < sig.Params.Count; i++) {
if (index >= instrs.Count)
return false;
if (DotNetUtils.getArgIndex(instrs[index++]) != i)
if (instrs[index++].GetParameterIndex() != i)
return false;
}
@ -136,7 +139,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
throw new System.NotImplementedException();
}
protected override void getCallInfo(object context, FieldDef field, out MethodReference calledMethod, out OpCode callOpcode) {
protected override void getCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode) {
throw new System.NotImplementedException();
}
}

View File

@ -25,14 +25,14 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.Goliath_NET {
class StringDecrypter : DecrypterBase {
TypeReference delegateReturnType;
IType delegateReturnType;
FieldDef stringStructField;
public TypeDef StringStruct {
get { return Detected && stringStructField != null ? stringStructField.DeclaringType : null; }
}
public StringDecrypter(ModuleDefinition module)
public StringDecrypter(ModuleDefMD module)
: base(module) {
}
@ -48,10 +48,10 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
if (fields[0].FieldType.FullName != "System.Byte[]")
return false;
var dict = fields[1].FieldType as GenericInstanceType;
var dict = fields[1].FieldType.ToGenericInstSig();
if (dict == null || dict.GenericArguments.Count != 2)
return false;
if (dict.ElementType.FullName != "System.Collections.Generic.Dictionary`2")
if (dict.GenericType.GetFullName() != "System.Collections.Generic.Dictionary`2")
return false;
if (dict.GenericArguments[0].FullName != "System.Int32")
@ -106,7 +106,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
var ldfld = instrs[i + 1];
if (ldfld.OpCode.Code != Code.Ldfld)
continue;
if (!MemberReferenceHelper.compareFieldReferenceAndDeclaringType(stringStructField, ldfld.Operand as FieldReference))
if (!FieldEqualityComparer.CompareDeclaringTypes.Equals(stringStructField, ldfld.Operand as IField))
continue;
block.remove(i + 1, 1);
}

View File

@ -23,7 +23,7 @@ using de4dot.blocks;
namespace de4dot.code.deobfuscators.Goliath_NET {
class StrongNameChecker {
ModuleDefinition module;
ModuleDefMD module;
TypeDef strongNameType;
MethodDef strongNameCheckMethod;
@ -39,7 +39,7 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
get { return strongNameCheckMethod; }
}
public StrongNameChecker(ModuleDefinition module) {
public StrongNameChecker(ModuleDefMD module) {
this.module = module;
}
@ -108,13 +108,13 @@ namespace de4dot.code.deobfuscators.Goliath_NET {
var call1 = instrs[i + 1];
if (call1.OpCode.Code != Code.Call && call1.OpCode.Code != Code.Callvirt)
continue;
if (!DotNetUtils.isMethod(call1.Operand as MethodReference, "System.Type", "(System.RuntimeTypeHandle)"))
if (!DotNetUtils.isMethod(call1.Operand as IMethod, "System.Type", "(System.RuntimeTypeHandle)"))
continue;
var call2 = instrs[i + 2];
if (call2.OpCode.Code != Code.Call && call2.OpCode.Code != Code.Callvirt)
continue;
if (!MemberReferenceHelper.compareMethodReferenceAndDeclaringType(call2.Operand as MethodReference, strongNameCheckMethod))
if (!MethodEqualityComparer.CompareDeclaringTypes.Equals(call2.Operand as IMethod, strongNameCheckMethod))
continue;
block.remove(i, 3);

View File

@ -168,7 +168,8 @@ namespace de4dot.code.deobfuscators {
else
removeIndexes.Add(info.Index);
}
block.remove(removeIndexes);
if (removeIndexes.Count > 0)
block.remove(removeIndexes);
}
return removeInfos.Count > 0;

View File

@ -633,6 +633,7 @@ namespace de4dot.code.renamer.asmmodules {
case ElementType.GenericInst:
var gis = (GenericInstSig)ts;
add(gis.GenericType);
add(gis.GenericArguments);
break;

View File

@ -146,9 +146,11 @@ namespace de4dot.cui {
}));
miscOptions.Add(new NoArgOption("v", null, "Verbose", () => {
Logger.Instance.MaxLoggerEvent = LoggerEvent.Verbose;
Logger.Instance.CanIgnoreMessages = false;
}));
miscOptions.Add(new NoArgOption("vv", null, "Very verbose", () => {
Logger.Instance.MaxLoggerEvent = LoggerEvent.VeryVerbose;
Logger.Instance.CanIgnoreMessages = false;
}));
miscOptions.Add(new NoArgOption("h", "help", "Show this help message", () => {
usage();

View File

@ -49,8 +49,8 @@ namespace de4dot.cui {
new de4dot.code.deobfuscators.dotNET_Reactor.v3.DeobfuscatorInfo(),
new de4dot.code.deobfuscators.dotNET_Reactor.v4.DeobfuscatorInfo(),
new de4dot.code.deobfuscators.Eazfuscator_NET.DeobfuscatorInfo(),
#if PORT
new de4dot.code.deobfuscators.Goliath_NET.DeobfuscatorInfo(),
#if PORT
new de4dot.code.deobfuscators.ILProtector.DeobfuscatorInfo(),
new de4dot.code.deobfuscators.MaxtoCode.DeobfuscatorInfo(),
#endif
@ -110,7 +110,7 @@ namespace de4dot.cui {
if (Logger.Instance.NumIgnoredMessages > 0) {
Logger.n("Ignored {0} warnings/errors", Logger.Instance.NumIgnoredMessages);
Logger.n("Set environment variable {0}=1 to see all messages", showAllMessagesEnvName);
Logger.n("Use -v/-vv option or set environment variable {0}=1 to see all messages", showAllMessagesEnvName);
}
if (isN00bUser()) {

2
dot10

@ -1 +1 @@
Subproject commit f863f442bac69c0ce647c45ae6d1df8d55757e0c
Subproject commit 4abefc928d63ffe8b7d6c5b4646b2205e684c1c4