diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj
index bc39df46..de4514e0 100644
--- a/de4dot.code/de4dot.code.csproj
+++ b/de4dot.code/de4dot.code.csproj
@@ -107,6 +107,11 @@
+
+
+
+
+
diff --git a/de4dot.code/deobfuscators/CodeWall/Deobfuscator.cs b/de4dot.code/deobfuscators/CodeWall/Deobfuscator.cs
new file mode 100644
index 00000000..e02adf51
--- /dev/null
+++ b/de4dot.code/deobfuscators/CodeWall/Deobfuscator.cs
@@ -0,0 +1,136 @@
+/*
+ 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;
+using System.Collections.Generic;
+using Mono.Cecil;
+using Mono.MyStuff;
+using de4dot.blocks;
+using de4dot.PE;
+
+namespace de4dot.code.deobfuscators.CodeWall {
+ public class DeobfuscatorInfo : DeobfuscatorInfoBase {
+ public const string THE_NAME = "CodeWall";
+ public const string THE_TYPE = "cw";
+
+ 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 getOptionsInternal() {
+ return new List () {
+ };
+ }
+ }
+
+ class Deobfuscator : DeobfuscatorBase {
+ Options options;
+ MethodsDecrypter methodsDecrypter;
+
+ internal class Options : OptionsBase {
+ }
+
+ public override string Type {
+ get { return DeobfuscatorInfo.THE_TYPE; }
+ }
+
+ public override string TypeLong {
+ get { return DeobfuscatorInfo.THE_NAME; }
+ }
+
+ public override string Name {
+ get { return DeobfuscatorInfo.THE_NAME; }
+ }
+
+ public Deobfuscator(Options options)
+ : base(options) {
+ this.options = options;
+ }
+
+ protected override int detectInternal() {
+ int val = 0;
+
+ int sum = toInt32(methodsDecrypter.Detected);
+ if (sum > 0)
+ val += 100 + 10 * (sum - 1);
+
+ return val;
+ }
+
+ protected override void scanForObfuscator() {
+ methodsDecrypter = new MethodsDecrypter(module);
+ methodsDecrypter.find();
+ }
+
+ public override bool getDecryptedModule(ref byte[] newFileData, ref DumpedMethods dumpedMethods) {
+ if (!methodsDecrypter.Detected)
+ return false;
+
+ byte[] fileData = ModuleBytes ?? DeobUtils.readModule(module);
+ var peImage = new PeImage(fileData);
+
+ if (!methodsDecrypter.decrypt(peImage, ref dumpedMethods))
+ return false;
+
+ newFileData = fileData;
+ return true;
+ }
+
+ public override IDeobfuscator moduleReloaded(ModuleDefinition module) {
+ var newOne = new Deobfuscator(options);
+ newOne.setModule(module);
+ newOne.methodsDecrypter = new MethodsDecrypter(module, methodsDecrypter);
+ return newOne;
+ }
+
+ public override void deobfuscateBegin() {
+ base.deobfuscateBegin();
+ addAssemblyReferenceToBeRemoved(methodsDecrypter.AssemblyNameReference, "Obfuscator decrypter DLL reference");
+ }
+
+ public override void deobfuscateMethodEnd(Blocks blocks) {
+ methodsDecrypter.deobfuscate(blocks);
+ base.deobfuscateMethodEnd(blocks);
+ }
+
+ public override void deobfuscateEnd() {
+ base.deobfuscateEnd();
+ }
+
+ public override IEnumerable getStringDecrypterMethods() {
+ var list = new List();
+ //TODO:
+ return list;
+ }
+ }
+}
diff --git a/de4dot.code/deobfuscators/CodeWall/KeyGenerator.cs b/de4dot.code/deobfuscators/CodeWall/KeyGenerator.cs
new file mode 100644
index 00000000..e7830cd0
--- /dev/null
+++ b/de4dot.code/deobfuscators/CodeWall/KeyGenerator.cs
@@ -0,0 +1,44 @@
+/*
+ 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;
+using de4dot.code.deobfuscators.CodeWall.randomc;
+
+namespace de4dot.code.deobfuscators.CodeWall {
+ class KeyGenerator {
+ CRandomMersenne mersenne;
+ CRandomMother mother;
+
+ public KeyGenerator(int seed) {
+ mersenne = new CRandomMersenne(seed);
+ mother = new CRandomMother(seed);
+ }
+
+ uint random() {
+ return (mersenne.BRandom() >> 1) ^ (uint)Math.Abs((int)(mother.Random() * int.MinValue));
+ }
+
+ public byte[] generate(int size) {
+ var key = new byte[size];
+ for (int i = 0; i < size; i++)
+ key[i] = (byte)random();
+ return key;
+ }
+ }
+}
diff --git a/de4dot.code/deobfuscators/CodeWall/MethodsDecrypter.cs b/de4dot.code/deobfuscators/CodeWall/MethodsDecrypter.cs
new file mode 100644
index 00000000..cfdde32b
--- /dev/null
+++ b/de4dot.code/deobfuscators/CodeWall/MethodsDecrypter.cs
@@ -0,0 +1,167 @@
+/*
+ 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;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.MyStuff;
+using de4dot.PE;
+using de4dot.blocks;
+
+namespace de4dot.code.deobfuscators.CodeWall {
+ class MethodsDecrypter {
+ static readonly byte[] newCodeHeader = new byte[6] { 0x2B, 4, 0, 0, 0, 0 };
+ static readonly byte[] decryptKey = new byte[10] { 0x8D, 0xB5, 0x2C, 0x3A, 0x1F, 0xC7, 0x31, 0xC3, 0xCD, 0x47 };
+
+ ModuleDefinition module;
+ MethodReference initMethod;
+
+ public bool Detected {
+ get { return initMethod != null; }
+ }
+
+ public AssemblyNameReference AssemblyNameReference {
+ get { return initMethod == null ? null : (AssemblyNameReference)initMethod.DeclaringType.Scope; }
+ }
+
+ public MethodsDecrypter(ModuleDefinition module) {
+ this.module = module;
+ }
+
+ public MethodsDecrypter(ModuleDefinition module, MethodsDecrypter oldOne) {
+ this.module = module;
+ initMethod = lookup(oldOne.initMethod, "Could not find initMethod");
+ }
+
+ T lookup(T def, string errorMessage) where T : MemberReference {
+ return DeobUtils.lookup(module, def, errorMessage);
+ }
+
+ public void find() {
+ foreach (var cctor in DeobUtils.getInitCctors(module, 3)) {
+ if (checkCctor(cctor))
+ return;
+ }
+ }
+
+ bool checkCctor(MethodDefinition method) {
+ if (method == null || method.Body == null)
+ return false;
+
+ foreach (var instr in method.Body.Instructions) {
+ if (instr.OpCode.Code != Code.Call)
+ continue;
+ var calledMethod = instr.Operand as MethodReference;
+ if (calledMethod == null)
+ continue;
+ if (calledMethod.DeclaringType.Scope == module)
+ return false;
+ if (calledMethod.FullName != "System.Void Q::X()")
+ return false;
+
+ initMethod = calledMethod;
+ return true;
+ }
+ return false;
+ }
+
+ public bool decrypt(PeImage peImage, ref DumpedMethods dumpedMethods) {
+ dumpedMethods = new DumpedMethods();
+
+ bool decrypted = false;
+
+ var metadataTables = peImage.Cor20Header.createMetadataTables();
+ var methodDef = metadataTables.getMetadataType(MetadataIndex.iMethodDef);
+ uint methodDefOffset = methodDef.fileOffset;
+ for (int i = 0; i < methodDef.rows; i++, methodDefOffset += methodDef.totalSize) {
+ uint bodyRva = peImage.offsetReadUInt32(methodDefOffset);
+ if (bodyRva == 0)
+ continue;
+ uint bodyOffset = peImage.rvaToOffset(bodyRva);
+
+ var dm = new DumpedMethod();
+ dm.token = (uint)(0x06000001 + i);
+
+ byte[] code, extraSections;
+ peImage.Reader.BaseStream.Position = bodyOffset;
+ var mbHeader = MethodBodyParser.parseMethodBody(peImage.Reader, out code, out extraSections);
+
+ if (code.Length < 6 || code[0] != 0x2A || code[1] != 0x2A)
+ continue;
+ dm.code = code;
+ dm.extraSections = extraSections;
+
+ int seed = BitConverter.ToInt32(code, 2);
+ Array.Copy(newCodeHeader, code, newCodeHeader.Length);
+ if (seed == 0)
+ decrypt(code);
+ else
+ decrypt(code, seed);
+
+ dm.mdImplFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[1].offset);
+ dm.mdFlags = peImage.offsetReadUInt16(methodDefOffset + (uint)methodDef.fields[2].offset);
+ dm.mdName = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[3].offset, methodDef.fields[3].size);
+ dm.mdSignature = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[4].offset, methodDef.fields[4].size);
+ dm.mdParamList = peImage.offsetRead(methodDefOffset + (uint)methodDef.fields[5].offset, methodDef.fields[5].size);
+
+ dm.mhFlags = mbHeader.flags;
+ dm.mhMaxStack = mbHeader.maxStack;
+ dm.mhCodeSize = (uint)dm.code.Length;
+ dm.mhLocalVarSigTok = mbHeader.localVarSigTok;
+
+ dumpedMethods.add(dm);
+ decrypted = true;
+ }
+
+ return decrypted;
+ }
+
+ void decrypt(byte[] data) {
+ for (int i = 6; i < data.Length; i++)
+ data[i] ^= decryptKey[i % decryptKey.Length];
+ }
+
+ void decrypt(byte[] data, int seed) {
+ var key = new KeyGenerator(seed).generate(data.Length);
+ for (int i = 6; i < data.Length; i++)
+ data[i] ^= key[i];
+ }
+
+ public void deobfuscate(Blocks blocks) {
+ if (initMethod == null)
+ return;
+ if (blocks.Method.Name != ".cctor")
+ return;
+
+ foreach (var block in blocks.MethodBlocks.getAllBlocks()) {
+ var instrs = block.Instructions;
+ for (int i = 0; i < instrs.Count; i++) {
+ var instr = instrs[i];
+ if (instr.OpCode.Code != Code.Call)
+ continue;
+ var calledMethod = instr.Operand as MethodReference;
+ if (!MemberReferenceHelper.compareMethodReferenceAndDeclaringType(calledMethod, initMethod))
+ continue;
+ block.remove(i, 1);
+ i--;
+ }
+ }
+ }
+ }
+}
diff --git a/de4dot.code/deobfuscators/CodeWall/randomc/CRandomMersenne.cs b/de4dot.code/deobfuscators/CodeWall/randomc/CRandomMersenne.cs
new file mode 100644
index 00000000..7e6107c7
--- /dev/null
+++ b/de4dot.code/deobfuscators/CodeWall/randomc/CRandomMersenne.cs
@@ -0,0 +1,103 @@
+/************************** mersenne.cpp **********************************
+* Author: Agner Fog
+* Date created: 2001
+* Last modified: 2008-11-16
+* Project: randomc.h
+* Platform: Any C++
+* Description:
+* Random Number generator of type 'Mersenne Twister'
+*
+* This random number generator is described in the article by
+* M. Matsumoto & T. Nishimura, in:
+* ACM Transactions on Modeling and Computer Simulation,
+* vol. 8, no. 1, 1998, pp. 3-30.
+* Details on the initialization scheme can be found at
+* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+*
+* Further documentation:
+* The file ran-instructions.pdf contains further documentation and
+* instructions.
+*
+* Copyright 2001-2008 by Agner Fog.
+* GNU General Public License http://www.gnu.org/licenses/gpl.html
+*******************************************************************************/
+
+// Only the methods I need have been ported to C#...
+
+namespace de4dot.code.deobfuscators.CodeWall.randomc {
+ class CRandomMersenne {
+ const int MERS_N = 624;
+ const int MERS_M = 397;
+ const int MERS_R = 31;
+ const int MERS_U = 11;
+ const int MERS_S = 7;
+ const int MERS_T = 15;
+ const int MERS_L = 18;
+ const uint MERS_A = 0x9908B0DF;
+ const uint MERS_B = 0x9D2C5680;
+ const uint MERS_C = 0xEFC60000;
+
+ uint[] mt = new uint[MERS_N]; // State vector
+ int mti; // Index into mt
+
+ public CRandomMersenne() {
+ }
+
+ public CRandomMersenne(int seed) {
+ RandomInit(seed);
+ }
+
+ void Init0(int seed) {
+ // Seed generator
+ const uint factor = 1812433253;
+ mt[0] = (uint)seed;
+ for (mti = 1; mti < MERS_N; mti++) {
+ mt[mti] = (factor * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + (uint)mti);
+ }
+ }
+
+ public void RandomInit(int seed) {
+ // Initialize and seed
+ Init0(seed);
+
+ // Randomize some more
+ for (int i = 0; i < 37; i++) BRandom();
+ }
+
+ static uint[] mag01 = new uint[2] { 0, MERS_A };
+ public uint BRandom() {
+ // Generate 32 random bits
+ uint y;
+
+ if (mti >= MERS_N) {
+ // Generate MERS_N words at one time
+ const uint LOWER_MASK = (1U << MERS_R) - 1; // Lower MERS_R bits
+ const uint UPPER_MASK = 0xFFFFFFFF << MERS_R; // Upper (32 - MERS_R) bits
+
+ int kk;
+ for (kk = 0; kk < MERS_N - MERS_M; kk++) {
+ y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
+ mt[kk] = mt[kk + MERS_M] ^ (y >> 1) ^ mag01[y & 1];
+ }
+
+ for (; kk < MERS_N - 1; kk++) {
+ y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
+ mt[kk] = mt[kk + (MERS_M - MERS_N)] ^ (y >> 1) ^ mag01[y & 1];
+ }
+
+ y = (mt[MERS_N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
+ mt[MERS_N - 1] = mt[MERS_M - 1] ^ (y >> 1) ^ mag01[y & 1];
+ mti = 0;
+ }
+ y = mt[mti++];
+
+ // Tempering (May be omitted):
+ y ^= y >> MERS_U;
+ y ^= (y << MERS_S) & MERS_B;
+ y ^= (y << MERS_T) & MERS_C;
+ y ^= y >> MERS_L;
+
+ return y;
+ }
+ }
+}
diff --git a/de4dot.code/deobfuscators/CodeWall/randomc/CRandomMother.cs b/de4dot.code/deobfuscators/CodeWall/randomc/CRandomMother.cs
new file mode 100644
index 00000000..11dbcaec
--- /dev/null
+++ b/de4dot.code/deobfuscators/CodeWall/randomc/CRandomMother.cs
@@ -0,0 +1,67 @@
+/************************** mother.cpp ************************************
+* Author: Agner Fog
+* Date created: 1999
+* Last modified: 2008-11-16
+* Project: randomc.h
+* Platform: This implementation uses 64-bit integers for intermediate calculations.
+* Works only on compilers that support 64-bit integers.
+* Description:
+* Random Number generator of type 'Mother-Of-All generator'.
+*
+* This is a multiply-with-carry type of random number generator
+* invented by George Marsaglia. The algorithm is:
+* S = 2111111111*X[n-4] + 1492*X[n-3] + 1776*X[n-2] + 5115*X[n-1] + C
+* X[n] = S modulo 2^32
+* C = floor(S / 2^32)
+*
+* Further documentation:
+* The file ran-instructions.pdf contains further documentation and
+* instructions.
+*
+* Copyright 1999-2008 by Agner Fog.
+* GNU General Public License http://www.gnu.org/licenses/gpl.html
+******************************************************************************/
+
+// Only the methods I need have been ported to C#...
+
+namespace de4dot.code.deobfuscators.CodeWall.randomc {
+ class CRandomMother {
+ uint[] x = new uint[5]; // History buffer
+
+ public CRandomMother(int seed) {
+ RandomInit(seed);
+ }
+
+ // this function initializes the random number generator:
+ public void RandomInit(int seed) {
+ int i;
+ uint s = (uint)seed;
+ // make random numbers and put them into the buffer
+ for (i = 0; i < 5; i++) {
+ s = s * 29943829 - 1;
+ x[i] = s;
+ }
+ // randomize some more
+ for (i = 0; i < 19; i++) BRandom();
+ }
+
+ // Output random bits
+ public uint BRandom() {
+ ulong sum;
+ sum = (ulong)2111111111UL * (ulong)x[3] +
+ (ulong)1492 * (ulong)(x[2]) +
+ (ulong)1776 * (ulong)(x[1]) +
+ (ulong)5115 * (ulong)(x[0]) +
+ (ulong)x[4];
+ x[3] = x[2]; x[2] = x[1]; x[1] = x[0];
+ x[4] = (uint)(sum >> 32); // Carry
+ x[0] = (uint)sum; // Low 32 bits of sum
+ return x[0];
+ }
+
+ // returns a random number between 0 and 1:
+ public double Random() {
+ return (double)BRandom() * (1.0/(65536.0*65536.0));
+ }
+ }
+}
diff --git a/de4dot.cui/Program.cs b/de4dot.cui/Program.cs
index a3a5f5ac..6fca2285 100644
--- a/de4dot.cui/Program.cs
+++ b/de4dot.cui/Program.cs
@@ -40,6 +40,7 @@ namespace de4dot.cui {
new de4dot.code.deobfuscators.Babel_NET.DeobfuscatorInfo(),
new de4dot.code.deobfuscators.CliSecure.DeobfuscatorInfo(),
new de4dot.code.deobfuscators.CodeVeil.DeobfuscatorInfo(),
+ new de4dot.code.deobfuscators.CodeWall.DeobfuscatorInfo(),
new de4dot.code.deobfuscators.CryptoObfuscator.DeobfuscatorInfo(),
new de4dot.code.deobfuscators.DeepSea.DeobfuscatorInfo(),
new de4dot.code.deobfuscators.Dotfuscator.DeobfuscatorInfo(),