Merge pull request #111 from angelsl/master

CryptoObfuscator: Detect if decrypter should skip before reading flag or vice versa
This commit is contained in:
0xd4d 2015-08-29 12:24:29 +02:00
commit 21318d2161

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,21 +180,22 @@ 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++) { index = -1;
for (i = 0; i < instrs.Count - 1; i++) {
var ldloc = instrs[i]; var ldloc = instrs[i];
if (!ldloc.IsLdloc()) if (!ldloc.IsLdloc())
continue; continue;
var local = ldloc.GetLocal(method.Body.Variables); var local = ldloc.GetLocal(method.Body.Variables);
if (local == null || local.Type.GetElementType().GetPrimitiveSize() < 0) if (local == null || local.Type.GetElementType().GetPrimitiveSize() < 0)
continue; continue;
if (instrs[i + 1].OpCode.Code == Code.Not) {
if (instrs[i + 1].OpCode.Code == Code.Not)
nots++; nots++;
index = i + 1;
}
} }
return (nots & 1) == 1; return (nots & 1) == 1;
} }
@ -223,8 +225,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 +263,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 +275,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 +318,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)