Files
PEASS-ng/winPEAS/winPEASexe/winPEAS/Checks/FileAnalysis.cs
carlospolop 09312c6883 winpeas fix
2022-03-07 22:49:35 +00:00

319 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
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
}.ForEach(action => CheckRunner.Run(action, isDebug));
}
private static List<CustomFileInfo> InitializeFileSearch()
{
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
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("*");
string pattern = string.Empty;
if (isRegexSearch)
{
pattern = GetRegexpFromString(fileName);
}
foreach (var file in files)
{
bool isFileFound;
if (isRegexSearch)
{
isFileFound = Regex.IsMatch(file.Filename, pattern, RegexOptions.IgnoreCase);
}
else
{
isFileFound = file.Filename.ToLower() == fileName;
}
if (isFileFound)
{
if (!somethingFound) {
Beaprint.MainPrint($"Found {searchName} Files");
somethingFound = true;
}
// there are no inner sections
if (fileSettings.files == null)
{
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)
{
// search for inner files/folders by inner file/folder name
var innerFiles = SearchHelper.GetFilesFast(file.FullPath, innerFileToSearch.name, isFoldersIncluded: true);
foreach (var innerFile in innerFiles)
{
// process inner file/folder
var isProcessed = ProcessResult(innerFile, innerFileToSearch.value, ref resultsCount);
if (!isProcessed)
{
return new bool[] { true, somethingFound };
}
}
}
}
}
}
return new bool[] { false, somethingFound };
}
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.config.auto_check &&
(i.value.disable == null || !i.value.disable.Contains("winpeas")));
foreach (var searchItem in searchItems)
{
if (searchItem.name != "Wifi Connections")
continue;
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;
var itemsToSearch = fileSettings.type == "f" ? files : folders;
results = Search(itemsToSearch, fileName, fileSettings, ref resultsCount, searchName, somethingFound);
isSearchFinished = results[0];
somethingFound = results[1];
if (isSearchFinished)
{
break;
}
}
}, Checks.IsDebug);
}
}
catch (Exception 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 (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;
}
}
}