diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj
index 7d714538..3fdfe8bb 100644
--- a/de4dot.code/de4dot.code.csproj
+++ b/de4dot.code/de4dot.code.csproj
@@ -69,6 +69,7 @@
+
diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/ArrayFinder.cs b/de4dot.code/deobfuscators/dotNET_Reactor/ArrayFinder.cs
new file mode 100644
index 00000000..68e6ae49
--- /dev/null
+++ b/de4dot.code/deobfuscators/dotNET_Reactor/ArrayFinder.cs
@@ -0,0 +1,146 @@
+/*
+ Copyright (C) 2011 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 Mono.Cecil.Cil;
+using de4dot.blocks;
+using de4dot.blocks.cflow;
+
+namespace de4dot.deobfuscators.dotNET_Reactor {
+ class ArrayFinder {
+ List arrays = new List();
+
+ public ArrayFinder(MethodDefinition method) {
+ init(method);
+ }
+
+ void init(MethodDefinition method) {
+ if (method.Body == null)
+ return;
+
+ foreach (var instr in method.Body.Instructions) {
+ if (instr.OpCode.Code != Code.Ldtoken)
+ continue;
+ var field = instr.Operand as FieldDefinition;
+ if (field == null)
+ continue;
+ arrays.Add(field.InitialValue);
+ }
+
+ var instructions = method.Body.Instructions;
+ for (int i = 1; i < instructions.Count; i++) {
+ var instr = instructions[i];
+ if (instr.OpCode.Code != Code.Newarr)
+ continue;
+ var ldci4 = instructions[i - 1];
+ if (!DotNetUtils.isLdcI4(ldci4))
+ continue;
+ int arraySize = DotNetUtils.getLdcI4Value(ldci4);
+ var ary = getInitializedArray(arraySize, method, ref i);
+ if (ary != null)
+ arrays.Add(ary);
+ }
+ }
+
+ public bool exists(byte[] array) {
+ foreach (var ary in arrays) {
+ if (isEqual(ary, array))
+ return true;
+ }
+ return false;
+ }
+
+ static bool isEqual(byte[] ary1, byte[] ary2) {
+ if (ary1.Length != ary2.Length)
+ return false;
+ for (int i = 0; i < ary1.Length; i++) {
+ if (ary1[i] != ary2[i])
+ return false;
+ }
+ return true;
+ }
+
+ public static byte[] getInitializedArray(MethodDefinition method, int arraySize) {
+ int newarrIndex = findNewarr(method, arraySize);
+ if (newarrIndex < 0)
+ return null;
+ return getInitializedArray(arraySize, method, ref newarrIndex);
+ }
+
+ public static byte[] getInitializedArray(int arraySize, MethodDefinition method, ref int newarrIndex) {
+ var resultValueArray = new Value[arraySize];
+
+ var emulator = new InstructionEmulator(method.HasThis, false, method.Parameters, method.Body.Variables);
+ var theArray = new UnknownValue();
+ emulator.push(theArray);
+
+ var instructions = method.Body.Instructions;
+ int i;
+ for (i = newarrIndex + 1; i < instructions.Count; i++) {
+ var instr = instructions[i];
+ if (instr.OpCode.FlowControl != FlowControl.Next)
+ break;
+ if (instr.OpCode.Code == Code.Newarr)
+ break;
+
+ if (instr.OpCode.Code == Code.Stelem_I1) {
+ var value = emulator.pop();
+ var index = emulator.pop() as Int32Value;
+ var array = emulator.pop();
+ if (ReferenceEquals(array, theArray) && index != null && index.allBitsValid()) {
+ if (0 <= index.value && index.value < resultValueArray.Length)
+ resultValueArray[index.value] = value;
+ }
+ }
+ else
+ emulator.emulate(instr);
+ }
+ newarrIndex = i;
+
+ byte[] resultArray = new byte[resultValueArray.Length];
+ for (i = 0; i < resultArray.Length; i++) {
+ var intValue = resultValueArray[i] as Int32Value;
+ if (intValue == null || !intValue.allBitsValid())
+ return null;
+ resultArray[i] = (byte)intValue.value;
+ }
+
+ return resultArray;
+ }
+
+ static int findNewarr(MethodDefinition method, int arraySize) {
+ var instructions = method.Body.Instructions;
+ for (int i = 0; i < instructions.Count; i++) {
+ var instr = instructions[i];
+ if (instr.OpCode.Code != Code.Newarr || i < 1)
+ continue;
+ var ldci4 = instructions[i - 1];
+ if (!DotNetUtils.isLdcI4(ldci4))
+ continue;
+ if (DotNetUtils.getLdcI4Value(ldci4) != arraySize)
+ continue;
+
+ return i;
+ }
+
+ return -1;
+ }
+ }
+}
diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/EncryptedResource.cs b/de4dot.code/deobfuscators/dotNET_Reactor/EncryptedResource.cs
index 3a67222e..6a2bdb50 100644
--- a/de4dot.code/deobfuscators/dotNET_Reactor/EncryptedResource.cs
+++ b/de4dot.code/deobfuscators/dotNET_Reactor/EncryptedResource.cs
@@ -22,9 +22,7 @@ using System.IO;
using System.Collections.Generic;
using System.Security.Cryptography;
using Mono.Cecil;
-using Mono.Cecil.Cil;
using de4dot.blocks;
-using de4dot.blocks.cflow;
namespace de4dot.deobfuscators.dotNET_Reactor {
class EncryptedResource {
@@ -98,10 +96,10 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
if (encryptedDataResource == null)
throw new ApplicationException("Could not find encrypted resource");
- key = initArray(resourceDecrypterMethod, 32);
+ key = ArrayFinder.getInitializedArray(resourceDecrypterMethod, 32);
if (key == null)
throw new ApplicationException("Could not find resource decrypter key");
- iv = initArray(resourceDecrypterMethod, 16);
+ iv = ArrayFinder.getInitializedArray(resourceDecrypterMethod, 16);
if (iv == null)
throw new ApplicationException("Could not find resource decrypter IV");
var publicKeyToken = module.Assembly.Name.PublicKeyToken;
@@ -120,67 +118,6 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
return null;
}
- static byte[] initArray(MethodDefinition method, int arraySize) {
- int newarrIndex = findNewarr(method, arraySize);
- if (newarrIndex < 0)
- return null;
-
- var resultValueArray = new Value[arraySize];
-
- var emulator = new InstructionEmulator(method.HasThis, false, method.Parameters, method.Body.Variables);
- var theArray = new UnknownValue();
- emulator.push(theArray);
-
- var instructions = method.Body.Instructions;
- for (int i = newarrIndex + 1; i < instructions.Count; i++) {
- var instr = instructions[i];
- if (instr.OpCode.FlowControl != FlowControl.Next)
- break;
- if (instr.OpCode.Code == Code.Newarr)
- break;
-
- if (instr.OpCode.Code == Code.Stelem_I1) {
- var value = emulator.pop();
- var index = emulator.pop() as Int32Value;
- var array = emulator.pop();
- if (ReferenceEquals(array, theArray) && index != null && index.allBitsValid()) {
- if (0 <= index.value && index.value < resultValueArray.Length)
- resultValueArray[index.value] = value;
- }
- }
- else
- emulator.emulate(instr);
- }
-
- byte[] resultArray = new byte[resultValueArray.Length];
- for (int i = 0; i < resultArray.Length; i++) {
- var intValue = resultValueArray[i] as Int32Value;
- if (intValue == null || !intValue.allBitsValid())
- return null;
- resultArray[i] = (byte)intValue.value;
- }
-
- return resultArray;
- }
-
- static int findNewarr(MethodDefinition method, int arraySize) {
- var instructions = method.Body.Instructions;
- for (int i = 0; i < instructions.Count; i++) {
- var instr = instructions[i];
- if (instr.OpCode.Code != Code.Newarr || i < 1)
- continue;
- var ldci4 = instructions[i - 1];
- if (!DotNetUtils.isLdcI4(ldci4))
- continue;
- if (DotNetUtils.getLdcI4Value(ldci4) != arraySize)
- continue;
-
- return i;
- }
-
- return -1;
- }
-
public byte[] decrypt() {
if (encryptedDataResource == null || key == null || iv == null)
throw new ApplicationException("Can't decrypt resource");