Detect if decrypter should skip before reading flag or vice versa

Seems like some versions of CryptoObfuscator skip the bytes before reading the
actual flag instead of the behaviour expected by de4dot currently.

Signed-off-by: angelsl <hidingfromhidden@gmail.com>
This commit is contained in:
angelsl 2015-08-21 15:57:44 +08:00
parent 39cf94964f
commit ffeb7c9472

View File

@ -38,6 +38,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
byte bitwiseNotEncryptedFlag; byte bitwiseNotEncryptedFlag;
FrameworkType frameworkType; FrameworkType frameworkType;
bool flipFlagsBits; bool flipFlagsBits;
bool skipBeforeFlag;
int skipBytes; int skipBytes;
public ResourceDecrypter(ModuleDefMD module, ISimpleDeobfuscator simpleDeobfuscator) { public ResourceDecrypter(ModuleDefMD module, ISimpleDeobfuscator simpleDeobfuscator) {
@ -179,10 +180,10 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
bitwiseNotEncryptedFlag = 4; bitwiseNotEncryptedFlag = 4;
} }
static bool CheckFlipBits(MethodDef method) { static bool CheckFlipBits(MethodDef method, out int index) {
int nots = 0; int nots = 0, i;
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) { for (i = 0; i < instrs.Count - 1; i++) {
var ldloc = instrs[i]; var ldloc = instrs[i];
if (!ldloc.IsLdloc()) if (!ldloc.IsLdloc())
continue; continue;
@ -193,7 +194,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
if (instrs[i + 1].OpCode.Code == Code.Not) if (instrs[i + 1].OpCode.Code == Code.Not)
nots++; nots++;
} }
index = i;
return (nots & 1) == 1; return (nots & 1) == 1;
} }
@ -223,8 +224,10 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
constants.Add(flagValue); constants.Add(flagValue);
} }
flipFlagsBits = CheckFlipBits(method); int notIndex, skipIndex;
skipBytes = GetHeaderSkipBytes(method); flipFlagsBits = CheckFlipBits(method, out notIndex);
skipBytes = GetHeaderSkipBytes(method, out skipIndex);
skipBeforeFlag = skipIndex < notIndex;
switch (frameworkType) { switch (frameworkType) {
case FrameworkType.Desktop: case FrameworkType.Desktop:
@ -259,7 +262,7 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
return false; return false;
} }
static int GetHeaderSkipBytes(MethodDef method) { static int GetHeaderSkipBytes(MethodDef method, out int index) {
var instrs = method.Body.Instructions; var instrs = method.Body.Instructions;
for (int i = 0; i < instrs.Count - 1; i++) { for (int i = 0; i < instrs.Count - 1; i++) {
var ldci4 = instrs[i]; var ldci4 = instrs[i];
@ -271,8 +274,10 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
var blt = instrs[i + 1]; var blt = instrs[i + 1];
if (blt.OpCode.Code != Code.Blt && blt.OpCode.Code != Code.Blt_S && blt.OpCode.Code != Code.Clt) if (blt.OpCode.Code != Code.Blt && blt.OpCode.Code != Code.Blt_S && blt.OpCode.Code != Code.Clt)
continue; continue;
index = i;
return loopCount - 1; return loopCount - 1;
} }
index = 0;
return 0; return 0;
} }
@ -312,15 +317,22 @@ namespace de4dot.code.deobfuscators.CryptoObfuscator {
} }
public byte[] Decrypt(Stream resourceStream) { public byte[] Decrypt(Stream resourceStream) {
byte flags = (byte)resourceStream.ReadByte();
if (flipFlagsBits)
flags = (byte)~flags;
Stream sourceStream = resourceStream; Stream sourceStream = resourceStream;
int sourceStreamOffset = 1; int sourceStreamOffset = 1;
bool didSomething = false; bool didSomething = false;
sourceStream.Position += skipBytes; if (skipBeforeFlag)
sourceStreamOffset += skipBytes; {
sourceStream.Position += skipBytes;
sourceStreamOffset += skipBytes;
}
byte flags = (byte)sourceStream.ReadByte();
if (flipFlagsBits)
flags = (byte)~flags;
if (!skipBeforeFlag) {
sourceStream.Position += skipBytes;
sourceStreamOffset += skipBytes;
}
byte allFlags = (byte)(desEncryptedFlag | deflatedFlag | bitwiseNotEncryptedFlag); byte allFlags = (byte)(desEncryptedFlag | deflatedFlag | bitwiseNotEncryptedFlag);
if ((flags & ~allFlags) != 0) if ((flags & ~allFlags) != 0)