Make it compatible with 5.0 again

Version detection may be flawed since it checks if the string decryptor
method uses cgt.un instead of ceq for flags because the changes in 5.1
are subtle.
This commit is contained in:
PythEch 2016-01-24 00:45:37 +02:00
parent 84e0aa0b77
commit 2581da1c26
2 changed files with 112 additions and 3 deletions

View File

@ -155,6 +155,12 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
stringMethod = method;
realMethod = GetRealDecrypterMethod(method);
isV50OrLater = true;
foreach (var inst in stringMethod.Body.Instructions) {
if (inst.OpCode.Code == Code.Cgt_Un) {
isV51OrLater = true;
break;
}
}
}
else stringMethod = method;
@ -422,7 +428,36 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
return -1;
}
static Local GetFlagsLocal(MethodDef method, int index) {
Local GetFlagsLocal(MethodDef method, int index) {
if (isV51OrLater)
return GetFlagsLocalNew(method, index);
return GetFlagsLocalOld(method, index);
}
// <= 5.0
static Local GetFlagsLocalOld(MethodDef method, int index) {
var instrs = method.Body.Instructions;
if (index + 5 >= instrs.Count)
return null;
if (instrs[index++].OpCode.Code != Code.And)
return null;
if (instrs[index++].OpCode.Code != Code.Ldc_I4_0)
return null;
if (instrs[index++].OpCode.Code != Code.Ceq)
return null;
if (instrs[index++].OpCode.Code != Code.Ldc_I4_0)
return null;
if (instrs[index++].OpCode.Code != Code.Ceq)
return null;
var stloc = instrs[index++];
if (!stloc.IsStloc())
return null;
return stloc.GetLocal(method.Body.Variables);
}
// 5.1+
// Uses different OpCodes
static Local GetFlagsLocalNew(MethodDef method, int index) {
var instrs = method.Body.Instructions;
if (index + 5 >= instrs.Count)
return null;
@ -695,7 +730,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
break;
}
}
done: ;
done:
foreach (var val in fields.Values) {
if (val == null)
@ -708,6 +743,75 @@ done: ;
}
bool EmulateDynocode(InstructionEmulator emu, ref int index) {
if (isV51OrLater)
return EmulateDynocodeNew(emu, ref index);
return EmulateDynocodeOld(emu, ref index);
}
// <= 5.0
bool EmulateDynocodeOld(InstructionEmulator emu, ref int index) {
var instrs = stringMethod.Body.Instructions;
var instr = instrs[index];
var ctor = instr.Operand as MethodDef;
if (ctor == null || ctor.MethodSig.GetParamCount() != 1 || ctor.MethodSig.Params[0].ElementType != ElementType.I4)
return false;
if (index + 4 >= instrs.Count)
return false;
var ldloc = instrs[index + 3];
var stfld = instrs[index + 4];
if (!ldloc.IsLdloc() || stfld.OpCode.Code != Code.Stfld)
return false;
var enumerableField = stfld.Operand as FieldDef;
if (enumerableField == null)
return false;
var initValue = emu.GetLocal(ldloc.GetLocal(stringMethod.Body.Variables)) as Int32Value;
if (initValue == null || !initValue.AllBitsValid())
return false;
int leaveIndex = FindLeave(instrs, index);
if (leaveIndex < 0)
return false;
var afterLoop = instrs[leaveIndex].Operand as Instruction;
if (afterLoop == null)
return false;
int newIndex = instrs.IndexOf(afterLoop);
var loopLocal = GetDCLoopLocal(index, newIndex);
if (loopLocal == null)
return false;
var initValue2 = emu.GetLocal(loopLocal) as Int32Value;
if (initValue2 == null || !initValue2.AllBitsValid())
return false;
int loopStart = GetIndexOfCall(instrs, index, leaveIndex, "System.Int32", "()");
int loopEnd = GetIndexOfCall(instrs, loopStart, leaveIndex, "System.Boolean", "()");
if (loopStart < 0 || loopEnd < 0)
return false;
loopStart++;
loopEnd--;
dynocode.Initialize(module);
var ctorArg = emu.Pop() as Int32Value;
if (ctorArg == null || !ctorArg.AllBitsValid())
return false;
dynocode.CreateEnumerable(ctor, new object[] { ctorArg.Value });
dynocode.WriteEnumerableField(enumerableField.MDToken.ToUInt32(), initValue.Value);
dynocode.CreateEnumerator();
foreach (var val in dynocode) {
emu.Push(new Int32Value(val));
for (int i = loopStart; i < loopEnd; i++)
emu.Emulate(instrs[i]);
}
index = newIndex - 1;
return true;
}
// 5.1+
// the only changes are the indexes of ldloc and stfld
bool EmulateDynocodeNew(InstructionEmulator emu, ref int index) {
var instrs = stringMethod.Body.Instructions;
var instr = instrs[index];

View File

@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using dnlib.DotNet.Emit;
using dnlib.DotNet;
using de4dot.blocks;
@ -818,7 +819,11 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
decryptStringMethod.Body.ExceptionHandlers.Count == 1 &&
new LocalTypes(decryptStringMethod).All(locals50) &&
CheckTypeFields2(fields50)) {
return "5.0";
foreach (var inst in stringDecrypter.Method.Body.Instructions) {
if (inst.OpCode.Code == Code.Cgt_Un)
return "5.1";
}
return "5.0";
}
}