diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj
index 4d7cddd4..2ce039ec 100644
--- a/de4dot.code/de4dot.code.csproj
+++ b/de4dot.code/de4dot.code.csproj
@@ -91,6 +91,7 @@
+
diff --git a/de4dot.code/deobfuscators/DeobfuscatorBase.cs b/de4dot.code/deobfuscators/DeobfuscatorBase.cs
index 4b44e47e..69288f19 100644
--- a/de4dot.code/deobfuscators/DeobfuscatorBase.cs
+++ b/de4dot.code/deobfuscators/DeobfuscatorBase.cs
@@ -77,7 +77,7 @@ namespace de4dot.deobfuscators {
}
public Func IsValidName {
- get { return (name) => optionsBase.ValidNameRegex.isMatch(name); }
+ get { return (name) => checkValidName(name); }
}
public DeobfuscatorBase(OptionsBase optionsBase) {
@@ -94,6 +94,10 @@ namespace de4dot.deobfuscators {
this.module = module;
}
+ protected virtual bool checkValidName(string name) {
+ return optionsBase.ValidNameRegex.isMatch(name);
+ }
+
public virtual int earlyDetect() {
return 0;
}
diff --git a/de4dot.code/deobfuscators/RandomNameChecker.cs b/de4dot.code/deobfuscators/RandomNameChecker.cs
new file mode 100644
index 00000000..2f42c19e
--- /dev/null
+++ b/de4dot.code/deobfuscators/RandomNameChecker.cs
@@ -0,0 +1,233 @@
+/*
+ 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 System.Text;
+using System.Text.RegularExpressions;
+
+namespace de4dot.deobfuscators {
+ static class RandomNameChecker {
+ static Regex noUpper = new Regex(@"^[^A-Z]+$");
+ static Regex allUpper = new Regex(@"^[A-Z]+$");
+
+ public static bool isNonRandom(string name) {
+ if (name.Length < 5)
+ return true;
+ if (noUpper.IsMatch(name))
+ return true;
+ if (allUpper.IsMatch(name))
+ return true;
+
+ for (int i = 0; i < name.Length - 1; i++) {
+ if (isDigit(name[i]))
+ return false;
+ if (i > 0 && isUpper(name[i]) && isUpper(name[i - 1]))
+ return false;
+ }
+
+ var words = getCamelWords(name);
+ int vowels = 0;
+ foreach (var word in words) {
+ if (word.Length > 1 && hasVowel(word))
+ vowels++;
+ }
+ switch (words.Count) {
+ case 1:
+ return vowels == words.Count;
+ case 2:
+ case 3:
+ return vowels >= 1;
+ case 4:
+ case 5:
+ return vowels >= 2;
+ case 6:
+ return vowels >= 3;
+ case 7:
+ return vowels >= 4;
+ default:
+ return vowels >= words.Count - 4;
+ }
+ }
+
+ static bool hasVowel(string s) {
+ foreach (var c in s) {
+ switch (c) {
+ case 'A':
+ case 'a':
+ case 'E':
+ case 'e':
+ case 'I':
+ case 'i':
+ case 'O':
+ case 'o':
+ case 'U':
+ case 'u':
+ case 'Y':
+ case 'y':
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static List getCamelWords(string name) {
+ var words = new List();
+ var sb = new StringBuilder();
+
+ for (int i = 0; i < name.Length; i++) {
+ char c = name[i];
+ if (isUpper(c)) {
+ if (sb.Length > 0)
+ words.Add(sb.ToString());
+ sb.Length = 0;
+ }
+ sb.Append(c);
+ }
+ if (sb.Length > 0)
+ words.Add(sb.ToString());
+
+ return words;
+ }
+
+ // Returns true if random, false if unknown
+ public static bool isRandom(string name) {
+ int len = name.Length;
+ if (len < 5)
+ return false;
+
+ var typeWords = getTypeWords(name);
+
+ if (countNumbers(typeWords, 2))
+ return true;
+
+ int lower, upper, digits;
+ countTypeWords(typeWords, out lower, out upper, out digits);
+ if (upper >= 3)
+ return true;
+ bool hasTwoUpperWords = upper == 2;
+
+ foreach (var word in typeWords) {
+ if (word.Length > 1 && isDigit(word[0]))
+ return true;
+ }
+
+ // Check for: lower, digit, lower
+ for (int i = 2; i < typeWords.Count; i++) {
+ if (isDigit(typeWords[i - 1][0]) && isLower(typeWords[i - 2][0]) && isLower(typeWords[i][0]))
+ return true;
+ }
+
+ if (hasTwoUpperWords && hasDigit(name))
+ return true;
+
+ // Check if it ends in lower, upper, digit
+ if (isLower(name[len - 3]) && isUpper(name[len - 2]) && isDigit(name[len - 1]))
+ return true;
+
+ return false;
+ }
+
+ static bool hasDigit(string s) {
+ foreach (var c in s) {
+ if (isDigit(c))
+ return true;
+ }
+ return false;
+ }
+
+ static List getTypeWords(string s) {
+ var words = new List();
+ var sb = new StringBuilder();
+
+ for (int i = 0; i < s.Length; ) {
+ if (isDigit(s[i])) {
+ sb.Length = 0;
+ while (i < s.Length && isDigit(s[i]))
+ sb.Append(s[i++]);
+ words.Add(sb.ToString());
+ }
+ else if (isUpper(s[i])) {
+ sb.Length = 0;
+ while (i < s.Length && isUpper(s[i]))
+ sb.Append(s[i++]);
+ words.Add(sb.ToString());
+ }
+ else if (isLower(s[i])) {
+ sb.Length = 0;
+ while (i < s.Length && isLower(s[i]))
+ sb.Append(s[i++]);
+ words.Add(sb.ToString());
+ }
+ else {
+ sb.Length = 0;
+ while (i < s.Length) {
+ if (isDigit(s[i]) || isUpper(s[i]) || isLower(s[i]))
+ break;
+ sb.Append(s[i++]);
+ }
+ words.Add(sb.ToString());
+ }
+ }
+
+ return words;
+ }
+
+ static bool countNumbers(List words, int numbers) {
+ int num = 0;
+ foreach (var word in words) {
+ if (string.IsNullOrEmpty(word))
+ continue;
+ if (isDigit(word[0]) && ++num >= numbers)
+ return true;
+ }
+ return false;
+ }
+
+ // 2+ chars only
+ static void countTypeWords(List words, out int lower, out int upper, out int digits) {
+ lower = 0;
+ upper = 0;
+ digits = 0;
+
+ foreach (var word in words) {
+ if (word.Length <= 1)
+ continue;
+ char c = word[0];
+ if (isDigit(c))
+ digits++;
+ else if (isLower(c))
+ lower++;
+ else if (isUpper(c))
+ upper++;
+ }
+ }
+
+ static bool isLower(char c) {
+ return 'a' <= c && c <= 'z';
+ }
+
+ static bool isUpper(char c) {
+ return 'A' <= c && c <= 'Z';
+ }
+
+ static bool isDigit(char c) {
+ return '0' <= c && c <= '9';
+ }
+ }
+}
diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/Deobfuscator.cs b/de4dot.code/deobfuscators/dotNET_Reactor/Deobfuscator.cs
index 52a2a904..9ee8ed36 100644
--- a/de4dot.code/deobfuscators/dotNET_Reactor/Deobfuscator.cs
+++ b/de4dot.code/deobfuscators/dotNET_Reactor/Deobfuscator.cs
@@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
+using System.Text.RegularExpressions;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.MyStuff;
@@ -27,7 +28,7 @@ using de4dot.blocks;
namespace de4dot.deobfuscators.dotNET_Reactor {
class DeobfuscatorInfo : DeobfuscatorInfoBase {
public const string THE_NAME = ".NET Reactor";
- const string DEFAULT_REGEX = @"!^[a-zA-Z0-9]{6,}(?:`\d+)?$&" + DeobfuscatorBase.DEFAULT_VALID_NAME_REGEX;
+ const string DEFAULT_REGEX = DeobfuscatorBase.DEFAULT_VALID_NAME_REGEX;
BoolOption decryptMethods;
BoolOption decryptBools;
BoolOption restoreTypes;
@@ -139,6 +140,18 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
base.init(module);
}
+ static Regex isRandomNameRegex1 = new Regex(@"^[a-zA-Z0-9]{9,11}$"); // methods, fields, props, events
+ static Regex isRandomNameRegex2 = new Regex(@"^[a-zA-Z0-9]{18,19}(?:`\d+)?$"); // types, namespaces
+ protected override bool checkValidName(string name) {
+ if (isRandomNameRegex1.IsMatch(name) || isRandomNameRegex2.IsMatch(name)) {
+ if (RandomNameChecker.isRandom(name))
+ return false;
+ if (!RandomNameChecker.isNonRandom(name))
+ return false;
+ }
+ return base.checkValidName(name);
+ }
+
protected override int detectInternal() {
int val = 0;