Skip to content
This repository was archived by the owner on Dec 8, 2022. It is now read-only.

Commit 9715fe4

Browse files
committed
Merge pull request #117 from PythEch/fix-eazfuscator-51
Added support for Eazfuscator.NET 5.1
2 parents 4c684bb + 17c23f9 commit 9715fe4

File tree

3 files changed

+190
-12
lines changed

3 files changed

+190
-12
lines changed

de4dot.code/deobfuscators/Eazfuscator_NET/DecrypterType.cs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class DecrypterType {
3535
int i1, i2, i3;
3636
int m1_i1, m2_i1, m2_i2, m3_i1;
3737
MethodDef[] efConstMethods;
38+
List<int> shiftConsts;
3839

3940
public MethodDef Int64Method {
4041
get { return int64Method; }
@@ -54,6 +55,16 @@ public bool Detected {
5455
get { return type != null; }
5556
}
5657

58+
public List<int> ShiftConsts {
59+
get { return shiftConsts; }
60+
set {
61+
if (shiftConsts == null)
62+
shiftConsts = value;
63+
else if (shiftConsts != value)
64+
throw new ApplicationException("Found another one");
65+
}
66+
}
67+
5768
public DecrypterType(ModuleDefMD module, ISimpleDeobfuscator simpleDeobfuscator) {
5869
this.module = module;
5970
this.simpleDeobfuscator = simpleDeobfuscator;
@@ -216,6 +227,7 @@ bool FindMethodInts() {
216227
return false;
217228
}
218229

230+
219231
static List<MethodDef> GetBinaryIntMethods(TypeDef type) {
220232
var list = new List<MethodDef>();
221233
foreach (var method in type.Methods) {
@@ -346,15 +358,18 @@ public ulong GetMagic() {
346358
bytes.AddRange(module.Assembly.PublicKeyToken.Data);
347359
bytes.AddRange(Encoding.Unicode.GetBytes(module.Assembly.Name.String));
348360
}
349-
int cm1 = ConstMethod1();
350-
bytes.Add((byte)(type.MDToken.ToInt32() >> 24));
351-
bytes.Add((byte)(cm1 >> 16));
352-
bytes.Add((byte)(type.MDToken.ToInt32() >> 8));
353-
bytes.Add((byte)cm1);
354-
bytes.Add((byte)(type.MDToken.ToInt32() >> 16));
355-
bytes.Add((byte)(cm1 >> 8));
356-
bytes.Add((byte)type.MDToken.ToInt32());
357-
bytes.Add((byte)(cm1 >> 24));
361+
362+
int num3 = ConstMethod1();
363+
int num2 = type.MDToken.ToInt32();
364+
365+
bytes.Add((byte)(num2 >> shiftConsts[0]));
366+
bytes.Add((byte)(num3 >> shiftConsts[1]));
367+
bytes.Add((byte)(num2 >> shiftConsts[2]));
368+
bytes.Add((byte)(num3 >> shiftConsts[3]));
369+
bytes.Add((byte)(num2 >> shiftConsts[4]));
370+
bytes.Add((byte)(num3 >> shiftConsts[5]));
371+
bytes.Add((byte)(num2 >> shiftConsts[6]));
372+
bytes.Add((byte)(num3 >> shiftConsts[7]));
358373

359374
ulong magic = 0;
360375
foreach (var b in bytes) {

de4dot.code/deobfuscators/Eazfuscator_NET/StringDecrypter.cs

Lines changed: 160 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class StringDecrypter : IDisposable {
4747
EfConstantsReader stringMethodConsts;
4848
bool isV32OrLater;
4949
bool isV50OrLater;
50+
bool isV51OrLater;
5051
int? validStringDecrypterValue;
5152
DynamicDynocodeIterator dynocode;
5253
MethodDef realMethod;
@@ -154,6 +155,12 @@ public void Find() {
154155
stringMethod = method;
155156
realMethod = GetRealDecrypterMethod(method);
156157
isV50OrLater = true;
158+
foreach (var inst in stringMethod.Body.Instructions) {
159+
if (inst.OpCode.Code == Code.Cgt_Un) {
160+
isV51OrLater = true;
161+
break;
162+
}
163+
}
157164
}
158165
else stringMethod = method;
159166

@@ -318,10 +325,22 @@ bool FindConstants(ISimpleDeobfuscator simpleDeobfuscator) {
318325
if (decrypterType.Detected && !decrypterType.Initialize())
319326
return false;
320327

328+
if (!isV50OrLater) {
329+
decrypterType.ShiftConsts = new List<int> { 24, 16, 8, 0, 16, 8, 0, 24 };
330+
}
331+
else {
332+
List<int> shiftConsts;
333+
if (!FindShiftInts(decrypterType.Int64Method, out shiftConsts))
334+
return false;
335+
336+
decrypterType.ShiftConsts = shiftConsts;
337+
}
338+
321339
if (!FindInts(index))
322340
return false;
323341
}
324342

343+
325344
InitializeFlags();
326345
Initialize();
327346

@@ -421,7 +440,14 @@ static int GetFlagsOffset(MethodDef method, int index, Local local) {
421440
return -1;
422441
}
423442

424-
static Local GetFlagsLocal(MethodDef method, int index) {
443+
Local GetFlagsLocal(MethodDef method, int index) {
444+
if (isV51OrLater)
445+
return GetFlagsLocalNew(method, index);
446+
return GetFlagsLocalOld(method, index);
447+
}
448+
449+
// <= 5.0
450+
static Local GetFlagsLocalOld(MethodDef method, int index) {
425451
var instrs = method.Body.Instructions;
426452
if (index + 5 >= instrs.Count)
427453
return null;
@@ -441,6 +467,24 @@ static Local GetFlagsLocal(MethodDef method, int index) {
441467
return stloc.GetLocal(method.Body.Variables);
442468
}
443469

470+
// 5.1+
471+
// Uses different OpCodes
472+
static Local GetFlagsLocalNew(MethodDef method, int index) {
473+
var instrs = method.Body.Instructions;
474+
if (index + 5 >= instrs.Count)
475+
return null;
476+
if (instrs[index++].OpCode.Code != Code.And)
477+
return null;
478+
if (instrs[index++].OpCode.Code != Code.Ldc_I4_0)
479+
return null;
480+
if (instrs[index++].OpCode.Code != Code.Cgt_Un)
481+
return null;
482+
var stloc = instrs[index++];
483+
if (!stloc.IsStloc())
484+
return null;
485+
return stloc.GetLocal(method.Body.Variables);
486+
}
487+
444488
void Initialize() {
445489
reader = new BinaryReader(encryptedResource.GetResourceStream());
446490
short len = (short)(reader.ReadInt16() ^ s1);
@@ -592,6 +636,51 @@ EmbeddedResource FindResourceFromStringBuilder(MethodDef method) {
592636
return DotNetUtils.GetResource(module, sb.ToString()) as EmbeddedResource;
593637
}
594638

639+
bool FindShiftInts(MethodDef method, out List<int> bytes) {
640+
var instrs = method.Body.Instructions;
641+
var constantsReader = new EfConstantsReader(method);
642+
bytes = new List<int>(8);
643+
644+
for (int i = 0; i < instrs.Count - 4; i++) {
645+
if (bytes.Count >= 8)
646+
return true;
647+
648+
var ldloc1 = instrs[i];
649+
if (ldloc1.OpCode.Code != Code.Ldloc_1)
650+
continue;
651+
652+
var ldlocs = instrs[i + 1];
653+
if (ldlocs.OpCode.Code != Code.Ldloc_S)
654+
continue;
655+
656+
var maybe = instrs[i + 2];
657+
if (maybe.OpCode.Code == Code.Conv_U1) {
658+
var callvirt = instrs[i + 3];
659+
if (callvirt.OpCode.Code != Code.Callvirt)
660+
return false;
661+
662+
bytes.Add(0);
663+
continue;
664+
}
665+
var shr = instrs[i + 3];
666+
if (shr.OpCode.Code != Code.Shr)
667+
return false;
668+
669+
var convu1 = instrs[i + 4];
670+
if (convu1.OpCode.Code != Code.Conv_U1)
671+
return false;
672+
673+
int constant;
674+
int index = i + 2;
675+
if (!constantsReader.GetInt32(ref index, out constant))
676+
return false;
677+
678+
bytes.Add(constant);
679+
}
680+
681+
return false;
682+
}
683+
595684
static MethodDef FindInt64Method(MethodDef method) {
596685
foreach (var instr in method.Body.Instructions) {
597686
if (instr.OpCode.Code != Code.Call)
@@ -698,7 +787,7 @@ bool FindInts(int index) {
698787
break;
699788
}
700789
}
701-
done: ;
790+
done:
702791

703792
foreach (var val in fields.Values) {
704793
if (val == null)
@@ -711,6 +800,13 @@ bool FindInts(int index) {
711800
}
712801

713802
bool EmulateDynocode(InstructionEmulator emu, ref int index) {
803+
if (isV51OrLater)
804+
return EmulateDynocodeNew(emu, ref index);
805+
return EmulateDynocodeOld(emu, ref index);
806+
}
807+
808+
// <= 5.0
809+
bool EmulateDynocodeOld(InstructionEmulator emu, ref int index) {
714810
var instrs = stringMethod.Body.Instructions;
715811
var instr = instrs[index];
716812

@@ -770,6 +866,68 @@ bool EmulateDynocode(InstructionEmulator emu, ref int index) {
770866
return true;
771867
}
772868

869+
// 5.1+
870+
// the only changes are the indexes of ldloc and stfld
871+
bool EmulateDynocodeNew(InstructionEmulator emu, ref int index) {
872+
var instrs = stringMethod.Body.Instructions;
873+
var instr = instrs[index];
874+
875+
var ctor = instr.Operand as MethodDef;
876+
if (ctor == null || ctor.MethodSig.GetParamCount() != 1 || ctor.MethodSig.Params[0].ElementType != ElementType.I4)
877+
return false;
878+
879+
if (index + 4 >= instrs.Count)
880+
return false;
881+
var ldloc = instrs[index + 2];
882+
var stfld = instrs[index + 3];
883+
if (!ldloc.IsLdloc() || stfld.OpCode.Code != Code.Stfld)
884+
return false;
885+
var enumerableField = stfld.Operand as FieldDef;
886+
if (enumerableField == null)
887+
return false;
888+
889+
var initValue = emu.GetLocal(ldloc.GetLocal(stringMethod.Body.Variables)) as Int32Value;
890+
if (initValue == null || !initValue.AllBitsValid())
891+
return false;
892+
893+
int leaveIndex = FindLeave(instrs, index);
894+
if (leaveIndex < 0)
895+
return false;
896+
var afterLoop = instrs[leaveIndex].Operand as Instruction;
897+
if (afterLoop == null)
898+
return false;
899+
int newIndex = instrs.IndexOf(afterLoop);
900+
var loopLocal = GetDCLoopLocal(index, newIndex);
901+
if (loopLocal == null)
902+
return false;
903+
var initValue2 = emu.GetLocal(loopLocal) as Int32Value;
904+
if (initValue2 == null || !initValue2.AllBitsValid())
905+
return false;
906+
907+
int loopStart = GetIndexOfCall(instrs, index, leaveIndex, "System.Int32", "()");
908+
int loopEnd = GetIndexOfCall(instrs, loopStart, leaveIndex, "System.Boolean", "()");
909+
if (loopStart < 0 || loopEnd < 0)
910+
return false;
911+
loopStart++;
912+
loopEnd--;
913+
914+
dynocode.Initialize(module);
915+
var ctorArg = emu.Pop() as Int32Value;
916+
if (ctorArg == null || !ctorArg.AllBitsValid())
917+
return false;
918+
dynocode.CreateEnumerable(ctor, new object[] { ctorArg.Value });
919+
dynocode.WriteEnumerableField(enumerableField.MDToken.ToUInt32(), initValue.Value);
920+
dynocode.CreateEnumerator();
921+
foreach (var val in dynocode) {
922+
emu.Push(new Int32Value(val));
923+
for (int i = loopStart; i < loopEnd; i++)
924+
emu.Emulate(instrs[i]);
925+
}
926+
927+
index = newIndex - 1;
928+
return true;
929+
}
930+
773931
static int GetIndexOfCall(IList<Instruction> instrs, int startIndex, int endIndex, string returnType, string parameters) {
774932
if (startIndex < 0 || endIndex < 0)
775933
return -1;

de4dot.code/deobfuscators/Eazfuscator_NET/VersionDetector.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License
1919

2020
using System;
2121
using System.Collections.Generic;
22+
using dnlib.DotNet.Emit;
2223
using dnlib.DotNet;
2324
using de4dot.blocks;
2425

@@ -667,7 +668,7 @@ public string Detect() {
667668
(decryptStringMethod.Body.ExceptionHandlers.Count == 1 || decryptStringMethod.Body.ExceptionHandlers.Count == 2) &&
668669
new LocalTypes(decryptStringMethod).Exactly(locals33_149) &&
669670
CheckTypeFields2(fields33_149)) {
670-
return "3.3.149 - 3.4"; // 3.3.149+ (but not SL or CF)
671+
return "3.3.149 - 3.4"; // 3.3.149+ (but not SL or CF)
671672
}
672673

673674
/////////////////////////////////////////////////////////////////
@@ -818,6 +819,10 @@ public string Detect() {
818819
decryptStringMethod.Body.ExceptionHandlers.Count == 1 &&
819820
new LocalTypes(decryptStringMethod).All(locals50) &&
820821
CheckTypeFields2(fields50)) {
822+
foreach (var inst in stringDecrypter.Method.Body.Instructions) {
823+
if (inst.OpCode.Code == Code.Cgt_Un)
824+
return "5.1";
825+
}
821826
return "5.0";
822827
}
823828
}

0 commit comments

Comments
 (0)