diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj
index 8a368666..fa1a753f 100644
--- a/de4dot.code/de4dot.code.csproj
+++ b/de4dot.code/de4dot.code.csproj
@@ -116,7 +116,6 @@
-
@@ -142,10 +141,14 @@
+
+
+
+
diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/QuickLZ.cs b/de4dot.code/deobfuscators/QuickLZ.cs
similarity index 77%
rename from de4dot.code/deobfuscators/dotNET_Reactor/QuickLZ.cs
rename to de4dot.code/deobfuscators/QuickLZ.cs
index a54a12e3..4a594ad3 100644
--- a/de4dot.code/deobfuscators/dotNET_Reactor/QuickLZ.cs
+++ b/de4dot.code/deobfuscators/QuickLZ.cs
@@ -11,44 +11,21 @@
using System;
-namespace de4dot.code.deobfuscators.dotNET_Reactor {
- static class QuickLZ {
- static int sig = 0x5A4C4351; // "QCLZ"
-
- public static bool isCompressed(byte[] data) {
- if (data.Length < 4)
- return false;
- return BitConverter.ToInt32(data, 0) == sig;
- }
-
- static uint read32(byte[] data, int index) {
+namespace de4dot.code.deobfuscators {
+ class QuickLZBase {
+ protected static uint read32(byte[] data, int index) {
return BitConverter.ToUInt32(data, index);
}
// Can't use Array.Copy() when data overlaps so here's one that works
- static void copy(byte[] src, int srcIndex, byte[] dst, int dstIndex, int size) {
+ protected static void copy(byte[] src, int srcIndex, byte[] dst, int dstIndex, int size) {
for (int i = 0; i < size; i++)
dst[dstIndex++] = src[srcIndex++];
}
static int[] indexInc = new int[] { 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
- public static byte[] decompress(byte[] inData) {
- int mode = BitConverter.ToInt32(inData, 4);
- int compressedLength = BitConverter.ToInt32(inData, 8);
- int decompressedLength = BitConverter.ToInt32(inData, 12);
- bool isDataCompressed = BitConverter.ToInt32(inData, 16) == 1;
- int headerLength = 32;
- if (BitConverter.ToInt32(inData, 0) != sig || BitConverter.ToInt32(inData, compressedLength - 4) != sig)
- throw new ApplicationException("No QCLZ sig");
-
- byte[] outData = new byte[decompressedLength];
-
- if (!isDataCompressed) {
- copy(inData, headerLength, outData, 0, decompressedLength);
- return outData;
- }
-
- int inIndex = headerLength;
+ public static void decompress(byte[] inData, int inIndex, byte[] outData) {
+ int decompressedLength = outData.Length;
int outIndex = 0;
uint val1 = 1;
uint count;
@@ -89,18 +66,30 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor {
inIndex += 3;
}
else if ((val2 & 8) == 0) {
- size = (int)((val2 >> 4) & 0x07FF) + 3;
count = val2 >> 15;
+ if (count != 0) {
+ size = (int)((val2 >> 4) & 0x07FF) + 3;
+ inIndex += 4;
+ }
+ else {
+ size = (int)read32(inData, inIndex + 4);
+ count = read32(inData, inIndex + 8);
+ inIndex += 12;
+ }
copy(outData, (int)(outIndex - count), outData, outIndex, size);
outIndex += size;
- inIndex += 4;
}
else {
byte b = (byte)(val2 >> 16);
size = (int)(val2 >> 4) & 0x0FFF;
+ if (size == 0) {
+ size = (int)read32(inData, inIndex + 3);
+ inIndex += 7;
+ }
+ else
+ inIndex += 3;
for (int i = 0; i < size; i++)
outData[outIndex++] = b;
- inIndex += 3;
}
}
else {
@@ -121,7 +110,39 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor {
outData[outIndex++] = inData[inIndex++];
val1 >>= 1;
}
+ }
+ }
+ class QuickLZ : QuickLZBase {
+ static int DEFAULT_QCLZ_SIG = 0x5A4C4351; // "QCLZ"
+
+ public static bool isCompressed(byte[] data) {
+ if (data.Length < 4)
+ return false;
+ return BitConverter.ToInt32(data, 0) == DEFAULT_QCLZ_SIG;
+ }
+
+ public static byte[] decompress(byte[] inData) {
+ return decompress(inData, DEFAULT_QCLZ_SIG);
+ }
+
+ public static byte[] decompress(byte[] inData, int sig) {
+ int mode = BitConverter.ToInt32(inData, 4);
+ int compressedLength = BitConverter.ToInt32(inData, 8);
+ int decompressedLength = BitConverter.ToInt32(inData, 12);
+ bool isDataCompressed = BitConverter.ToInt32(inData, 16) == 1;
+ int headerLength = 32;
+ if (BitConverter.ToInt32(inData, 0) != sig || BitConverter.ToInt32(inData, compressedLength - 4) != sig)
+ throw new ApplicationException("No QCLZ sig");
+
+ byte[] outData = new byte[decompressedLength];
+
+ if (!isDataCompressed) {
+ copy(inData, headerLength, outData, 0, decompressedLength);
+ return outData;
+ }
+
+ decompress(inData, headerLength, outData);
return outData;
}
}
diff --git a/de4dot.code/deobfuscators/Spices_Net/Deobfuscator.cs b/de4dot.code/deobfuscators/Spices_Net/Deobfuscator.cs
new file mode 100644
index 00000000..96511b30
--- /dev/null
+++ b/de4dot.code/deobfuscators/Spices_Net/Deobfuscator.cs
@@ -0,0 +1,137 @@
+/*
+ Copyright (C) 2011-2012 de4dot@gmail.com
+
+ This file is part of de4dot.
+
+ de4dot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ de4dot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with de4dot. If not, see .
+*/
+
+using System.Collections.Generic;
+using Mono.Cecil;
+using de4dot.blocks.cflow;
+
+namespace de4dot.code.deobfuscators.Spices_Net {
+ public class DeobfuscatorInfo : DeobfuscatorInfoBase {
+ public const string THE_NAME = "Spices.Net";
+ public const string THE_TYPE = "sn";
+
+ public DeobfuscatorInfo()
+ : base() {
+ }
+
+ public override string Name {
+ get { return THE_NAME; }
+ }
+
+ public override string Type {
+ get { return THE_TYPE; }
+ }
+
+ public override IDeobfuscator createDeobfuscator() {
+ return new Deobfuscator(new Deobfuscator.Options {
+ ValidNameRegex = validNameRegex.get(),
+ });
+ }
+
+ protected override IEnumerable