try fix long path error
This commit is contained in:
parent
940b4bc791
commit
f86e301a1b
@ -35,6 +35,8 @@ namespace winPEAS.Checks
|
||||
public static string PaintActiveUsersNoAdministrator = "";
|
||||
public static string PaintDisabledUsers = "";
|
||||
public static string PaintDisabledUsersNoAdministrator = "";
|
||||
public static bool is_long_path = false;
|
||||
public static bool warning_is_long_path = false;
|
||||
//static string paint_lockoutUsers = "";
|
||||
public static string PaintAdminUsers = "";
|
||||
public static YamlConfig YamlConfig;
|
||||
@ -206,6 +208,8 @@ namespace winPEAS.Checks
|
||||
CheckRegANSI();
|
||||
}
|
||||
|
||||
CheckLongPath();
|
||||
|
||||
Beaprint.PrintInit();
|
||||
|
||||
CheckRunner.Run(CreateDynamicLists, IsDebug);
|
||||
@ -404,6 +408,24 @@ namespace winPEAS.Checks
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckLongPath()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (RegistryHelper.GetRegValue("HKLM", @"SYSTEM\CurrentControlSet\Control\FileSystem", "LongPathsEnabled") != "1")
|
||||
{
|
||||
System.Console.WriteLine(@"Long paths are disabled, so the maximum length of a path supported is 260chars(this may cause false negatives when looking for files). If you are admin, you can enable it with 'REG ADD HKLM\SYSTEM\CurrentControlSet\Control\FileSystem /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD");
|
||||
is_long_path = false;
|
||||
}
|
||||
else
|
||||
is_long_path = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Beaprint.GrayPrint("Error while checking LongPathsEnabled registry: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void WaitInput()
|
||||
{
|
||||
Console.Write("\n -- Press a key to continue... ");
|
||||
|
@ -1,89 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Search;
|
||||
using static winPEAS.Helpers.YamlConfig.YamlConfig.SearchParameters;
|
||||
|
||||
namespace winPEAS.Checks
|
||||
{
|
||||
|
||||
internal class FileAnalysis : ISystemCheck
|
||||
{
|
||||
private const int ListFileLimit = 70;
|
||||
|
||||
public void PrintInfo(bool isDebug)
|
||||
{
|
||||
Beaprint.GreatPrint("File Analysis");
|
||||
|
||||
new List<Action>
|
||||
{
|
||||
PrintYAMLSearchFiles,
|
||||
PrintYAMLRegexesSearchFiles
|
||||
}.ForEach(action => CheckRunner.Run(action, isDebug));
|
||||
}
|
||||
|
||||
private static List<CustomFileInfo> InitializeFileSearch(bool useProgramFiles=true)
|
||||
{
|
||||
var files = new List<CustomFileInfo>();
|
||||
var systemDrive = $"{SearchHelper.SystemDrive}\\";
|
||||
|
||||
List<string> directories = new List<string>()
|
||||
{
|
||||
@$"{systemDrive}inetpub",
|
||||
@$"{systemDrive}usr\etc\snmp",
|
||||
@$"{systemDrive}windows\temp",
|
||||
@$"{systemDrive}xampp",
|
||||
};
|
||||
|
||||
List<string> wildcardDirectories = new List<string>()
|
||||
{
|
||||
"apache*",
|
||||
"tomcat*",
|
||||
};
|
||||
|
||||
foreach (var wildcardDirectory in wildcardDirectories)
|
||||
{
|
||||
directories.AddRange(Directory.GetDirectories(systemDrive, wildcardDirectory, SearchOption.TopDirectoryOnly));
|
||||
}
|
||||
|
||||
foreach (var directory in directories)
|
||||
{
|
||||
files.AddRange(SearchHelper.GetFilesFast(directory, "*", isFoldersIncluded: true));
|
||||
}
|
||||
|
||||
files.AddRange(SearchHelper.RootDirUsers);
|
||||
// files.AddRange(SearchHelper.RootDirCurrentUser); // not needed, it's contained within RootDirUsers
|
||||
files.AddRange(SearchHelper.DocumentsAndSettings);
|
||||
files.AddRange(SearchHelper.GroupPolicyHistory); // TODO maybe not needed here
|
||||
if (useProgramFiles)
|
||||
{
|
||||
files.AddRange(SearchHelper.ProgramFiles);
|
||||
files.AddRange(SearchHelper.ProgramFilesX86);
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
private static bool[] Search(List<CustomFileInfo> files, string fileName, FileSettings fileSettings, ref int resultsCount, string searchName, bool somethingFound)
|
||||
{
|
||||
bool isRegexSearch = fileName.Contains("*");
|
||||
bool isFolder = fileSettings.files != null;
|
||||
string pattern = string.Empty;
|
||||
|
||||
|
||||
if (isRegexSearch)
|
||||
{
|
||||
pattern = GetRegexpFromString(fileName);
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Search;
|
||||
using static winPEAS.Helpers.YamlConfig.YamlConfig.SearchParameters;
|
||||
|
||||
namespace winPEAS.Checks
|
||||
{
|
||||
|
||||
internal class FileAnalysis : ISystemCheck
|
||||
{
|
||||
private const int ListFileLimit = 70;
|
||||
|
||||
public void PrintInfo(bool isDebug)
|
||||
{
|
||||
Beaprint.GreatPrint("File Analysis");
|
||||
|
||||
new List<Action>
|
||||
{
|
||||
PrintYAMLSearchFiles,
|
||||
PrintYAMLRegexesSearchFiles
|
||||
}.ForEach(action => CheckRunner.Run(action, isDebug));
|
||||
}
|
||||
|
||||
private static List<CustomFileInfo> InitializeFileSearch(bool useProgramFiles=true)
|
||||
{
|
||||
var files = new List<CustomFileInfo>();
|
||||
var systemDrive = $"{SearchHelper.SystemDrive}\\";
|
||||
|
||||
List<string> directories = new List<string>()
|
||||
{
|
||||
@$"{systemDrive}inetpub",
|
||||
@$"{systemDrive}usr\etc\snmp",
|
||||
@$"{systemDrive}windows\temp",
|
||||
@$"{systemDrive}xampp",
|
||||
};
|
||||
|
||||
List<string> wildcardDirectories = new List<string>()
|
||||
{
|
||||
"apache*",
|
||||
"tomcat*",
|
||||
};
|
||||
|
||||
foreach (var wildcardDirectory in wildcardDirectories)
|
||||
{
|
||||
directories.AddRange(Directory.GetDirectories(systemDrive, wildcardDirectory, SearchOption.TopDirectoryOnly));
|
||||
}
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
bool isFileFound = false;
|
||||
|
||||
foreach (var directory in directories)
|
||||
{
|
||||
files.AddRange(SearchHelper.GetFilesFast(directory, "*", isFoldersIncluded: true));
|
||||
}
|
||||
|
||||
files.AddRange(SearchHelper.RootDirUsers);
|
||||
// files.AddRange(SearchHelper.RootDirCurrentUser); // not needed, it's contained within RootDirUsers
|
||||
files.AddRange(SearchHelper.DocumentsAndSettings);
|
||||
files.AddRange(SearchHelper.GroupPolicyHistory); // TODO maybe not needed here
|
||||
if (useProgramFiles)
|
||||
{
|
||||
files.AddRange(SearchHelper.ProgramFiles);
|
||||
files.AddRange(SearchHelper.ProgramFilesX86);
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
private static bool[] Search(List<CustomFileInfo> files, string fileName, FileSettings fileSettings, ref int resultsCount, string searchName, bool somethingFound)
|
||||
{
|
||||
bool isRegexSearch = fileName.Contains("*");
|
||||
bool isFolder = fileSettings.files != null;
|
||||
string pattern = string.Empty;
|
||||
|
||||
|
||||
if (isRegexSearch)
|
||||
{
|
||||
pattern = GetRegexpFromString(fileName);
|
||||
}
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
bool isFileFound = false;
|
||||
|
||||
if (isFolder)
|
||||
{
|
||||
if (pattern == string.Empty)
|
||||
@ -98,9 +98,9 @@ namespace winPEAS.Checks
|
||||
if (isFileFound) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pattern == String.Empty)
|
||||
{
|
||||
isFileFound = file.Filename.ToLower() == fileName.ToLower();
|
||||
@ -108,285 +108,285 @@ namespace winPEAS.Checks
|
||||
else
|
||||
{
|
||||
isFileFound = Regex.IsMatch(file.Filename, pattern, RegexOptions.IgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isFileFound)
|
||||
{
|
||||
if (!somethingFound) {
|
||||
Beaprint.MainPrint($"Found {searchName} Files");
|
||||
somethingFound = true;
|
||||
}
|
||||
|
||||
if (!isFolder)
|
||||
{
|
||||
var isProcessed = ProcessResult(file, fileSettings, ref resultsCount);
|
||||
if (!isProcessed)
|
||||
{
|
||||
return new bool[] { true, somethingFound };
|
||||
}
|
||||
}
|
||||
// there are inner sections
|
||||
else
|
||||
{
|
||||
foreach (var innerFileToSearch in fileSettings.files)
|
||||
{
|
||||
List<CustomFileInfo> one_file_list = new List<CustomFileInfo>() { file };
|
||||
Search(one_file_list, innerFileToSearch.name, innerFileToSearch.value, ref resultsCount, searchName, somethingFound);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new bool[] { false, somethingFound };
|
||||
}
|
||||
|
||||
private static List<string> SearchContent(string text, string regex_str, bool caseinsensitive)
|
||||
{
|
||||
List<string> foundMatches = new List<string>();
|
||||
|
||||
try
|
||||
{
|
||||
Regex rgx;
|
||||
if (caseinsensitive)
|
||||
rgx = new Regex(regex_str.Trim(), RegexOptions.IgnoreCase);
|
||||
else
|
||||
rgx = new Regex(regex_str.Trim());
|
||||
|
||||
int cont = 0;
|
||||
foreach (Match match in rgx.Matches(text))
|
||||
{
|
||||
if (cont > 4) break;
|
||||
|
||||
if (match.Value.Length < 400 && match.Value.Trim().Length > 2)
|
||||
foundMatches.Add(match.Value);
|
||||
|
||||
cont++;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Beaprint.GrayPrint($"Error looking for regex {regex_str} inside files: {e}");
|
||||
}
|
||||
|
||||
//}
|
||||
|
||||
return foundMatches;
|
||||
}
|
||||
|
||||
private static void PrintYAMLSearchFiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
var files = InitializeFileSearch();
|
||||
//var folders = files.Where(f => f.IsDirectory).ToList();
|
||||
var config = Checks.YamlConfig;
|
||||
var defaults = config.defaults;
|
||||
var searchItems = config.search.Where(i => !(i.value.disable != null && i.value.disable.Contains("winpeas")));
|
||||
|
||||
foreach (var searchItem in searchItems)
|
||||
{
|
||||
var searchName = searchItem.name;
|
||||
var value = searchItem.value;
|
||||
var searchConfig = value.config;
|
||||
bool somethingFound = false;
|
||||
|
||||
CheckRunner.Run(() =>
|
||||
{
|
||||
int resultsCount = 0;
|
||||
bool[] results;
|
||||
bool isSearchFinished = false;
|
||||
|
||||
foreach (var file in value.files)
|
||||
{
|
||||
var fileName = file.name.ToLower();
|
||||
var fileSettings = file.value;
|
||||
|
||||
results = Search(files, fileName, fileSettings, ref resultsCount, searchName, somethingFound);
|
||||
|
||||
isSearchFinished = results[0];
|
||||
somethingFound = results[1];
|
||||
|
||||
if (isSearchFinished)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, Checks.IsDebug);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintYAMLRegexesSearchFiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
//List<string> extra_no_extensions = new List<string>() { ".msi", ".exe", ".dll", ".pyc", ".pyi", ".lnk", ".css", ".hyb", ".etl", ".mo", ".xrm-ms", ".idl", ".vsix", ".mui", ".qml", ".tt" };
|
||||
|
||||
List<string> valid_extensions = new List<string>() {
|
||||
// text
|
||||
".txt", ".text", ".md", ".markdown", ".toml", ".rtf",
|
||||
|
||||
// config
|
||||
".conf", ".config", ".json", ".yml", ".yaml", ".xml", ".xaml",
|
||||
|
||||
// dev
|
||||
".py", ".js", ".html", ".c", ".cpp", ".pl", ".rb", ".smali", ".java", ".php", ".bat", ".ps1",
|
||||
|
||||
// hidden
|
||||
".id_rsa", ".id_dsa", ".bash_history", ".rsa",
|
||||
};
|
||||
|
||||
List<string> invalid_names = new List<string>()
|
||||
{
|
||||
"eula.rtf", "changelog.md"
|
||||
};
|
||||
|
||||
// No dirs, less thatn 1MB, only interesting extensions and not false positives files.
|
||||
var files = InitializeFileSearch(Checks.SearchProgramFiles).Where(f => !f.IsDirectory && valid_extensions.Contains(f.Extension.ToLower()) && !invalid_names.Contains(f.Filename.ToLower()) && f.Size > 0 && f.Size < 1000000).ToList();
|
||||
var config = Checks.RegexesYamlConfig; // Get yaml info
|
||||
Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>> foundRegexes = new Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>> { };
|
||||
|
||||
/*
|
||||
* Useful for debbugging purposes to see the common file extensions found
|
||||
Dictionary <string, int> dict_str = new Dictionary<string, int>();
|
||||
foreach (var f in files)
|
||||
{
|
||||
if (dict_str.ContainsKey(f.Extension))
|
||||
dict_str[f.Extension] += 1;
|
||||
else
|
||||
dict_str[f.Extension] = 1;
|
||||
}
|
||||
|
||||
var sortedDict = from entry in dict_str orderby entry.Value descending select entry;
|
||||
|
||||
foreach (KeyValuePair<string, int> kvp in sortedDict)
|
||||
{
|
||||
Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
|
||||
}*/
|
||||
|
||||
double pb = 0;
|
||||
using (var progress = new ProgressBar())
|
||||
{
|
||||
CheckRunner.Run(() =>
|
||||
{
|
||||
int num_threads = 8;
|
||||
try
|
||||
{
|
||||
num_threads = Environment.ProcessorCount;
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
|
||||
Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = num_threads }, f =>
|
||||
{
|
||||
//foreach (var f in files)
|
||||
//{
|
||||
foreach (var regex_obj in config.regular_expresions)
|
||||
{
|
||||
foreach (var regex in regex_obj.regexes)
|
||||
{
|
||||
if (regex.disable != null && regex.disable.ToLower().Contains("winpeas"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
List<string> results = new List<string> { };
|
||||
|
||||
try
|
||||
{
|
||||
string text = System.IO.File.ReadAllText(f.FullPath);
|
||||
|
||||
results = SearchContent(text, regex.regex, (bool)regex.caseinsensitive);
|
||||
if (results.Count > 0)
|
||||
{
|
||||
if (!foundRegexes.ContainsKey(regex_obj.name)) foundRegexes[regex_obj.name] = new Dictionary<string, Dictionary<string, List<string>>> { };
|
||||
if (!foundRegexes[regex_obj.name].ContainsKey(regex.name)) foundRegexes[regex_obj.name][regex.name] = new Dictionary<string, List<string>> { };
|
||||
|
||||
foundRegexes[regex_obj.name][regex.name][f.FullPath] = results;
|
||||
}
|
||||
}
|
||||
catch (System.IO.IOException)
|
||||
{
|
||||
// Cannot read the file
|
||||
}
|
||||
}
|
||||
}
|
||||
pb += (double)100 / files.Count;
|
||||
progress.Report(pb / 100); //Value must be in [0..1] range
|
||||
});
|
||||
//}
|
||||
}, Checks.IsDebug);
|
||||
}
|
||||
|
||||
// Print results
|
||||
foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, List<string>>>> item in foundRegexes)
|
||||
{
|
||||
foreach (KeyValuePair<string, Dictionary<string, List<string>>> item2 in item.Value)
|
||||
{
|
||||
string masterCategory = item.Key;
|
||||
string regexCategory = item2.Key;
|
||||
int limit = 70;
|
||||
|
||||
string msg = $"Found {masterCategory}-{regexCategory} Regexes";
|
||||
if (item2.Value.Count > limit)
|
||||
msg += $" (limited to {limit})";
|
||||
|
||||
Beaprint.MainPrint(msg);
|
||||
|
||||
int cont = 0;
|
||||
foreach (KeyValuePair<string, List<string>> item3 in item2.Value)
|
||||
{
|
||||
if (cont > limit)
|
||||
break;
|
||||
|
||||
foreach (string regexMatch in item3.Value)
|
||||
{
|
||||
string filePath = item3.Key;
|
||||
Beaprint.PrintNoNL($"{filePath}: ");
|
||||
Beaprint.BadPrint(regexMatch);
|
||||
}
|
||||
|
||||
cont++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Beaprint.GrayPrint($"Error looking for regexes inside files: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetRegexpFromString(string str)
|
||||
{
|
||||
// we need to update the regexp to work here
|
||||
// . -> \.
|
||||
// * -> .*
|
||||
// add $ at the end to avoid false positives
|
||||
|
||||
var pattern = str.Replace(".", @"\.")
|
||||
.Replace("*", @".*");
|
||||
|
||||
pattern = $"{pattern}$";
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
||||
private static bool ProcessResult(
|
||||
CustomFileInfo fileInfo,
|
||||
Helpers.YamlConfig.YamlConfig.SearchParameters.FileSettings fileSettings,
|
||||
ref int resultsCount)
|
||||
{
|
||||
// print depending on the options here
|
||||
resultsCount++;
|
||||
|
||||
if (resultsCount > ListFileLimit) return false;
|
||||
|
||||
// If contains undesireable string, stop processing
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isFileFound)
|
||||
{
|
||||
if (!somethingFound) {
|
||||
Beaprint.MainPrint($"Found {searchName} Files");
|
||||
somethingFound = true;
|
||||
}
|
||||
|
||||
if (!isFolder)
|
||||
{
|
||||
var isProcessed = ProcessResult(file, fileSettings, ref resultsCount);
|
||||
if (!isProcessed)
|
||||
{
|
||||
return new bool[] { true, somethingFound };
|
||||
}
|
||||
}
|
||||
// there are inner sections
|
||||
else
|
||||
{
|
||||
foreach (var innerFileToSearch in fileSettings.files)
|
||||
{
|
||||
List<CustomFileInfo> one_file_list = new List<CustomFileInfo>() { file };
|
||||
Search(one_file_list, innerFileToSearch.name, innerFileToSearch.value, ref resultsCount, searchName, somethingFound);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new bool[] { false, somethingFound };
|
||||
}
|
||||
|
||||
private static List<string> SearchContent(string text, string regex_str, bool caseinsensitive)
|
||||
{
|
||||
List<string> foundMatches = new List<string>();
|
||||
|
||||
try
|
||||
{
|
||||
Regex rgx;
|
||||
if (caseinsensitive)
|
||||
rgx = new Regex(regex_str.Trim(), RegexOptions.IgnoreCase);
|
||||
else
|
||||
rgx = new Regex(regex_str.Trim());
|
||||
|
||||
int cont = 0;
|
||||
foreach (Match match in rgx.Matches(text))
|
||||
{
|
||||
if (cont > 4) break;
|
||||
|
||||
if (match.Value.Length < 400 && match.Value.Trim().Length > 2)
|
||||
foundMatches.Add(match.Value);
|
||||
|
||||
cont++;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Beaprint.GrayPrint($"Error looking for regex {regex_str} inside files: {e}");
|
||||
}
|
||||
|
||||
//}
|
||||
|
||||
return foundMatches;
|
||||
}
|
||||
|
||||
private static void PrintYAMLSearchFiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
var files = InitializeFileSearch();
|
||||
//var folders = files.Where(f => f.IsDirectory).ToList();
|
||||
var config = Checks.YamlConfig;
|
||||
var defaults = config.defaults;
|
||||
var searchItems = config.search.Where(i => !(i.value.disable != null && i.value.disable.Contains("winpeas")));
|
||||
|
||||
foreach (var searchItem in searchItems)
|
||||
{
|
||||
var searchName = searchItem.name;
|
||||
var value = searchItem.value;
|
||||
var searchConfig = value.config;
|
||||
bool somethingFound = false;
|
||||
|
||||
CheckRunner.Run(() =>
|
||||
{
|
||||
int resultsCount = 0;
|
||||
bool[] results;
|
||||
bool isSearchFinished = false;
|
||||
|
||||
foreach (var file in value.files)
|
||||
{
|
||||
var fileName = file.name.ToLower();
|
||||
var fileSettings = file.value;
|
||||
|
||||
results = Search(files, fileName, fileSettings, ref resultsCount, searchName, somethingFound);
|
||||
|
||||
isSearchFinished = results[0];
|
||||
somethingFound = results[1];
|
||||
|
||||
if (isSearchFinished)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, Checks.IsDebug);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintYAMLRegexesSearchFiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
//List<string> extra_no_extensions = new List<string>() { ".msi", ".exe", ".dll", ".pyc", ".pyi", ".lnk", ".css", ".hyb", ".etl", ".mo", ".xrm-ms", ".idl", ".vsix", ".mui", ".qml", ".tt" };
|
||||
|
||||
List<string> valid_extensions = new List<string>() {
|
||||
// text
|
||||
".txt", ".text", ".md", ".markdown", ".toml", ".rtf",
|
||||
|
||||
// config
|
||||
".conf", ".config", ".json", ".yml", ".yaml", ".xml", ".xaml",
|
||||
|
||||
// dev
|
||||
".py", ".js", ".html", ".c", ".cpp", ".pl", ".rb", ".smali", ".java", ".php", ".bat", ".ps1",
|
||||
|
||||
// hidden
|
||||
".id_rsa", ".id_dsa", ".bash_history", ".rsa",
|
||||
};
|
||||
|
||||
List<string> invalid_names = new List<string>()
|
||||
{
|
||||
"eula.rtf", "changelog.md"
|
||||
};
|
||||
|
||||
// No dirs, less thatn 1MB, only interesting extensions and not false positives files.
|
||||
var files = InitializeFileSearch(Checks.SearchProgramFiles).Where(f => !f.IsDirectory && valid_extensions.Contains(f.Extension.ToLower()) && !invalid_names.Contains(f.Filename.ToLower()) && f.Size > 0 && f.Size < 1000000).ToList();
|
||||
var config = Checks.RegexesYamlConfig; // Get yaml info
|
||||
Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>> foundRegexes = new Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>> { };
|
||||
|
||||
/*
|
||||
* Useful for debbugging purposes to see the common file extensions found
|
||||
Dictionary <string, int> dict_str = new Dictionary<string, int>();
|
||||
foreach (var f in files)
|
||||
{
|
||||
if (dict_str.ContainsKey(f.Extension))
|
||||
dict_str[f.Extension] += 1;
|
||||
else
|
||||
dict_str[f.Extension] = 1;
|
||||
}
|
||||
|
||||
var sortedDict = from entry in dict_str orderby entry.Value descending select entry;
|
||||
|
||||
foreach (KeyValuePair<string, int> kvp in sortedDict)
|
||||
{
|
||||
Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
|
||||
}*/
|
||||
|
||||
double pb = 0;
|
||||
using (var progress = new ProgressBar())
|
||||
{
|
||||
CheckRunner.Run(() =>
|
||||
{
|
||||
int num_threads = 8;
|
||||
try
|
||||
{
|
||||
num_threads = Environment.ProcessorCount;
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
|
||||
Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = num_threads }, f =>
|
||||
{
|
||||
//foreach (var f in files)
|
||||
//{
|
||||
foreach (var regex_obj in config.regular_expresions)
|
||||
{
|
||||
foreach (var regex in regex_obj.regexes)
|
||||
{
|
||||
if (regex.disable != null && regex.disable.ToLower().Contains("winpeas"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
List<string> results = new List<string> { };
|
||||
|
||||
try
|
||||
{
|
||||
string text = System.IO.File.ReadAllText(f.FullPath);
|
||||
|
||||
results = SearchContent(text, regex.regex, (bool)regex.caseinsensitive);
|
||||
if (results.Count > 0)
|
||||
{
|
||||
if (!foundRegexes.ContainsKey(regex_obj.name)) foundRegexes[regex_obj.name] = new Dictionary<string, Dictionary<string, List<string>>> { };
|
||||
if (!foundRegexes[regex_obj.name].ContainsKey(regex.name)) foundRegexes[regex_obj.name][regex.name] = new Dictionary<string, List<string>> { };
|
||||
|
||||
foundRegexes[regex_obj.name][regex.name][f.FullPath] = results;
|
||||
}
|
||||
}
|
||||
catch (System.IO.IOException)
|
||||
{
|
||||
// Cannot read the file
|
||||
}
|
||||
}
|
||||
}
|
||||
pb += (double)100 / files.Count;
|
||||
progress.Report(pb / 100); //Value must be in [0..1] range
|
||||
});
|
||||
//}
|
||||
}, Checks.IsDebug);
|
||||
}
|
||||
|
||||
// Print results
|
||||
foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, List<string>>>> item in foundRegexes)
|
||||
{
|
||||
foreach (KeyValuePair<string, Dictionary<string, List<string>>> item2 in item.Value)
|
||||
{
|
||||
string masterCategory = item.Key;
|
||||
string regexCategory = item2.Key;
|
||||
int limit = 70;
|
||||
|
||||
string msg = $"Found {masterCategory}-{regexCategory} Regexes";
|
||||
if (item2.Value.Count > limit)
|
||||
msg += $" (limited to {limit})";
|
||||
|
||||
Beaprint.MainPrint(msg);
|
||||
|
||||
int cont = 0;
|
||||
foreach (KeyValuePair<string, List<string>> item3 in item2.Value)
|
||||
{
|
||||
if (cont > limit)
|
||||
break;
|
||||
|
||||
foreach (string regexMatch in item3.Value)
|
||||
{
|
||||
string filePath = item3.Key;
|
||||
Beaprint.PrintNoNL($"{filePath}: ");
|
||||
Beaprint.BadPrint(regexMatch);
|
||||
}
|
||||
|
||||
cont++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Beaprint.GrayPrint($"Error looking for regexes inside files: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetRegexpFromString(string str)
|
||||
{
|
||||
// we need to update the regexp to work here
|
||||
// . -> \.
|
||||
// * -> .*
|
||||
// add $ at the end to avoid false positives
|
||||
|
||||
var pattern = str.Replace(".", @"\.")
|
||||
.Replace("*", @".*");
|
||||
|
||||
pattern = $"{pattern}$";
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
||||
private static bool ProcessResult(
|
||||
CustomFileInfo fileInfo,
|
||||
Helpers.YamlConfig.YamlConfig.SearchParameters.FileSettings fileSettings,
|
||||
ref int resultsCount)
|
||||
{
|
||||
// print depending on the options here
|
||||
resultsCount++;
|
||||
|
||||
if (resultsCount > ListFileLimit) return false;
|
||||
|
||||
// If contains undesireable string, stop processing
|
||||
if (fileSettings.remove_path != null && fileSettings.remove_path.Length > 0)
|
||||
{
|
||||
foreach(var rem_path in fileSettings.remove_path.Split('|'))
|
||||
@ -394,120 +394,120 @@ namespace winPEAS.Checks
|
||||
if (fileInfo.FullPath.ToLower().Contains(rem_path.ToLower()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileSettings.type == "f")
|
||||
{
|
||||
var colors = new Dictionary<string, string>();
|
||||
colors.Add(fileInfo.Filename, Beaprint.ansi_color_bad);
|
||||
Beaprint.AnsiPrint($"File: {fileInfo.FullPath}", colors);
|
||||
|
||||
if (!(bool)fileSettings.just_list_file)
|
||||
{
|
||||
GrepResult(fileInfo, fileSettings);
|
||||
}
|
||||
}
|
||||
else if (fileSettings.type == "d")
|
||||
{
|
||||
var colors = new Dictionary<string, string>();
|
||||
colors.Add(fileInfo.Filename, Beaprint.ansi_color_bad);
|
||||
Beaprint.AnsiPrint($"Folder: {fileInfo.FullPath}", colors);
|
||||
|
||||
// just list the directory
|
||||
if ((bool)fileSettings.just_list_file)
|
||||
{
|
||||
string[] files = Directory.GetFiles(fileInfo.FullPath, "*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
Beaprint.BadPrint($" {file}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// should not happen
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void GrepResult(CustomFileInfo fileInfo, FileSettings fileSettings)
|
||||
{
|
||||
var fileContent = File.ReadLines(fileInfo.FullPath);
|
||||
var colors = new Dictionary<string, string>();
|
||||
|
||||
if ((bool)fileSettings.only_bad_lines)
|
||||
{
|
||||
colors.Add(fileSettings.bad_regex, Beaprint.ansi_color_bad);
|
||||
fileContent = fileContent.Where(l => Regex.IsMatch(l, fileSettings.bad_regex, RegexOptions.IgnoreCase));
|
||||
}
|
||||
else
|
||||
{
|
||||
string lineGrep = null;
|
||||
|
||||
if ((bool)fileSettings.remove_empty_lines)
|
||||
{
|
||||
fileContent = fileContent.Where(l => !string.IsNullOrWhiteSpace(l));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(fileSettings.remove_regex))
|
||||
{
|
||||
var pattern = GetRegexpFromString(fileSettings.remove_regex);
|
||||
fileContent = fileContent.Where(l => !Regex.IsMatch(l, pattern, RegexOptions.IgnoreCase));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(fileSettings.good_regex))
|
||||
{
|
||||
colors.Add(fileSettings.good_regex, Beaprint.ansi_color_good);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(fileSettings.bad_regex))
|
||||
{
|
||||
colors.Add(fileSettings.bad_regex, Beaprint.ansi_color_bad);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(fileSettings.line_grep))
|
||||
{
|
||||
lineGrep = SanitizeLineGrep(fileSettings.line_grep);
|
||||
}
|
||||
|
||||
fileContent = fileContent.Where(line => (!string.IsNullOrWhiteSpace(fileSettings.good_regex) && Regex.IsMatch(line, fileSettings.good_regex, RegexOptions.IgnoreCase)) ||
|
||||
(!string.IsNullOrWhiteSpace(fileSettings.bad_regex) && Regex.IsMatch(line, fileSettings.bad_regex, RegexOptions.IgnoreCase)) ||
|
||||
(!string.IsNullOrWhiteSpace(lineGrep) && Regex.IsMatch(line, lineGrep, RegexOptions.IgnoreCase)));
|
||||
}
|
||||
|
||||
var content = string.Join(Environment.NewLine, fileContent);
|
||||
|
||||
Beaprint.AnsiPrint(content, colors);
|
||||
|
||||
if (content.Length > 0)
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
private static string SanitizeLineGrep(string lineGrep)
|
||||
{
|
||||
// sanitize the string, e.g.
|
||||
// '-i -a -o "description.*" | sort | uniq'
|
||||
// - remove everything except from "description.*"
|
||||
|
||||
Regex regex;
|
||||
if (lineGrep.Contains("-i"))
|
||||
{
|
||||
regex = new Regex("\"([^\"]+)\"", RegexOptions.IgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
regex = new Regex("\"([^\"]+)\"");
|
||||
}
|
||||
|
||||
Match match = regex.Match(lineGrep);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
var group = match.Groups[1];
|
||||
return group.Value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fileSettings.type == "f")
|
||||
{
|
||||
var colors = new Dictionary<string, string>();
|
||||
colors.Add(fileInfo.Filename, Beaprint.ansi_color_bad);
|
||||
Beaprint.AnsiPrint($"File: {fileInfo.FullPath}", colors);
|
||||
|
||||
if (!(bool)fileSettings.just_list_file)
|
||||
{
|
||||
GrepResult(fileInfo, fileSettings);
|
||||
}
|
||||
}
|
||||
else if (fileSettings.type == "d")
|
||||
{
|
||||
var colors = new Dictionary<string, string>();
|
||||
colors.Add(fileInfo.Filename, Beaprint.ansi_color_bad);
|
||||
Beaprint.AnsiPrint($"Folder: {fileInfo.FullPath}", colors);
|
||||
|
||||
// just list the directory
|
||||
if ((bool)fileSettings.just_list_file)
|
||||
{
|
||||
string[] files = Directory.GetFiles(fileInfo.FullPath, "*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
Beaprint.BadPrint($" {file}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// should not happen
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void GrepResult(CustomFileInfo fileInfo, FileSettings fileSettings)
|
||||
{
|
||||
var fileContent = File.ReadLines(fileInfo.FullPath);
|
||||
var colors = new Dictionary<string, string>();
|
||||
|
||||
if ((bool)fileSettings.only_bad_lines)
|
||||
{
|
||||
colors.Add(fileSettings.bad_regex, Beaprint.ansi_color_bad);
|
||||
fileContent = fileContent.Where(l => Regex.IsMatch(l, fileSettings.bad_regex, RegexOptions.IgnoreCase));
|
||||
}
|
||||
else
|
||||
{
|
||||
string lineGrep = null;
|
||||
|
||||
if ((bool)fileSettings.remove_empty_lines)
|
||||
{
|
||||
fileContent = fileContent.Where(l => !string.IsNullOrWhiteSpace(l));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(fileSettings.remove_regex))
|
||||
{
|
||||
var pattern = GetRegexpFromString(fileSettings.remove_regex);
|
||||
fileContent = fileContent.Where(l => !Regex.IsMatch(l, pattern, RegexOptions.IgnoreCase));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(fileSettings.good_regex))
|
||||
{
|
||||
colors.Add(fileSettings.good_regex, Beaprint.ansi_color_good);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(fileSettings.bad_regex))
|
||||
{
|
||||
colors.Add(fileSettings.bad_regex, Beaprint.ansi_color_bad);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(fileSettings.line_grep))
|
||||
{
|
||||
lineGrep = SanitizeLineGrep(fileSettings.line_grep);
|
||||
}
|
||||
|
||||
fileContent = fileContent.Where(line => (!string.IsNullOrWhiteSpace(fileSettings.good_regex) && Regex.IsMatch(line, fileSettings.good_regex, RegexOptions.IgnoreCase)) ||
|
||||
(!string.IsNullOrWhiteSpace(fileSettings.bad_regex) && Regex.IsMatch(line, fileSettings.bad_regex, RegexOptions.IgnoreCase)) ||
|
||||
(!string.IsNullOrWhiteSpace(lineGrep) && Regex.IsMatch(line, lineGrep, RegexOptions.IgnoreCase)));
|
||||
}
|
||||
|
||||
var content = string.Join(Environment.NewLine, fileContent);
|
||||
|
||||
Beaprint.AnsiPrint(content, colors);
|
||||
|
||||
if (content.Length > 0)
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
private static string SanitizeLineGrep(string lineGrep)
|
||||
{
|
||||
// sanitize the string, e.g.
|
||||
// '-i -a -o "description.*" | sort | uniq'
|
||||
// - remove everything except from "description.*"
|
||||
|
||||
Regex regex;
|
||||
if (lineGrep.Contains("-i"))
|
||||
{
|
||||
regex = new Regex("\"([^\"]+)\"", RegexOptions.IgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
regex = new Regex("\"([^\"]+)\"");
|
||||
}
|
||||
|
||||
Match match = regex.Match(lineGrep);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
var group = match.Groups[1];
|
||||
return group.Value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -213,6 +213,15 @@ namespace winPEAS.Helpers
|
||||
Console.WriteLine(DGRAY + to_print + NOCOLOR);
|
||||
}
|
||||
|
||||
public static void LongPathWarning(string path)
|
||||
{
|
||||
if (!Checks.Checks.warning_is_long_path)
|
||||
{
|
||||
GrayPrint($"The path {path} is too large, try to enable LongPathsin th registry (no more warning about this will be shown)");
|
||||
Checks.Checks.warning_is_long_path = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void PrintDebugLine(string log)
|
||||
{
|
||||
Console.WriteLine(YELLOW + " [Debug] " + log + NOCOLOR);
|
||||
|
@ -76,7 +76,7 @@ namespace winPEAS.Helpers.Search
|
||||
if (!StaticExtensions.Contains(f.Extension.ToLower()))
|
||||
{
|
||||
// It should always be lesss than 260, but some times it isn't so this will bypass that file
|
||||
if (f.FullName.Length <= 260)
|
||||
if (Checks.Checks.is_long_path || f.FullName.Length <= 260)
|
||||
{
|
||||
CustomFileInfo file_info = new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false);
|
||||
files.Add(file_info);
|
||||
@ -88,6 +88,8 @@ namespace winPEAS.Helpers.Search
|
||||
files.Add(file_dir);
|
||||
}
|
||||
}
|
||||
else if (f.FullName.Length > 260)
|
||||
Beaprint.LongPathWarning(f.FullName);
|
||||
}
|
||||
}
|
||||
) ;
|
||||
@ -169,14 +171,24 @@ namespace winPEAS.Helpers.Search
|
||||
{
|
||||
foreach (var directory in directories)
|
||||
{
|
||||
files.Add(new CustomFileInfo(directory.Name, null, directory.FullName, 0, true));
|
||||
if (Checks.Checks.is_long_path || directory.FullName.Length <= 260)
|
||||
files.Add(new CustomFileInfo(directory.Name, null, directory.FullName, 0, true));
|
||||
|
||||
else if (directory.FullName.Length > 260)
|
||||
Beaprint.LongPathWarning(directory.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var f in dirInfo.GetFiles(pattern))
|
||||
{
|
||||
if (!StaticExtensions.Contains(f.Extension.ToLower()))
|
||||
files.Add(new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false));
|
||||
if (!StaticExtensions.Contains(f.Extension.ToLower()))
|
||||
{
|
||||
if (Checks.Checks.is_long_path || f.FullName.Length <= 260)
|
||||
files.Add(new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false));
|
||||
|
||||
else if (f.FullName.Length > 260)
|
||||
Beaprint.LongPathWarning(f.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
if (directories.Length > 1) return new List<DirectoryInfo>(directories);
|
||||
|
Loading…
Reference in New Issue
Block a user