update
This commit is contained in:
parent
56d71ae847
commit
bbc22b3a91
@ -14,10 +14,6 @@ Find the **latest versions of all the scripts and binaries in [the releases page
|
|||||||
- [Link to WinPEAS C# project (.exe)](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS/winPEASexe) (.Net >= 4.5.2 required)
|
- [Link to WinPEAS C# project (.exe)](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS/winPEASexe) (.Net >= 4.5.2 required)
|
||||||
- **Please, read the Readme of that folder to learn how to execute winpeas from memory or how make colors work among other tricks**
|
- **Please, read the Readme of that folder to learn how to execute winpeas from memory or how make colors work among other tricks**
|
||||||
|
|
||||||
## Please, if this tool has been useful for you consider to donate
|
|
||||||
|
|
||||||
[](https://www.patreon.com/peass)
|
|
||||||
|
|
||||||
## PEASS Style
|
## PEASS Style
|
||||||
|
|
||||||
Are you a PEASS fan? Get now our merch at **[PEASS Shop](https://teespring.com/stores/peass)** and show your love for our favorite peas
|
Are you a PEASS fan? Get now our merch at **[PEASS Shop](https://teespring.com/stores/peass)** and show your love for our favorite peas
|
||||||
|
@ -129,10 +129,6 @@ This is the kind of outpuf that you have to look for when usnig the winPEAS.bat
|
|||||||
|
|
||||||
[More info about icacls here](https://ss64.com/nt/icacls.html)
|
[More info about icacls here](https://ss64.com/nt/icacls.html)
|
||||||
|
|
||||||
## Please, if this tool has been useful for you consider to donate
|
|
||||||
|
|
||||||
[](https://www.patreon.com/peass)
|
|
||||||
|
|
||||||
## Advisory
|
## Advisory
|
||||||
|
|
||||||
All the scripts/binaries of the PEAS Suite should be used for authorized penetration testing and/or educational purposes only. Any misuse of this software will not be the responsibility of the author or of any other collaborator. Use it at your own networks and/or with the network owner's permission.
|
All the scripts/binaries of the PEAS Suite should be used for authorized penetration testing and/or educational purposes only. Any misuse of this software will not be the responsibility of the author or of any other collaborator. Use it at your own networks and/or with the network owner's permission.
|
||||||
|
@ -66,8 +66,7 @@ winpeas.exe -lolbas #Execute also additional LOLBAS search check
|
|||||||
|
|
||||||
## Help
|
## Help
|
||||||
```
|
```
|
||||||
quiet Do not print banner
|
domain Enumerate domain information
|
||||||
notcolor Don't use ansi colors (all white)
|
|
||||||
systeminfo Search system information
|
systeminfo Search system information
|
||||||
userinfo Search user information
|
userinfo Search user information
|
||||||
processinfo Search processes information
|
processinfo Search processes information
|
||||||
@ -76,16 +75,21 @@ applicationsinfo Search installed applications information
|
|||||||
networkinfo Search network information
|
networkinfo Search network information
|
||||||
windowscreds Search windows credentials
|
windowscreds Search windows credentials
|
||||||
browserinfo Search browser information
|
browserinfo Search browser information
|
||||||
filesinfo Search files that can contains credentials
|
filesinfo Search generic files that can contains credentials
|
||||||
|
fileanalysis Search specific files that can contains credentials and for regexes inside files
|
||||||
eventsinfo Display interesting events information
|
eventsinfo Display interesting events information
|
||||||
|
|
||||||
|
quiet Do not print banner
|
||||||
|
notcolor Don't use ansi colors (all white)
|
||||||
|
searchpf Search credentials via regex also in Program Files folders
|
||||||
wait Wait for user input between checks
|
wait Wait for user input between checks
|
||||||
debug Display debugging information - memory usage, method execution time
|
debug Display debugging information - memory usage, method execution time
|
||||||
log=[logfile] Log all output to file defined as logfile, or to "out.txt" if not specified
|
log[=logfile] Log all output to file defined as logfile, or to "out.txt" if not specified
|
||||||
|
|
||||||
Additional checks (slower):
|
Additional checks (slower):
|
||||||
-lolbas Run additional LOLBAS check
|
-lolbas Run additional LOLBAS check
|
||||||
-linpeas=[url] Run additional linpeas.sh check for default WSL distribution, optionally provide custom linpeas.sh URL
|
-linpeas=[url] Run additional linpeas.sh check for default WSL distribution, optionally provide custom linpeas.sh URL
|
||||||
(default: https://raw.githubusercontent.com/carlospolop/privilege-escalation-awesome-scripts-suite/master/linPEAS/linpeas.sh)
|
(default: https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Basic information
|
## Basic information
|
||||||
@ -276,10 +280,6 @@ If you find any issue, please report it using **[github issues](https://github.c
|
|||||||
|
|
||||||
**WinPEAS** is being **updated** every time I find something that could be useful to escalate privileges.
|
**WinPEAS** is being **updated** every time I find something that could be useful to escalate privileges.
|
||||||
|
|
||||||
## Please, if this tool has been useful for you consider to donate
|
|
||||||
|
|
||||||
[](https://www.patreon.com/peass)
|
|
||||||
|
|
||||||
## Advisory
|
## Advisory
|
||||||
|
|
||||||
All the scripts/binaries of the PEAS Suite should be used for authorized penetration testing and/or educational purposes only. Any misuse of this software will not be the responsibility of the author or of any other collaborator. Use it at your own networks and/or with the network owner's permission.
|
All the scripts/binaries of the PEAS Suite should be used for authorized penetration testing and/or educational purposes only. Any misuse of this software will not be the responsibility of the author or of any other collaborator. Use it at your own networks and/or with the network owner's permission.
|
||||||
|
@ -21,6 +21,7 @@ namespace winPEAS.Checks
|
|||||||
public static bool IsDebug = false;
|
public static bool IsDebug = false;
|
||||||
public static bool IsLinpeas = false;
|
public static bool IsLinpeas = false;
|
||||||
public static bool IsLolbas = false;
|
public static bool IsLolbas = false;
|
||||||
|
public static bool SearchProgramFiles = false;
|
||||||
|
|
||||||
// Create Dynamic blacklists
|
// Create Dynamic blacklists
|
||||||
public static readonly string CurrentUserName = Environment.UserName;
|
public static readonly string CurrentUserName = Environment.UserName;
|
||||||
@ -37,6 +38,7 @@ namespace winPEAS.Checks
|
|||||||
//static string paint_lockoutUsers = "";
|
//static string paint_lockoutUsers = "";
|
||||||
public static string PaintAdminUsers = "";
|
public static string PaintAdminUsers = "";
|
||||||
public static YamlConfig YamlConfig;
|
public static YamlConfig YamlConfig;
|
||||||
|
public static YamlRegexConfig RegexesYamlConfig;
|
||||||
|
|
||||||
private static List<SystemCheck> _systemChecks;
|
private static List<SystemCheck> _systemChecks;
|
||||||
private static readonly HashSet<string> _systemCheckSelectedKeysHashSet = new HashSet<string>();
|
private static readonly HashSet<string> _systemCheckSelectedKeysHashSet = new HashSet<string>();
|
||||||
@ -152,6 +154,11 @@ namespace winPEAS.Checks
|
|||||||
IsDomainEnumeration = true;
|
IsDomainEnumeration = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.Equals(arg, "searchpf", StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
SearchProgramFiles = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (string.Equals(arg, "-lolbas", StringComparison.CurrentCultureIgnoreCase))
|
if (string.Equals(arg, "-lolbas", StringComparison.CurrentCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
IsLolbas = true;
|
IsLolbas = true;
|
||||||
@ -248,12 +255,22 @@ namespace winPEAS.Checks
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Beaprint.GrayPrint(" - Loading YAML definitions file...");
|
Beaprint.GrayPrint(" - Loading sensitive_files yaml definitions file...");
|
||||||
YamlConfig = YamlConfigHelper.GetWindowsSearchConfig();
|
YamlConfig = YamlConfigHelper.GetWindowsSearchConfig();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Beaprint.GrayPrint("Error while getting AD info: " + ex);
|
Beaprint.GrayPrint("Error while getting sensitive_files yaml info: " + ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Beaprint.GrayPrint(" - Loading regexes yaml definitions file...");
|
||||||
|
RegexesYamlConfig = YamlConfigHelper.GetRegexesSearchConfig();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Beaprint.GrayPrint("Error while getting regexes yaml info: " + ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -3,12 +3,14 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using winPEAS.Helpers;
|
using winPEAS.Helpers;
|
||||||
using winPEAS.Helpers.Search;
|
using winPEAS.Helpers.Search;
|
||||||
using static winPEAS.Helpers.YamlConfig.YamlConfig.SearchParameters;
|
using static winPEAS.Helpers.YamlConfig.YamlConfig.SearchParameters;
|
||||||
|
|
||||||
namespace winPEAS.Checks
|
namespace winPEAS.Checks
|
||||||
{
|
{
|
||||||
|
|
||||||
internal class FileAnalysis : ISystemCheck
|
internal class FileAnalysis : ISystemCheck
|
||||||
{
|
{
|
||||||
private const int ListFileLimit = 70;
|
private const int ListFileLimit = 70;
|
||||||
@ -19,11 +21,12 @@ namespace winPEAS.Checks
|
|||||||
|
|
||||||
new List<Action>
|
new List<Action>
|
||||||
{
|
{
|
||||||
PrintYAMLSearchFiles
|
PrintYAMLSearchFiles,
|
||||||
|
PrintYAMLRegexesSearchFiles
|
||||||
}.ForEach(action => CheckRunner.Run(action, isDebug));
|
}.ForEach(action => CheckRunner.Run(action, isDebug));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<CustomFileInfo> InitializeFileSearch()
|
private static List<CustomFileInfo> InitializeFileSearch(bool useProgramFiles=true)
|
||||||
{
|
{
|
||||||
var files = new List<CustomFileInfo>();
|
var files = new List<CustomFileInfo>();
|
||||||
var systemDrive = $"{SearchHelper.SystemDrive}\\";
|
var systemDrive = $"{SearchHelper.SystemDrive}\\";
|
||||||
@ -56,8 +59,11 @@ namespace winPEAS.Checks
|
|||||||
// files.AddRange(SearchHelper.RootDirCurrentUser); // not needed, it's contained within RootDirUsers
|
// files.AddRange(SearchHelper.RootDirCurrentUser); // not needed, it's contained within RootDirUsers
|
||||||
files.AddRange(SearchHelper.DocumentsAndSettings);
|
files.AddRange(SearchHelper.DocumentsAndSettings);
|
||||||
files.AddRange(SearchHelper.GroupPolicyHistory); // TODO maybe not needed here
|
files.AddRange(SearchHelper.GroupPolicyHistory); // TODO maybe not needed here
|
||||||
files.AddRange(SearchHelper.ProgramFiles);
|
if (useProgramFiles)
|
||||||
files.AddRange(SearchHelper.ProgramFilesX86);
|
{
|
||||||
|
files.AddRange(SearchHelper.ProgramFiles);
|
||||||
|
files.AddRange(SearchHelper.ProgramFilesX86);
|
||||||
|
}
|
||||||
|
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
@ -65,25 +71,47 @@ namespace winPEAS.Checks
|
|||||||
private static bool[] Search(List<CustomFileInfo> files, string fileName, FileSettings fileSettings, ref int resultsCount, string searchName, bool somethingFound)
|
private static bool[] Search(List<CustomFileInfo> files, string fileName, FileSettings fileSettings, ref int resultsCount, string searchName, bool somethingFound)
|
||||||
{
|
{
|
||||||
bool isRegexSearch = fileName.Contains("*");
|
bool isRegexSearch = fileName.Contains("*");
|
||||||
|
bool isFolder = fileSettings.files != null;
|
||||||
string pattern = string.Empty;
|
string pattern = string.Empty;
|
||||||
|
|
||||||
|
|
||||||
if (isRegexSearch)
|
if (isRegexSearch)
|
||||||
{
|
{
|
||||||
pattern = GetRegexpFromString(fileName);
|
pattern = GetRegexpFromString(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
bool isFileFound;
|
bool isFileFound = false;
|
||||||
if (isRegexSearch)
|
|
||||||
{
|
if (isFolder)
|
||||||
isFileFound = Regex.IsMatch(file.Filename, pattern, RegexOptions.IgnoreCase);
|
{
|
||||||
|
if (pattern == string.Empty)
|
||||||
|
{
|
||||||
|
isFileFound = file.FullPath.ToLower().Contains($"\\{fileName}\\");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var fold in file.FullPath.Split('\\').Skip(1))
|
||||||
|
{
|
||||||
|
isFileFound = Regex.IsMatch(fold, pattern, RegexOptions.IgnoreCase);
|
||||||
|
if (isFileFound) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isFileFound = file.Filename.ToLower() == fileName;
|
if (pattern == String.Empty)
|
||||||
|
{
|
||||||
|
isFileFound = file.Filename.ToLower() == fileName.ToLower();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isFileFound = Regex.IsMatch(file.Filename, pattern, RegexOptions.IgnoreCase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (isFileFound)
|
if (isFileFound)
|
||||||
{
|
{
|
||||||
if (!somethingFound) {
|
if (!somethingFound) {
|
||||||
@ -91,8 +119,7 @@ namespace winPEAS.Checks
|
|||||||
somethingFound = true;
|
somethingFound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// there are no inner sections
|
if (!isFolder)
|
||||||
if (fileSettings.files == null)
|
|
||||||
{
|
{
|
||||||
var isProcessed = ProcessResult(file, fileSettings, ref resultsCount);
|
var isProcessed = ProcessResult(file, fileSettings, ref resultsCount);
|
||||||
if (!isProcessed)
|
if (!isProcessed)
|
||||||
@ -105,18 +132,8 @@ namespace winPEAS.Checks
|
|||||||
{
|
{
|
||||||
foreach (var innerFileToSearch in fileSettings.files)
|
foreach (var innerFileToSearch in fileSettings.files)
|
||||||
{
|
{
|
||||||
// search for inner files/folders by inner file/folder name
|
List<CustomFileInfo> one_file_list = new List<CustomFileInfo>() { file };
|
||||||
var innerFiles = SearchHelper.GetFilesFast(file.FullPath, innerFileToSearch.name, isFoldersIncluded: true);
|
Search(one_file_list, innerFileToSearch.name, innerFileToSearch.value, ref resultsCount, searchName, somethingFound);
|
||||||
|
|
||||||
foreach (var innerFile in innerFiles)
|
|
||||||
{
|
|
||||||
// process inner file/folder
|
|
||||||
var isProcessed = ProcessResult(innerFile, innerFileToSearch.value, ref resultsCount);
|
|
||||||
if (!isProcessed)
|
|
||||||
{
|
|
||||||
return new bool[] { true, somethingFound };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,22 +141,52 @@ namespace winPEAS.Checks
|
|||||||
|
|
||||||
return new bool[] { false, 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()
|
private static void PrintYAMLSearchFiles()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var files = InitializeFileSearch();
|
var files = InitializeFileSearch();
|
||||||
var folders = files.Where(f => f.IsDirectory).ToList();
|
//var folders = files.Where(f => f.IsDirectory).ToList();
|
||||||
var config = Checks.YamlConfig;
|
var config = Checks.YamlConfig;
|
||||||
var defaults = config.defaults;
|
var defaults = config.defaults;
|
||||||
var searchItems = config.search.Where(i => i.value.config.auto_check &&
|
var searchItems = config.search.Where(i => !(i.value.disable != null && i.value.disable.Contains("winpeas")));
|
||||||
(i.value.disable == null || !i.value.disable.Contains("winpeas")));
|
|
||||||
|
|
||||||
foreach (var searchItem in searchItems)
|
foreach (var searchItem in searchItems)
|
||||||
{
|
{
|
||||||
if (searchItem.name != "Wifi Connections")
|
|
||||||
continue;
|
|
||||||
var searchName = searchItem.name;
|
var searchName = searchItem.name;
|
||||||
var value = searchItem.value;
|
var value = searchItem.value;
|
||||||
var searchConfig = value.config;
|
var searchConfig = value.config;
|
||||||
@ -155,9 +202,8 @@ namespace winPEAS.Checks
|
|||||||
{
|
{
|
||||||
var fileName = file.name.ToLower();
|
var fileName = file.name.ToLower();
|
||||||
var fileSettings = file.value;
|
var fileSettings = file.value;
|
||||||
var itemsToSearch = fileSettings.type == "f" ? files : folders;
|
|
||||||
|
|
||||||
results = Search(itemsToSearch, fileName, fileSettings, ref resultsCount, searchName, somethingFound);
|
results = Search(files, fileName, fileSettings, ref resultsCount, searchName, somethingFound);
|
||||||
|
|
||||||
isSearchFinished = results[0];
|
isSearchFinished = results[0];
|
||||||
somethingFound = results[1];
|
somethingFound = results[1];
|
||||||
@ -175,6 +221,146 @@ namespace winPEAS.Checks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
private static string GetRegexpFromString(string str)
|
||||||
{
|
{
|
||||||
// we need to update the regexp to work here
|
// we need to update the regexp to work here
|
||||||
@ -199,7 +385,16 @@ namespace winPEAS.Checks
|
|||||||
resultsCount++;
|
resultsCount++;
|
||||||
|
|
||||||
if (resultsCount > ListFileLimit) return false;
|
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('|'))
|
||||||
|
{
|
||||||
|
if (fileInfo.FullPath.ToLower().Contains(rem_path.ToLower()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fileSettings.type == "f")
|
if (fileSettings.type == "f")
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,7 @@ namespace winPEAS.Checks
|
|||||||
{
|
{
|
||||||
{ badIps, Beaprint.ansi_color_bad },
|
{ badIps, Beaprint.ansi_color_bad },
|
||||||
{ @"\[\:\:1\]", Beaprint.ansi_color_bad },
|
{ @"\[\:\:1\]", Beaprint.ansi_color_bad },
|
||||||
|
{ @"\[\:\:\]", Beaprint.ansi_color_bad },
|
||||||
};
|
};
|
||||||
|
|
||||||
public void PrintInfo(bool isDebug)
|
public void PrintInfo(bool isDebug)
|
||||||
@ -223,6 +224,11 @@ namespace winPEAS.Checks
|
|||||||
|
|
||||||
foreach (var udpConnectionInfo in NetworkInfoHelper.GetUdpConnections(IPVersion.IPv4, processesByPid))
|
foreach (var udpConnectionInfo in NetworkInfoHelper.GetUdpConnections(IPVersion.IPv4, processesByPid))
|
||||||
{
|
{
|
||||||
|
if (udpConnectionInfo.ProcessName == "dns") // Hundreds of them sometimes
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Beaprint.AnsiPrint(
|
Beaprint.AnsiPrint(
|
||||||
string.Format(formatString,
|
string.Format(formatString,
|
||||||
" UDP",
|
" UDP",
|
||||||
@ -254,6 +260,11 @@ namespace winPEAS.Checks
|
|||||||
|
|
||||||
foreach (var udpConnectionInfo in NetworkInfoHelper.GetUdpConnections(IPVersion.IPv6, processesByPid))
|
foreach (var udpConnectionInfo in NetworkInfoHelper.GetUdpConnections(IPVersion.IPv6, processesByPid))
|
||||||
{
|
{
|
||||||
|
if (udpConnectionInfo.ProcessName == "dns") // Hundreds of them sometimes
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Beaprint.AnsiPrint(
|
Beaprint.AnsiPrint(
|
||||||
string.Format(formatString,
|
string.Format(formatString,
|
||||||
" UDP",
|
" UDP",
|
||||||
|
@ -14,7 +14,8 @@ namespace winPEAS.Checks
|
|||||||
|
|
||||||
new List<Action>
|
new List<Action>
|
||||||
{
|
{
|
||||||
PrintInterestingProcesses,
|
//PrintInterestingProcesses,
|
||||||
|
PrintVulnLeakedHandlers,
|
||||||
}.ForEach(action => CheckRunner.Run(action, isDebug));
|
}.ForEach(action => CheckRunner.Run(action, isDebug));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,5 +84,24 @@ namespace winPEAS.Checks
|
|||||||
Beaprint.GrayPrint(ex.Message);
|
Beaprint.GrayPrint(ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrintVulnLeakedHandlers()
|
||||||
|
{
|
||||||
|
Beaprint.MainPrint("Vulnerable Leaked Handlers");
|
||||||
|
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/leaked-handle-exploitation");
|
||||||
|
|
||||||
|
List<Dictionary<string, string>> vulnHandlers = ProcessesInfo.GetVulnHandlers();
|
||||||
|
foreach (Dictionary<string, string> handler in vulnHandlers)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> colors = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ Checks.CurrentUserName, Beaprint.ansi_color_bad },
|
||||||
|
{ handler["Reason"], Beaprint.ansi_color_bad },
|
||||||
|
};
|
||||||
|
|
||||||
|
Beaprint.DictPrint(vulnHandlers, colors, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,8 @@ namespace winPEAS.Checks
|
|||||||
PrintInetInfo,
|
PrintInetInfo,
|
||||||
PrintDrivesInfo,
|
PrintDrivesInfo,
|
||||||
PrintWSUS,
|
PrintWSUS,
|
||||||
|
PrintKrbRelayUp,
|
||||||
|
PrintInsideContainer,
|
||||||
PrintAlwaysInstallElevated,
|
PrintAlwaysInstallElevated,
|
||||||
PrintLSAInfo,
|
PrintLSAInfo,
|
||||||
PrintNtlmSettings,
|
PrintNtlmSettings,
|
||||||
@ -586,6 +588,52 @@ namespace winPEAS.Checks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PrintKrbRelayUp()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Beaprint.MainPrint("Checking KrbRelayUp");
|
||||||
|
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#krbrelayup");
|
||||||
|
|
||||||
|
if (Checks.CurrentAdDomainName.Length > 0)
|
||||||
|
{
|
||||||
|
Beaprint.BadPrint(" The system is inside a domain (" + Checks.CurrentAdDomainName + ") so it could be vulnerable.");
|
||||||
|
Beaprint.InfoPrint("You can try https://github.com/DecOne/KrbRelayUp to escalate privileges");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Beaprint.GoodPrint(" The system isn't inside a domain, so it isn't vulnerable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Beaprint.PrintException(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PrintInsideContainer()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Beaprint.MainPrint("Checking If Inside Container");
|
||||||
|
Beaprint.LinkPrint("", "If the binary cexecsvc.exe or associated service exists, you are inside Docker");
|
||||||
|
Dictionary<string, object> regVal = RegistryHelper.GetRegValues("HKLM", @"System\CurrentControlSet\Services\cexecsvc");
|
||||||
|
bool cexecsvcExist = File.Exists(Environment.SystemDirectory + @"\cexecsvc.exe");
|
||||||
|
if (regVal != null || cexecsvcExist)
|
||||||
|
{
|
||||||
|
Beaprint.BadPrint("You are inside a container");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Beaprint.GoodPrint("You are NOT inside a container");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Beaprint.PrintException(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void PrintAlwaysInstallElevated()
|
static void PrintAlwaysInstallElevated()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -721,13 +769,18 @@ namespace winPEAS.Checks
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string formatString = " {0,-100} {1}\n";
|
string formatString = " {0,-100} {1,-70} {2}\n";
|
||||||
|
|
||||||
Beaprint.NoColorPrint(string.Format($"{formatString}", "Name", "Sddl"));
|
Beaprint.NoColorPrint(string.Format($"{formatString}", "Name", "CurrentUserPerms", "Sddl"));
|
||||||
|
|
||||||
foreach (var namedPipe in NamedPipes.GetNamedPipeInfos())
|
foreach (var namedPipe in NamedPipes.GetNamedPipeInfos())
|
||||||
{
|
{
|
||||||
Beaprint.BadPrint(string.Format(formatString, namedPipe.Name, namedPipe.Sddl));
|
var colors = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{namedPipe.CurrentUserPerms.Replace("[","\\[").Replace("]","\\]"), Beaprint.ansi_color_bad },
|
||||||
|
};
|
||||||
|
|
||||||
|
Beaprint.AnsiPrint(string.Format(formatString, namedPipe.Name, namedPipe.CurrentUserPerms, namedPipe.Sddl), colors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -34,9 +34,7 @@ namespace winPEAS.Helpers
|
|||||||
private static string Advisory =
|
private static string Advisory =
|
||||||
"winpeas should be used for authorized penetration testing and/or educational purposes only." +
|
"winpeas should be used for authorized penetration testing and/or educational purposes only." +
|
||||||
"Any misuse of this software will not be the responsibility of the author or of any other collaborator. " +
|
"Any misuse of this software will not be the responsibility of the author or of any other collaborator. " +
|
||||||
"Use it at your own networks and/or with the network owner's permission.";
|
"Use it at your own devices and/or with the device owner's permission.";
|
||||||
|
|
||||||
private static string Version = "ng";
|
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
///////// PRINT THINGS /////////
|
///////// PRINT THINGS /////////
|
||||||
@ -46,27 +44,27 @@ namespace winPEAS.Helpers
|
|||||||
Console.WriteLine(BLUE + string.Format(@"
|
Console.WriteLine(BLUE + string.Format(@"
|
||||||
{0}((((((((((((((((((((((((((((((((
|
{0}((((((((((((((((((((((((((((((((
|
||||||
{0}(((((((((((((((((((((((((((((((((((((((((((
|
{0}(((((((((((((((((((((((((((((((((((((((((((
|
||||||
{0}(((((((((((((({2}**********/{1}##########{0}.((((((((((((
|
{0}(((((((((((((({2}**********/{1}##########{0}(((((((((((((
|
||||||
{0}(((((((((((/{2}********************/{1}#######{0}.((((((((((
|
{0}(((((((((((({2}********************/{1}#######{0}(((((((((((
|
||||||
{0}(((((((.{2}******************{3}/@@@@@/{0}{2}****{1}######{0}.(((((((((
|
{0}(((((((({2}******************{3}/@@@@@/{0}{2}****{1}######{0}((((((((((
|
||||||
{0}(((((.{2}********************{3}@@@@@@@@@@/{0}{2}***,{1}####{0}.(((((((((
|
{0}(((((({2}********************{3}@@@@@@@@@@/{0}{2}***,{1}####{0}((((((((((
|
||||||
{0}((((.{2}********************{3}/@@@@@%@@@@{0}{2}/********{1}##{0}(((((((((
|
{0}((((({2}********************{3}/@@@@@%@@@@/{0}{2}********{1}##{0}(((((((((
|
||||||
{0}.(({1}############{2}*********{3}/%@@@@@@@@@{0}{2}/************{0}.(((((((
|
{0}((({1}############{2}*********{3}/%@@@@@@@@@/{0}{2}************{0}((((((((
|
||||||
{0}.({1}##################(/{2}******{3}/@@@@@{0}{2}/***************{0}.(((((
|
{0}(({1}##################(/{2}******{3}/@@@@@/{0}{2}***************{0}((((((
|
||||||
{0}.({1}#########################(/{2}**********************{0}.((((
|
{0}(({1}#########################(/{2}**********************{0}(((((
|
||||||
{0}.({1}##############################(/{2}*****************{0}.((((
|
{0}(({1}##############################(/{2}*****************{0}(((((
|
||||||
{0}.({1}###################################(/{2}************{0}.((((
|
{0}(({1}###################################(/{2}************{0}(((((
|
||||||
{0}.({1}#######################################({2}*********{0}.((((
|
{0}(({1}#######################################({2}*********{0}(((((
|
||||||
{0}.({1}#######(,.***.,(###################(..***.{2}*******{0}.((((
|
{0}(({1}#######(,.***.,(###################(..***.{2}*******{0}(((((
|
||||||
{0}.({1}#######*(#####((##################((######/({2}*****{0}.((((
|
{0}(({1}#######*(#####((##################((######/({2}*****{0}(((((
|
||||||
{0}.({1}###################(/***********(##############({0}).((((
|
{0}(({1}###################(/***********(##############({0})(((((
|
||||||
{0}.(({1}#####################/*******(################{0})((((((
|
{0}((({1}#####################/*******(################{0})((((((
|
||||||
{0}.((({1}############################################{0}).(((((
|
{0}(((({1}############################################{0})((((((
|
||||||
{0}..((({1}##########################################{0}).((((((
|
{0}((((({1}##########################################{0})(((((((
|
||||||
{0}....(({1}########################################{0}).((((((
|
{0}(((((({1}########################################{0})(((((((
|
||||||
{0}......(({1}####################################{0}).(((((((
|
{0}(((((((({1}####################################{0})((((((((
|
||||||
{0}((((((((({1}#################################{0}).((((((((
|
{0}((((((((({1}#################################{0})(((((((((
|
||||||
{0}(((((((((/{1}##########################{0}).((((((((
|
{0}(((((((((({1}##########################{0})(((((((((
|
||||||
{0}((((((((((((((((((((((((((((((((((((((
|
{0}((((((((((((((((((((((((((((((((((((((
|
||||||
{0}((((((((((((((((((((((((((((((", LGREEN, GREEN, BLUE, NOCOLOR) + NOCOLOR);
|
{0}((((((((((((((((((((((((((((((", LGREEN, GREEN, BLUE, NOCOLOR) + NOCOLOR);
|
||||||
|
|
||||||
@ -81,15 +79,15 @@ namespace winPEAS.Helpers
|
|||||||
|
|
||||||
// Patreon link
|
// Patreon link
|
||||||
Console.WriteLine(GREEN + string.Format(@"
|
Console.WriteLine(GREEN + string.Format(@"
|
||||||
/---------------------------------------------------------------------------\
|
/---------------------------------------------------------------------------------\
|
||||||
| {1}Do you like PEASS?{0} |
|
| {1}Do you like PEASS?{0} |
|
||||||
|---------------------------------------------------------------------------|
|
|---------------------------------------------------------------------------------|
|
||||||
| {3}Get latest WinPEAS{0} : {2}https://github.com/sponsors/carlospolop{0} |
|
| {3}Get the latest version{0} : {2}https://github.com/sponsors/carlospolop{0} |
|
||||||
| {3}Follow on Twitter{0} : {2}@carlospolopm{0} |
|
| {3}Follow on Twitter{0} : {2}@carlospolopm{0} |
|
||||||
| {3}Respect on HTB{0} : {2}SirBroccoli & makikvues{0} |
|
| {3}Respect on HTB{0} : {2}SirBroccoli {0} |
|
||||||
|---------------------------------------------------------------------------|
|
|---------------------------------------------------------------------------------|
|
||||||
| {1}Thank you!{0} |
|
| {1}Thank you!{0} |
|
||||||
\---------------------------------------------------------------------------/
|
\---------------------------------------------------------------------------------/
|
||||||
", GREEN, BLUE, RED, YELLOW) + NOCOLOR);
|
", GREEN, BLUE, RED, YELLOW) + NOCOLOR);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -101,7 +99,7 @@ namespace winPEAS.Helpers
|
|||||||
PrintBanner();
|
PrintBanner();
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine(YELLOW + " WinPEAS" + GREEN + Version + NOCOLOR + YELLOW + " by @carlospolopm, makikvues(makikvues2[at]gmail[dot]com)" + NOCOLOR);
|
Console.WriteLine(YELLOW + " WinPEAS-ng" + NOCOLOR + YELLOW + " by @carlospolopm" + NOCOLOR);
|
||||||
|
|
||||||
PrintMarketingBanner();
|
PrintMarketingBanner();
|
||||||
|
|
||||||
@ -124,8 +122,6 @@ namespace winPEAS.Helpers
|
|||||||
public static void PrintUsage()
|
public static void PrintUsage()
|
||||||
{
|
{
|
||||||
Console.WriteLine(YELLOW + " [*] " + GREEN + "WinPEAS is a binary to enumerate possible paths to escalate privileges locally" + NOCOLOR);
|
Console.WriteLine(YELLOW + " [*] " + GREEN + "WinPEAS is a binary to enumerate possible paths to escalate privileges locally" + NOCOLOR);
|
||||||
Console.WriteLine(LBLUE + " quiet" + GRAY + " Do not print banner" + NOCOLOR);
|
|
||||||
Console.WriteLine(LBLUE + " notcolor" + GRAY + " Don't use ansi colors (all white)" + NOCOLOR);
|
|
||||||
Console.WriteLine(LBLUE + " domain" + GRAY + " Enumerate domain information" + NOCOLOR);
|
Console.WriteLine(LBLUE + " domain" + GRAY + " Enumerate domain information" + NOCOLOR);
|
||||||
Console.WriteLine(LBLUE + " systeminfo" + GRAY + " Search system information" + NOCOLOR);
|
Console.WriteLine(LBLUE + " systeminfo" + GRAY + " Search system information" + NOCOLOR);
|
||||||
Console.WriteLine(LBLUE + " userinfo" + GRAY + " Search user information" + NOCOLOR);
|
Console.WriteLine(LBLUE + " userinfo" + GRAY + " Search user information" + NOCOLOR);
|
||||||
@ -136,8 +132,12 @@ namespace winPEAS.Helpers
|
|||||||
Console.WriteLine(LBLUE + " windowscreds" + GRAY + " Search windows credentials" + NOCOLOR);
|
Console.WriteLine(LBLUE + " windowscreds" + GRAY + " Search windows credentials" + NOCOLOR);
|
||||||
Console.WriteLine(LBLUE + " browserinfo" + GRAY + " Search browser information" + NOCOLOR);
|
Console.WriteLine(LBLUE + " browserinfo" + GRAY + " Search browser information" + NOCOLOR);
|
||||||
Console.WriteLine(LBLUE + " filesinfo" + GRAY + " Search generic files that can contains credentials" + NOCOLOR);
|
Console.WriteLine(LBLUE + " filesinfo" + GRAY + " Search generic files that can contains credentials" + NOCOLOR);
|
||||||
Console.WriteLine(LBLUE + " fileanalysis" + GRAY + " Search specific files that can contains credentials" + NOCOLOR);
|
Console.WriteLine(LBLUE + " fileanalysis" + GRAY + " Search specific files that can contains credentials and for regexes inside files" + NOCOLOR);
|
||||||
Console.WriteLine(LBLUE + " eventsinfo" + GRAY + " Display interesting events information" + NOCOLOR);
|
Console.WriteLine(LBLUE + " eventsinfo" + GRAY + " Display interesting events information" + NOCOLOR);
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine(LBLUE + " quiet" + GRAY + " Do not print banner" + NOCOLOR);
|
||||||
|
Console.WriteLine(LBLUE + " notcolor" + GRAY + " Don't use ansi colors (all white)" + NOCOLOR);
|
||||||
|
Console.WriteLine(LBLUE + " searchpf" + GRAY + " Search credentials via regex also in Program Files folders" + NOCOLOR);
|
||||||
Console.WriteLine(LBLUE + " wait" + GRAY + " Wait for user input between checks" + NOCOLOR);
|
Console.WriteLine(LBLUE + " wait" + GRAY + " Wait for user input between checks" + NOCOLOR);
|
||||||
Console.WriteLine(LBLUE + " debug" + GRAY + " Display debugging information - memory usage, method execution time" + NOCOLOR);
|
Console.WriteLine(LBLUE + " debug" + GRAY + " Display debugging information - memory usage, method execution time" + NOCOLOR);
|
||||||
Console.WriteLine(LBLUE + " log[=logfile]" + GRAY + $" Log all output to file defined as logfile, or to \"{Checks.Checks.DefaultLogFile}\" if not specified" + NOCOLOR);
|
Console.WriteLine(LBLUE + " log[=logfile]" + GRAY + $" Log all output to file defined as logfile, or to \"{Checks.Checks.DefaultLogFile}\" if not specified" + NOCOLOR);
|
||||||
@ -230,6 +230,11 @@ namespace winPEAS.Helpers
|
|||||||
GrayPrint($" [X] Exception: {message}");
|
GrayPrint($" [X] Exception: {message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void PrintNoNL(string message)
|
||||||
|
{
|
||||||
|
Console.Write(message);
|
||||||
|
}
|
||||||
|
|
||||||
public static void AnsiPrint(string to_print, Dictionary<string, string> ansi_colors_regexp)
|
public static void AnsiPrint(string to_print, Dictionary<string, string> ansi_colors_regexp)
|
||||||
{
|
{
|
||||||
if (to_print.Trim().Length > 0)
|
if (to_print.Trim().Length > 0)
|
||||||
@ -269,7 +274,7 @@ namespace winPEAS.Helpers
|
|||||||
{
|
{
|
||||||
foreach (KeyValuePair<string, string> entry in dicprint)
|
foreach (KeyValuePair<string, string> entry in dicprint)
|
||||||
{
|
{
|
||||||
if (delete_nulls && string.IsNullOrEmpty(entry.Value.Trim()))
|
if (delete_nulls && (entry.Value == null || string.IsNullOrEmpty(entry.Value.Trim())))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -295,6 +300,7 @@ namespace winPEAS.Helpers
|
|||||||
Console.WriteLine(line);
|
Console.WriteLine(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DictPrint(Dictionary<string, string> dicprint, bool delete_nulls)
|
public static void DictPrint(Dictionary<string, string> dicprint, bool delete_nulls)
|
||||||
{
|
{
|
||||||
if (dicprint.Count > 0)
|
if (dicprint.Count > 0)
|
||||||
|
@ -5,13 +5,15 @@
|
|||||||
public string Filename { get; }
|
public string Filename { get; }
|
||||||
public string Extension { get; }
|
public string Extension { get; }
|
||||||
public string FullPath { get; }
|
public string FullPath { get; }
|
||||||
|
public long Size { get; }
|
||||||
public bool IsDirectory { get; }
|
public bool IsDirectory { get; }
|
||||||
|
|
||||||
public CustomFileInfo(string filename, string extension, string fullPath, bool isDirectory)
|
public CustomFileInfo(string filename, string extension, string fullPath, long size, bool isDirectory)
|
||||||
{
|
{
|
||||||
Filename = filename;
|
Filename = filename;
|
||||||
Extension = extension;
|
Extension = extension;
|
||||||
FullPath = fullPath;
|
FullPath = fullPath;
|
||||||
|
Size = size;
|
||||||
IsDirectory = isDirectory;
|
IsDirectory = isDirectory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
601
winPEAS/winPEASexe/winPEAS/Helpers/HandlesHelper.cs
Normal file
601
winPEAS/winPEASexe/winPEAS/Helpers/HandlesHelper.cs
Normal file
@ -0,0 +1,601 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace winPEAS.Helpers
|
||||||
|
{
|
||||||
|
internal class HandlesHelper
|
||||||
|
{
|
||||||
|
private const int CNST_SYSTEM_EXTENDED_HANDLE_INFORMATION = 64;
|
||||||
|
public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
|
||||||
|
public const int DUPLICATE_SAME_ACCESS = 0x2;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||||
|
public struct FILE_NAME_INFO
|
||||||
|
{
|
||||||
|
public int FileNameLength;
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1000)]
|
||||||
|
public string FileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct THREAD_BASIC_INFORMATION
|
||||||
|
{
|
||||||
|
public uint ExitStatus;
|
||||||
|
public IntPtr TebBaseAdress;
|
||||||
|
public CLIENT_ID ClientId;
|
||||||
|
public uint AffinityMask;
|
||||||
|
public uint Priority;
|
||||||
|
public uint BasePriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct CLIENT_ID
|
||||||
|
{
|
||||||
|
public int UniqueProcess;
|
||||||
|
public int UniqueThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct PROCESS_BASIC_INFORMATION
|
||||||
|
{
|
||||||
|
public int ExitStatus;
|
||||||
|
public IntPtr PebBaseAddress;
|
||||||
|
public IntPtr AffinityMask;
|
||||||
|
public int BasePriority;
|
||||||
|
public IntPtr UniqueProcessId;
|
||||||
|
public IntPtr InheritedFromUniqueProcessId;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
|
||||||
|
{
|
||||||
|
public IntPtr Object;
|
||||||
|
public UIntPtr UniqueProcessId;
|
||||||
|
public IntPtr HandleValue;
|
||||||
|
public uint GrantedAccess;
|
||||||
|
public ushort CreatorBackTraceIndex;
|
||||||
|
public ushort ObjectTypeIndex;
|
||||||
|
public uint HandleAttributes;
|
||||||
|
public uint Reserved;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum ProcessAccessFlags : uint
|
||||||
|
{
|
||||||
|
All = 0x001F0FFF,
|
||||||
|
Terminate = 0x00000001,
|
||||||
|
CreateThread = 0x00000002,
|
||||||
|
VMOperation = 0x00000008,
|
||||||
|
VMRead = 0x00000010,
|
||||||
|
VMWrite = 0x00000020,
|
||||||
|
DupHandle = 0x00000040,
|
||||||
|
SetInformation = 0x00000200,
|
||||||
|
QueryInformation = 0x00000400,
|
||||||
|
QueryLimitedInformation = 0x1000,
|
||||||
|
Synchronize = 0x00100000
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct OBJECT_BASIC_INFORMATION
|
||||||
|
{ // Information Class 0
|
||||||
|
public int Attributes;
|
||||||
|
public int GrantedAccess;
|
||||||
|
public int HandleCount;
|
||||||
|
public int PointerCount;
|
||||||
|
public int PagedPoolUsage;
|
||||||
|
public int NonPagedPoolUsage;
|
||||||
|
public int Reserved1;
|
||||||
|
public int Reserved2;
|
||||||
|
public int Reserved3;
|
||||||
|
public int NameInformationLength;
|
||||||
|
public int TypeInformationLength;
|
||||||
|
public int SecurityDescriptorLength;
|
||||||
|
public System.Runtime.InteropServices.ComTypes.FILETIME CreateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct UNICODE_STRING
|
||||||
|
{
|
||||||
|
public ushort Length;
|
||||||
|
public ushort MaximumLength;
|
||||||
|
public IntPtr Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct OBJECT_NAME_INFORMATION
|
||||||
|
{ // Information Class 1
|
||||||
|
public UNICODE_STRING Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct OBJECT_TYPE_INFORMATION
|
||||||
|
{ // Information Class 1
|
||||||
|
public UNICODE_STRING Name;
|
||||||
|
public ulong TotalNumberOfObjects;
|
||||||
|
public ulong TotalNumberOfHandles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ObjectInformationClass : int
|
||||||
|
{
|
||||||
|
ObjectBasicInformation = 0,
|
||||||
|
ObjectNameInformation = 1,
|
||||||
|
ObjectTypeInformation = 2,
|
||||||
|
ObjectAllTypesInformation = 3,
|
||||||
|
ObjectHandleInformation = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct VULNERABLE_HANDLER_INFO
|
||||||
|
{
|
||||||
|
public string handlerType;
|
||||||
|
public bool isVuln;
|
||||||
|
public string reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct PT_RELEVANT_INFO
|
||||||
|
{
|
||||||
|
public int pid;
|
||||||
|
public string name;
|
||||||
|
public string imagePath;
|
||||||
|
public string userName;
|
||||||
|
public string userSid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct KEY_RELEVANT_INFO
|
||||||
|
{
|
||||||
|
public string hive;
|
||||||
|
public string path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Check if the given handler is exploitable
|
||||||
|
public static VULNERABLE_HANDLER_INFO checkExploitaible(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX h, string typeName)
|
||||||
|
{
|
||||||
|
VULNERABLE_HANDLER_INFO vulnHandler = new VULNERABLE_HANDLER_INFO();
|
||||||
|
vulnHandler.handlerType = typeName;
|
||||||
|
|
||||||
|
if (typeName == "process")
|
||||||
|
{
|
||||||
|
// Hex perms from https://docs.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights and https://github.com/buffer/maltracer/blob/master/defines.py
|
||||||
|
|
||||||
|
//PROCESS_ALL_ACCESS
|
||||||
|
if ((h.GrantedAccess & 0x001F0FFF) == h.GrantedAccess)
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = "PROCESS_ALL_ACCESS";
|
||||||
|
}
|
||||||
|
|
||||||
|
//PROCESS_CREATE_PROCESS
|
||||||
|
else if ((h.GrantedAccess & 0x0080) == h.GrantedAccess)
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = "PROCESS_CREATE_PROCESS";
|
||||||
|
}
|
||||||
|
|
||||||
|
//PROCESS_CREATE_THREAD
|
||||||
|
else if ((h.GrantedAccess & 0x0002) == h.GrantedAccess)
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = "PROCESS_CREATE_THREAD";
|
||||||
|
}
|
||||||
|
|
||||||
|
//PROCESS_DUP_HANDLE
|
||||||
|
else if ((h.GrantedAccess & 0x0040) == h.GrantedAccess)
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = "PROCESS_DUP_HANDLE";
|
||||||
|
}
|
||||||
|
|
||||||
|
//PROCESS_VM_WRITE
|
||||||
|
else if ((h.GrantedAccess & 0x0020) == h.GrantedAccess)
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = "PROCESS_VM_WRITE";
|
||||||
|
|
||||||
|
if ((h.GrantedAccess & 0x0010) == h.GrantedAccess)
|
||||||
|
vulnHandler.reason += "& PROCESS_VM_READ";
|
||||||
|
|
||||||
|
if ((h.GrantedAccess & 0x0008) == h.GrantedAccess)
|
||||||
|
vulnHandler.reason += "& PROCESS_VM_OPERATION";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (typeName == "thread")
|
||||||
|
{
|
||||||
|
// Codes from https://docs.microsoft.com/en-us/windows/win32/procthread/thread-security-and-access-rights and https://github.com/x0r19x91/code-injection/blob/master/inject.asm
|
||||||
|
|
||||||
|
//THREAD_ALL_ACCESS
|
||||||
|
if ((h.GrantedAccess & 0x1f03ff) == h.GrantedAccess)
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = "THREAD_ALL_ACCESS";
|
||||||
|
}
|
||||||
|
|
||||||
|
//THREAD_DIRECT_IMPERSONATION
|
||||||
|
else if ((h.GrantedAccess & 0x0200) == h.GrantedAccess)
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = "THREAD_DIRECT_IMPERSONATION";
|
||||||
|
}
|
||||||
|
|
||||||
|
//THREAD_GET_CONTEXT & THREAD_SET_CONTEXT
|
||||||
|
else if (((h.GrantedAccess & 0x0008) == h.GrantedAccess) && ((h.GrantedAccess & 0x0010) == h.GrantedAccess))
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = "THREAD_GET_CONTEXT & THREAD_SET_CONTEXT";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (typeName == "file")
|
||||||
|
{
|
||||||
|
|
||||||
|
string perm = PermissionsHelper.PermInt2Str((int)h.GrantedAccess, PermissionType.WRITEABLE_OR_EQUIVALENT);
|
||||||
|
if (perm != null && perm.Length> 0)
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = perm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (typeName == "key")
|
||||||
|
{
|
||||||
|
string perm = PermissionsHelper.PermInt2Str((int)h.GrantedAccess, PermissionType.WRITEABLE_OR_EQUIVALENT_REG);
|
||||||
|
if (perm != null && perm.Length > 0)
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = perm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (typeName == "section")
|
||||||
|
{
|
||||||
|
// Perms from
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/secauthz/standard-access-rights
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/secauthz/access-mask-format
|
||||||
|
// https://github.com/lab52io/LeakedHandlesFinder/blob/master/LeakedHandlesFinder/LeakedHandlesFinder.cpp
|
||||||
|
|
||||||
|
|
||||||
|
//MAP_WRITE
|
||||||
|
if ((h.GrantedAccess & 0x2) == h.GrantedAccess)
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = "MAP_WRITE (Research Needed)";
|
||||||
|
}
|
||||||
|
//DELETE, READ_CONTROL, WRITE_DAC, and WRITE_OWNER = STANDARD_RIGHTS_ALL
|
||||||
|
else if ((h.GrantedAccess & 0xf0000) == h.GrantedAccess)
|
||||||
|
{
|
||||||
|
vulnHandler.isVuln = true;
|
||||||
|
vulnHandler.reason = "STANDARD_RIGHTS_ALL (Research Needed)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vulnHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a found handler get what type is it.
|
||||||
|
public static string GetObjectType(IntPtr handle)
|
||||||
|
{
|
||||||
|
OBJECT_TYPE_INFORMATION basicType = new OBJECT_TYPE_INFORMATION();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IntPtr _basic = IntPtr.Zero;
|
||||||
|
string name;
|
||||||
|
int nameLength = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_basic = Marshal.AllocHGlobal(0x1000);
|
||||||
|
|
||||||
|
Native.Ntdll.NtQueryObject(handle, (int)ObjectInformationClass.ObjectTypeInformation, _basic, 0x1000, ref nameLength);
|
||||||
|
basicType = (OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(_basic, basicType.GetType());
|
||||||
|
name = Marshal.PtrToStringUni(basicType.Name.Buffer, basicType.Name.Length >> 1);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (_basic != IntPtr.Zero)
|
||||||
|
Marshal.FreeHGlobal(_basic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the name of the handler (if any)
|
||||||
|
public static string GetObjectName(IntPtr handle)
|
||||||
|
{
|
||||||
|
OBJECT_BASIC_INFORMATION basicInfo = new OBJECT_BASIC_INFORMATION();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
IntPtr _basic = IntPtr.Zero;
|
||||||
|
int nameLength = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_basic = Marshal.AllocHGlobal(Marshal.SizeOf(basicInfo));
|
||||||
|
|
||||||
|
Native.Ntdll.NtQueryObject(handle, (int)ObjectInformationClass.ObjectBasicInformation, _basic, Marshal.SizeOf(basicInfo), ref nameLength);
|
||||||
|
basicInfo = (OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(_basic, basicInfo.GetType());
|
||||||
|
nameLength = basicInfo.NameInformationLength;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (_basic != IntPtr.Zero)
|
||||||
|
Marshal.FreeHGlobal(_basic);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nameLength == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBJECT_NAME_INFORMATION nameInfo = new OBJECT_NAME_INFORMATION();
|
||||||
|
IntPtr _objectName = Marshal.AllocHGlobal(nameLength);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while ((uint)(Native.Ntdll.NtQueryObject(handle, (int)ObjectInformationClass.ObjectNameInformation, _objectName, nameLength, ref nameLength)) == STATUS_INFO_LENGTH_MISMATCH)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(_objectName);
|
||||||
|
_objectName = Marshal.AllocHGlobal(nameLength);
|
||||||
|
}
|
||||||
|
nameInfo = (OBJECT_NAME_INFORMATION)Marshal.PtrToStructure(_objectName, nameInfo.GetType());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(_objectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (nameInfo.Name.Length > 0)
|
||||||
|
return Marshal.PtrToStringUni(nameInfo.Name.Buffer, nameInfo.Name.Length >> 1);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all handlers inside the system
|
||||||
|
public static List<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> GetAllHandlers()
|
||||||
|
{
|
||||||
|
bool is_64 = Marshal.SizeOf(typeof(IntPtr)) == 8 ? true : false;
|
||||||
|
int infoLength = 0x10000;
|
||||||
|
int length = 0;
|
||||||
|
IntPtr _info = Marshal.AllocHGlobal(infoLength);
|
||||||
|
IntPtr _handle = IntPtr.Zero;
|
||||||
|
long handleCount = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Try to find the size
|
||||||
|
while ((Native.Ntdll.NtQuerySystemInformation(CNST_SYSTEM_EXTENDED_HANDLE_INFORMATION, _info, infoLength, ref length)) == STATUS_INFO_LENGTH_MISMATCH)
|
||||||
|
{
|
||||||
|
infoLength = length;
|
||||||
|
Marshal.FreeHGlobal(_info);
|
||||||
|
_info = Marshal.AllocHGlobal(infoLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (is_64)
|
||||||
|
{
|
||||||
|
handleCount = Marshal.ReadInt64(_info);
|
||||||
|
_handle = new IntPtr(_info.ToInt64() + 16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handleCount = Marshal.ReadInt32(_info);
|
||||||
|
_handle = new IntPtr(_info.ToInt32() + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo = new SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX();
|
||||||
|
List<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> handles = new List<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX>();
|
||||||
|
|
||||||
|
int infoSize = Marshal.SizeOf(handleInfo);
|
||||||
|
Type infoType = handleInfo.GetType();
|
||||||
|
|
||||||
|
|
||||||
|
for (long i = 0; i < handleCount; i++)
|
||||||
|
{
|
||||||
|
if (is_64)
|
||||||
|
{
|
||||||
|
handleInfo = (SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX)Marshal.PtrToStructure(_handle, infoType);
|
||||||
|
_handle = new IntPtr(_handle.ToInt64() + infoSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handleInfo = (SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX)Marshal.PtrToStructure(_handle, infoType);
|
||||||
|
_handle = new IntPtr(_handle.ToInt32() + infoSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
handles.Add(handleInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return handles;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the owner of a process given the PID
|
||||||
|
public static Dictionary<string, string> GetProcU(Process p)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> data = new Dictionary<string, string>();
|
||||||
|
data["name"] = "";
|
||||||
|
data["sid"] = "";
|
||||||
|
IntPtr pHandle = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Native.Advapi32.OpenProcessToken(p.Handle, 8, out pHandle);
|
||||||
|
WindowsIdentity WI = new WindowsIdentity(pHandle);
|
||||||
|
string uSEr = WI.Name;
|
||||||
|
string sid = WI.User.Value;
|
||||||
|
data["name"] = uSEr.Contains(@"\") ? uSEr.Substring(uSEr.IndexOf(@"\") + 1) : uSEr;
|
||||||
|
data["sid"] = sid;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (pHandle != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Native.Kernel32.CloseHandle(pHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get info of the process given the PID
|
||||||
|
public static PT_RELEVANT_INFO getProcInfoById(int pid)
|
||||||
|
{
|
||||||
|
PT_RELEVANT_INFO pri = new PT_RELEVANT_INFO();
|
||||||
|
|
||||||
|
Process proc = Process.GetProcessById(pid);
|
||||||
|
Dictionary<string,string> user = GetProcU(proc);
|
||||||
|
|
||||||
|
StringBuilder fileName = new StringBuilder(2000);
|
||||||
|
Native.Psapi.GetProcessImageFileName(proc.Handle, fileName, 2000);
|
||||||
|
|
||||||
|
pri.pid = pid;
|
||||||
|
pri.name = proc.ProcessName;
|
||||||
|
pri.userName = user["name"];
|
||||||
|
pri.userSid = user["sid"];
|
||||||
|
pri.imagePath = fileName.ToString();
|
||||||
|
|
||||||
|
return pri;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get information of a handler of type process
|
||||||
|
public static PT_RELEVANT_INFO getProcessHandlerInfo(IntPtr handle)
|
||||||
|
{
|
||||||
|
PT_RELEVANT_INFO pri = new PT_RELEVANT_INFO();
|
||||||
|
PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION();
|
||||||
|
IntPtr[] pbi_arr = new IntPtr[6];
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
|
||||||
|
int retLength = 0;
|
||||||
|
|
||||||
|
// Try to find the size
|
||||||
|
uint status = (uint)Native.Ntdll.NtQueryInformationProcess(handle, 0, pbi_arr, 48, ref retLength);
|
||||||
|
if (status == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
//pbi.ExitStatus = (int)pbi_arr[0];
|
||||||
|
//pbi.PebBaseAddress = pbi_arr[1];
|
||||||
|
//pbi.AffinityMask = pbi_arr[2];
|
||||||
|
//pbi.BasePriority = (int)pbi_arr[3];
|
||||||
|
pbi.UniqueProcessId = pbi_arr[4];
|
||||||
|
//pbi.InheritedFromUniqueProcessId = pbi_arr[5];
|
||||||
|
pid = (int)pbi.UniqueProcessId;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pid = (int)Native.Kernel32.GetProcessId(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid == 0)
|
||||||
|
return pri;
|
||||||
|
|
||||||
|
return getProcInfoById(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get information of a handler of type thread
|
||||||
|
public static PT_RELEVANT_INFO getThreadHandlerInfo(IntPtr handle)
|
||||||
|
{
|
||||||
|
PT_RELEVANT_INFO pri = new PT_RELEVANT_INFO();
|
||||||
|
THREAD_BASIC_INFORMATION tbi = new THREAD_BASIC_INFORMATION();
|
||||||
|
IntPtr[] tbi_arr = new IntPtr[6];
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
|
||||||
|
/* You could also get the PID using this method
|
||||||
|
int retLength = 0;
|
||||||
|
uint status = (uint)NtQueryInformationThread(handle, 0, tbi_arr, 48, ref retLength);
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
return pri;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = (int)GetProcessIdOfThread(handle);
|
||||||
|
|
||||||
|
CLIENT_ID ci = new CLIENT_ID();
|
||||||
|
|
||||||
|
tbi.ExitStatus = (uint)tbi_arr[0];
|
||||||
|
tbi.TebBaseAdress = tbi_arr[1];
|
||||||
|
tbi.ClientId = tbi_arr[2];
|
||||||
|
tbi.AffinityMask = (uint)tbi_arr[3];
|
||||||
|
tbi.Priority = (uint)tbi_arr[4];
|
||||||
|
tbi.BasePriority = (uint)tbi_arr[5];*/
|
||||||
|
|
||||||
|
pid = (int)Native.Kernel32.GetProcessIdOfThread(handle);
|
||||||
|
if (pid == 0)
|
||||||
|
return pri;
|
||||||
|
|
||||||
|
return getProcInfoById(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get information of a handler of type key
|
||||||
|
public static KEY_RELEVANT_INFO getKeyHandlerInfo(IntPtr handle)
|
||||||
|
{
|
||||||
|
KEY_RELEVANT_INFO kri = new KEY_RELEVANT_INFO();
|
||||||
|
int retLength = 0;
|
||||||
|
|
||||||
|
// Get KeyNameInformation (3)
|
||||||
|
uint status = (uint)Native.Ntdll.NtQueryKey(handle, 3, null, 0, ref retLength);
|
||||||
|
var keyInformation = new byte[retLength];
|
||||||
|
status = (uint)Native.Ntdll.NtQueryKey(handle, 3, keyInformation, retLength, ref retLength);
|
||||||
|
|
||||||
|
string path = Encoding.Unicode.GetString(keyInformation, 4, keyInformation.Length - 4).ToLower();
|
||||||
|
string hive = "";
|
||||||
|
|
||||||
|
// https://groups.google.com/g/comp.os.ms-windows.programmer.win32/c/nCs-9zFRm6I
|
||||||
|
if (path.StartsWith(@"\registry\machine"))
|
||||||
|
{
|
||||||
|
path = path.Replace(@"\registry\machine", "");
|
||||||
|
hive = "HKLM";
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (path.StartsWith(@"\registry\user"))
|
||||||
|
{
|
||||||
|
path = path.Replace(@"\registry\user", "");
|
||||||
|
hive = "HKU";
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{ // This shouldn't be needed
|
||||||
|
if (path.StartsWith("\\"))
|
||||||
|
path = path.Substring(1);
|
||||||
|
hive = Helpers.Registry.RegistryHelper.CheckIfExists(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.StartsWith("\\"))
|
||||||
|
path = path.Substring(1);
|
||||||
|
|
||||||
|
kri.hive = hive;
|
||||||
|
kri.path = path;
|
||||||
|
|
||||||
|
return kri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
88
winPEAS/winPEASexe/winPEAS/Helpers/ProgressBar.cs
Normal file
88
winPEAS/winPEASexe/winPEAS/Helpers/ProgressBar.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace winPEAS.Helpers
|
||||||
|
{
|
||||||
|
internal class ProgressBar : IDisposable, IProgress<double>
|
||||||
|
{
|
||||||
|
private const int blockCount = 10;
|
||||||
|
private readonly TimeSpan animationInterval = TimeSpan.FromSeconds(1.0 / 8);
|
||||||
|
private const string animation = @"|/-\";
|
||||||
|
|
||||||
|
private readonly Timer timer;
|
||||||
|
|
||||||
|
private double currentProgress = 0;
|
||||||
|
private string currentText = string.Empty;
|
||||||
|
private bool disposed = false;
|
||||||
|
private int animationIndex = 0;
|
||||||
|
|
||||||
|
public ProgressBar()
|
||||||
|
{
|
||||||
|
timer = new Timer(TimerHandler, new object(), animationInterval, animationInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Report(double value)
|
||||||
|
{
|
||||||
|
// Make sure value is in [0..1] range
|
||||||
|
value = Math.Max(0, Math.Min(1, value));
|
||||||
|
Interlocked.Exchange(ref currentProgress, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TimerHandler(object state)
|
||||||
|
{
|
||||||
|
lock (timer)
|
||||||
|
{
|
||||||
|
if (disposed) return;
|
||||||
|
|
||||||
|
int progressBlockCount = (int)(currentProgress * blockCount);
|
||||||
|
int percent = (int)(currentProgress * 100);
|
||||||
|
string text = string.Format("[{0}{1}] {2,3}% {3}",
|
||||||
|
new string('#', progressBlockCount), new string('-', blockCount - progressBlockCount),
|
||||||
|
percent,
|
||||||
|
animation[animationIndex++ % animation.Length]);
|
||||||
|
UpdateText(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateText(string text)
|
||||||
|
{
|
||||||
|
// Get length of common portion
|
||||||
|
int commonPrefixLength = 0;
|
||||||
|
int commonLength = Math.Min(currentText.Length, text.Length);
|
||||||
|
while (commonPrefixLength < commonLength && text[commonPrefixLength] == currentText[commonPrefixLength])
|
||||||
|
{
|
||||||
|
commonPrefixLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backtrack to the first differing character
|
||||||
|
StringBuilder outputBuilder = new StringBuilder();
|
||||||
|
outputBuilder.Append('\b', currentText.Length - commonPrefixLength);
|
||||||
|
|
||||||
|
// Output new suffix
|
||||||
|
outputBuilder.Append(text.Substring(commonPrefixLength));
|
||||||
|
|
||||||
|
// If the new text is shorter than the old one: delete overlapping characters
|
||||||
|
int overlapCount = currentText.Length - text.Length;
|
||||||
|
if (overlapCount > 0)
|
||||||
|
{
|
||||||
|
outputBuilder.Append(' ', overlapCount);
|
||||||
|
outputBuilder.Append('\b', overlapCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.Write(outputBuilder);
|
||||||
|
currentText = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
lock (timer)
|
||||||
|
{
|
||||||
|
disposed = true;
|
||||||
|
UpdateText(string.Empty);
|
||||||
|
timer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,18 @@ namespace winPEAS.Helpers.Registry
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
/// Functions related to obtain keys and values from the registry
|
/// Functions related to obtain keys and values from the registry
|
||||||
/// Some parts adapted from Seatbelt
|
/// Some parts adapted from Seatbelt
|
||||||
|
public static Microsoft.Win32.RegistryKey GetReg(string hive, string path)
|
||||||
|
{
|
||||||
|
if (hive == "HKCU")
|
||||||
|
return Microsoft.Win32.Registry.CurrentUser.OpenSubKey(path);
|
||||||
|
|
||||||
|
else if (hive == "HKU")
|
||||||
|
return Microsoft.Win32.Registry.Users.OpenSubKey(path);
|
||||||
|
|
||||||
|
else
|
||||||
|
return Microsoft.Win32.Registry.LocalMachine.OpenSubKey(path);
|
||||||
|
}
|
||||||
|
|
||||||
public static string GetRegValue(string hive, string path, string value)
|
public static string GetRegValue(string hive, string path, string value)
|
||||||
{
|
{
|
||||||
// returns a single registry value under the specified path in the specified hive (HKLM/HKCU)
|
// returns a single registry value under the specified path in the specified hive (HKLM/HKCU)
|
||||||
@ -174,5 +186,29 @@ namespace winPEAS.Helpers.Registry
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string CheckIfExists(string path)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(path);
|
||||||
|
if (key != null)
|
||||||
|
return "HKLM";
|
||||||
|
|
||||||
|
key = Microsoft.Win32.Registry.Users.OpenSubKey(path);
|
||||||
|
if (key != null)
|
||||||
|
return "HKU";
|
||||||
|
|
||||||
|
key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(path);
|
||||||
|
if (key != null)
|
||||||
|
return "HKCU";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,25 @@ namespace winPEAS.Helpers.Search
|
|||||||
public static string SystemDrive = Environment.GetEnvironmentVariable("SystemDrive");
|
public static string SystemDrive = Environment.GetEnvironmentVariable("SystemDrive");
|
||||||
private static string GlobalPattern = "*";
|
private static string GlobalPattern = "*";
|
||||||
|
|
||||||
|
public static List<string> StaticExtensions = new List<string>() {
|
||||||
|
// archives
|
||||||
|
".7z", ".tar", ".zip", ".gz",
|
||||||
|
|
||||||
|
// audio/video
|
||||||
|
".avi", ".mp3", ".mp4", ".wav", ".wmf", ".wmv", ".ts", ".pak",
|
||||||
|
|
||||||
|
// icons
|
||||||
|
".ico",
|
||||||
|
|
||||||
|
// fonts
|
||||||
|
".eot", ".fnt", ".fon", ".otf", ".odttf", ".ttc", ".ttf", ".woff", "woff2", "woff3",
|
||||||
|
|
||||||
|
// images
|
||||||
|
".bmp", ".emf", ".gif", ".pm",
|
||||||
|
".jif", ".jfi", ".jfif", ".jpe", ".jpeg", ".jpg",
|
||||||
|
".png", ".psd", ".raw", ".svg", ".svgz", ".tif", ".tiff", ".webp",
|
||||||
|
};
|
||||||
|
|
||||||
public static List<CustomFileInfo> GetFilesFast(string folder, string pattern = "*", HashSet<string> excludedDirs = null, bool isFoldersIncluded = false)
|
public static List<CustomFileInfo> GetFilesFast(string folder, string pattern = "*", HashSet<string> excludedDirs = null, bool isFoldersIncluded = false)
|
||||||
{
|
{
|
||||||
ConcurrentBag<CustomFileInfo> files = new ConcurrentBag<CustomFileInfo>();
|
ConcurrentBag<CustomFileInfo> files = new ConcurrentBag<CustomFileInfo>();
|
||||||
@ -52,17 +71,25 @@ namespace winPEAS.Helpers.Search
|
|||||||
Parallel.ForEach(GetStartDirectories(d.FullName, files, pattern, isFoldersIncluded), (dir) =>
|
Parallel.ForEach(GetStartDirectories(d.FullName, files, pattern, isFoldersIncluded), (dir) =>
|
||||||
{
|
{
|
||||||
GetFiles(dir.FullName, pattern).ForEach(
|
GetFiles(dir.FullName, pattern).ForEach(
|
||||||
(f) => {
|
(f) =>
|
||||||
CustomFileInfo file_info = new CustomFileInfo(f.Name, f.Extension, f.FullName, false);
|
{
|
||||||
files.Add(file_info);
|
if (!StaticExtensions.Contains(f.Extension.ToLower()))
|
||||||
|
{
|
||||||
CustomFileInfo file_dir = new CustomFileInfo(f.Directory.Name, "", f.Directory.FullName, true);
|
// It should always be lesss than 260, but some times it isn't so this will bypass that file
|
||||||
if (!known_dirs.Contains(file_dir.FullPath))
|
if (f.FullName.Length <= 260)
|
||||||
{
|
{
|
||||||
known_dirs.Add(file_dir.FullPath);
|
CustomFileInfo file_info = new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false);
|
||||||
files.Add(file_dir);
|
files.Add(file_info);
|
||||||
}
|
|
||||||
|
CustomFileInfo file_dir = new CustomFileInfo(f.Directory.Name, "", f.Directory.FullName, 0, true);
|
||||||
|
if (!known_dirs.Contains(file_dir.FullPath))
|
||||||
|
{
|
||||||
|
known_dirs.Add(file_dir.FullPath);
|
||||||
|
files.Add(file_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
) ;
|
) ;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -142,13 +169,14 @@ namespace winPEAS.Helpers.Search
|
|||||||
{
|
{
|
||||||
foreach (var directory in directories)
|
foreach (var directory in directories)
|
||||||
{
|
{
|
||||||
files.Add(new CustomFileInfo(directory.Name, null, directory.FullName, true));
|
files.Add(new CustomFileInfo(directory.Name, null, directory.FullName, 0, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var f in dirInfo.GetFiles(pattern))
|
foreach (var f in dirInfo.GetFiles(pattern))
|
||||||
{
|
{
|
||||||
files.Add(new CustomFileInfo(f.Name, f.Extension, f.FullName, false));
|
if (!StaticExtensions.Contains(f.Extension.ToLower()))
|
||||||
|
files.Add(new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (directories.Length > 1) return new List<DirectoryInfo>(directories);
|
if (directories.Length > 1) return new List<DirectoryInfo>(directories);
|
||||||
|
@ -2,6 +2,24 @@
|
|||||||
|
|
||||||
namespace winPEAS.Helpers.YamlConfig
|
namespace winPEAS.Helpers.YamlConfig
|
||||||
{
|
{
|
||||||
|
public class YamlRegexConfig
|
||||||
|
{
|
||||||
|
public class RegularExpressions
|
||||||
|
{
|
||||||
|
public string name { get; set; }
|
||||||
|
public RegularExpression[] regexes { get; set; }
|
||||||
|
public class RegularExpression {
|
||||||
|
public string name { get; set; }
|
||||||
|
public string regex { get; set; }
|
||||||
|
|
||||||
|
public bool caseinsensitive { get; set; }
|
||||||
|
|
||||||
|
public string disable { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegularExpressions[] regular_expresions { get; set; }
|
||||||
|
}
|
||||||
public class YamlConfig
|
public class YamlConfig
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -24,6 +42,7 @@ namespace winPEAS.Helpers.YamlConfig
|
|||||||
public bool? remove_empty_lines { get; set; }
|
public bool? remove_empty_lines { get; set; }
|
||||||
// public string remove_path { get; set; } // not used in Winpeas
|
// public string remove_path { get; set; } // not used in Winpeas
|
||||||
public string remove_regex { get; set; }
|
public string remove_regex { get; set; }
|
||||||
|
public string remove_path { get; set; }
|
||||||
// public string[] search_in { get; set; } // not used in Winpeas
|
// public string[] search_in { get; set; } // not used in Winpeas
|
||||||
public string type { get; set; }
|
public string type { get; set; }
|
||||||
public FileParam[] files { get; set; }
|
public FileParam[] files { get; set; }
|
||||||
|
@ -4,13 +4,49 @@ using System.IO;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using static winPEAS.Helpers.YamlConfig.YamlConfig;
|
using static winPEAS.Helpers.YamlConfig.YamlConfig;
|
||||||
|
using static winPEAS.Helpers.YamlConfig.YamlRegexConfig;
|
||||||
|
|
||||||
|
|
||||||
namespace winPEAS.Helpers.YamlConfig
|
namespace winPEAS.Helpers.YamlConfig
|
||||||
{
|
{
|
||||||
internal class YamlConfigHelper
|
internal class YamlConfigHelper
|
||||||
{
|
{
|
||||||
|
const string REGEXES_FILES = "regexes.yaml";
|
||||||
const string SENSITIVE_FILES = "sensitive_files.yaml";
|
const string SENSITIVE_FILES = "sensitive_files.yaml";
|
||||||
|
|
||||||
|
public static YamlRegexConfig GetRegexesSearchConfig()
|
||||||
|
{
|
||||||
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
|
var resourceName = assembly.GetManifestResourceNames().Where(i => i.EndsWith(REGEXES_FILES)).FirstOrDefault();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
||||||
|
using (StreamReader reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
string configFileContent = reader.ReadToEnd();
|
||||||
|
|
||||||
|
YamlSerializer yamlSerializer = new YamlSerializer();
|
||||||
|
YamlRegexConfig yamlConfig = (YamlRegexConfig)yamlSerializer.Deserialize(configFileContent, typeof(YamlRegexConfig))[0];
|
||||||
|
|
||||||
|
// check
|
||||||
|
if (yamlConfig.regular_expresions == null || yamlConfig.regular_expresions.Length == 0)
|
||||||
|
{
|
||||||
|
throw new System.Exception("No configuration was read");
|
||||||
|
}
|
||||||
|
|
||||||
|
return yamlConfig;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
Beaprint.PrintException($"An exception occured while parsing regexes.yaml configuration file: {e.Message}");
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static YamlConfig GetWindowsSearchConfig()
|
public static YamlConfig GetWindowsSearchConfig()
|
||||||
{
|
{
|
||||||
var assembly = Assembly.GetExecutingAssembly();
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
@ -52,7 +88,7 @@ namespace winPEAS.Helpers.YamlConfig
|
|||||||
}
|
}
|
||||||
catch (System.Exception e)
|
catch (System.Exception e)
|
||||||
{
|
{
|
||||||
Beaprint.PrintException($"An exception occured while parsing YAML configuration file: {e.Message}");
|
Beaprint.PrintException($"An exception occured while parsing sensitive_files.yaml configuration file: {e.Message}");
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
@ -78,6 +114,7 @@ namespace winPEAS.Helpers.YamlConfig
|
|||||||
value.only_bad_lines = GetValueOrDefault(value.only_bad_lines, defaults.only_bad_lines);
|
value.only_bad_lines = GetValueOrDefault(value.only_bad_lines, defaults.only_bad_lines);
|
||||||
value.remove_empty_lines = GetValueOrDefault(value.remove_empty_lines, defaults.remove_empty_lines);
|
value.remove_empty_lines = GetValueOrDefault(value.remove_empty_lines, defaults.remove_empty_lines);
|
||||||
value.remove_regex = GetValueOrDefault(value.remove_regex, defaults.remove_regex);
|
value.remove_regex = GetValueOrDefault(value.remove_regex, defaults.remove_regex);
|
||||||
|
value.remove_path = GetValueOrDefault(value.remove_path, defaults.remove_path);
|
||||||
value.type = GetValueOrDefault(value.type, defaults.type).ToLower();
|
value.type = GetValueOrDefault(value.type, defaults.type).ToLower();
|
||||||
|
|
||||||
if (value.files != null)
|
if (value.files != null)
|
||||||
|
@ -348,6 +348,12 @@ namespace winPEAS.Info.NetworkInfo
|
|||||||
MIB_TCPROW_OWNER_PID tcpRow = (MIB_TCPROW_OWNER_PID)Marshal.PtrToStructure(tableRowPtr, typeof(MIB_TCPROW_OWNER_PID));
|
MIB_TCPROW_OWNER_PID tcpRow = (MIB_TCPROW_OWNER_PID)Marshal.PtrToStructure(tableRowPtr, typeof(MIB_TCPROW_OWNER_PID));
|
||||||
|
|
||||||
// Add row to list of TcpConnetions.
|
// Add row to list of TcpConnetions.
|
||||||
|
string proc_name = GetProcessNameByPid(tcpRow.owningPid, processesByPid);
|
||||||
|
if (proc_name == "Idle")
|
||||||
|
{ //Sometime too many Idle connections that doesn't provide sensitive info
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
tcpTableRecords.Add(new TcpConnectionInfo(
|
tcpTableRecords.Add(new TcpConnectionInfo(
|
||||||
Protocol.TCP,
|
Protocol.TCP,
|
||||||
new IPAddress(tcpRow.localAddr),
|
new IPAddress(tcpRow.localAddr),
|
||||||
@ -360,7 +366,7 @@ namespace winPEAS.Info.NetworkInfo
|
|||||||
tcpRow.remotePort[0] }, 0),
|
tcpRow.remotePort[0] }, 0),
|
||||||
tcpRow.owningPid,
|
tcpRow.owningPid,
|
||||||
tcpRow.state,
|
tcpRow.state,
|
||||||
GetProcessNameByPid(tcpRow.owningPid, processesByPid)));
|
proc_name));
|
||||||
|
|
||||||
tableRowPtr = (IntPtr)((long)tableRowPtr + Marshal.SizeOf(tcpRow));
|
tableRowPtr = (IntPtr)((long)tableRowPtr + Marshal.SizeOf(tcpRow));
|
||||||
}
|
}
|
||||||
@ -377,6 +383,12 @@ namespace winPEAS.Info.NetworkInfo
|
|||||||
{
|
{
|
||||||
MIB_TCP6ROW_OWNER_PID tcpRow = (MIB_TCP6ROW_OWNER_PID)Marshal.PtrToStructure(tableRowPtr, typeof(MIB_TCP6ROW_OWNER_PID));
|
MIB_TCP6ROW_OWNER_PID tcpRow = (MIB_TCP6ROW_OWNER_PID)Marshal.PtrToStructure(tableRowPtr, typeof(MIB_TCP6ROW_OWNER_PID));
|
||||||
|
|
||||||
|
string proc_name = GetProcessNameByPid(tcpRow.owningPid, processesByPid);
|
||||||
|
if (proc_name == "Idle")
|
||||||
|
{ //Sometime too many Idle connections that doesn't provide sensitive info
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
tcpTableRecords.Add(new TcpConnectionInfo(
|
tcpTableRecords.Add(new TcpConnectionInfo(
|
||||||
Protocol.TCP,
|
Protocol.TCP,
|
||||||
new IPAddress(tcpRow.localAddr, tcpRow.localScopeId),
|
new IPAddress(tcpRow.localAddr, tcpRow.localScopeId),
|
||||||
@ -389,7 +401,7 @@ namespace winPEAS.Info.NetworkInfo
|
|||||||
tcpRow.remotePort[0] }, 0),
|
tcpRow.remotePort[0] }, 0),
|
||||||
tcpRow.owningPid,
|
tcpRow.owningPid,
|
||||||
tcpRow.state,
|
tcpRow.state,
|
||||||
GetProcessNameByPid(tcpRow.owningPid, processesByPid)));
|
proc_name));
|
||||||
|
|
||||||
tableRowPtr = (IntPtr)((long)tableRowPtr + Marshal.SizeOf(tcpRow));
|
tableRowPtr = (IntPtr)((long)tableRowPtr + Marshal.SizeOf(tcpRow));
|
||||||
}
|
}
|
||||||
|
@ -1,40 +1,20 @@
|
|||||||
using System;
|
using Microsoft.Win32;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Management;
|
using System.Management;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using winPEAS.Helpers;
|
using winPEAS.Helpers;
|
||||||
using winPEAS.Native;
|
|
||||||
|
|
||||||
namespace winPEAS.Info.ProcessInfo
|
namespace winPEAS.Info.ProcessInfo
|
||||||
{
|
{
|
||||||
internal class ProcessesInfo
|
internal class ProcessesInfo
|
||||||
{
|
{
|
||||||
private static string GetProcU(Process p)
|
|
||||||
{
|
|
||||||
IntPtr pHandle = IntPtr.Zero;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Advapi32.OpenProcessToken(p.Handle, 8, out pHandle);
|
|
||||||
WindowsIdentity WI = new WindowsIdentity(pHandle);
|
|
||||||
String uSEr = WI.Name;
|
|
||||||
return uSEr.Contains(@"\") ? uSEr.Substring(uSEr.IndexOf(@"\") + 1) : uSEr;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (pHandle != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
Kernel32.CloseHandle(pHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check out https://github.com/harleyQu1nn/AggressorScripts/blob/master/ProcessColor.cna#L10
|
// TODO: check out https://github.com/harleyQu1nn/AggressorScripts/blob/master/ProcessColor.cna#L10
|
||||||
public static List<Dictionary<string, string>> GetProcInfo()
|
public static List<Dictionary<string, string>> GetProcInfo()
|
||||||
{
|
{
|
||||||
@ -53,7 +33,7 @@ namespace winPEAS.Info.ProcessInfo
|
|||||||
Proc = p,
|
Proc = p,
|
||||||
Pth = (string)mo["ExecutablePath"],
|
Pth = (string)mo["ExecutablePath"],
|
||||||
CommLine = (string)mo["CommandLine"],
|
CommLine = (string)mo["CommandLine"],
|
||||||
Owner = GetProcU(p), //Needed inside the next foreach
|
Owner = Helpers.HandlesHelper.GetProcU(p)["name"], //Needed inside the next foreach
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var itm in queRy)
|
foreach (var itm in queRy)
|
||||||
@ -94,5 +74,163 @@ namespace winPEAS.Info.ProcessInfo
|
|||||||
}
|
}
|
||||||
return f_results;
|
return f_results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Dictionary<string, string>> GetVulnHandlers()
|
||||||
|
{
|
||||||
|
List<Dictionary<string, string>> vulnHandlers = new List<Dictionary<string, string>>();
|
||||||
|
List<HandlesHelper.SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> handlers = HandlesHelper.GetAllHandlers();
|
||||||
|
List<string> interestingHandlerTypes = new List<string>() { "file", "key", "process", "thread" }; //section
|
||||||
|
|
||||||
|
foreach (HandlesHelper.SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX h in handlers)
|
||||||
|
{
|
||||||
|
// skip some objects to avoid getting stuck
|
||||||
|
// see: https://github.com/adamdriscoll/PoshInternals/issues/7
|
||||||
|
if (h.GrantedAccess == 0x0012019f
|
||||||
|
|| h.GrantedAccess == 0x00120189
|
||||||
|
|| h.GrantedAccess == 0x120089
|
||||||
|
|| h.GrantedAccess == 0x1A019F)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
IntPtr dupHandle;
|
||||||
|
IntPtr _processHandle = Native.Kernel32.OpenProcess(HandlesHelper.ProcessAccessFlags.DupHandle | HandlesHelper.ProcessAccessFlags.QueryInformation, false, h.UniqueProcessId);
|
||||||
|
|
||||||
|
if (_processHandle == (IntPtr)0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint status = (uint)Native.Ntdll.NtDuplicateObject(
|
||||||
|
_processHandle,
|
||||||
|
h.HandleValue,
|
||||||
|
Native.Kernel32.GetCurrentProcess(),
|
||||||
|
out dupHandle,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
HandlesHelper.DUPLICATE_SAME_ACCESS);
|
||||||
|
|
||||||
|
Native.Kernel32.CloseHandle(_processHandle);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string typeName = HandlesHelper.GetObjectType(dupHandle).ToLower();
|
||||||
|
if (interestingHandlerTypes.Contains(typeName))
|
||||||
|
{
|
||||||
|
HandlesHelper.VULNERABLE_HANDLER_INFO handlerExp = HandlesHelper.checkExploitaible(h, typeName);
|
||||||
|
if (handlerExp.isVuln == true)
|
||||||
|
{
|
||||||
|
HandlesHelper.PT_RELEVANT_INFO origProcInfo = HandlesHelper.getProcInfoById((int)h.UniqueProcessId);
|
||||||
|
if (!Checks.Checks.CurrentUserSiDs.ContainsKey(origProcInfo.userSid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string hName = HandlesHelper.GetObjectName(dupHandle);
|
||||||
|
|
||||||
|
Dictionary<string, string> to_add = new Dictionary<string, string>();
|
||||||
|
to_add["Handle Name"] = hName;
|
||||||
|
to_add["Handle"] = h.HandleValue.ToString() + "(" + typeName + ")";
|
||||||
|
to_add["Handle Owner"] = "Pid is " + h.UniqueProcessId.ToString() + "(" + origProcInfo.name + ") with owner: " + origProcInfo.userName;
|
||||||
|
to_add["Reason"] = handlerExp.reason;
|
||||||
|
|
||||||
|
if (typeName == "process" || typeName == "thread")
|
||||||
|
{
|
||||||
|
HandlesHelper.PT_RELEVANT_INFO hInfo;
|
||||||
|
if (typeName == "process")
|
||||||
|
{
|
||||||
|
hInfo = HandlesHelper.getProcessHandlerInfo(dupHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
else //Thread
|
||||||
|
{
|
||||||
|
hInfo = HandlesHelper.getThreadHandlerInfo(dupHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the privileged access is from a proc to itself, or to a process of the same user, not a privesc
|
||||||
|
if (hInfo.pid == 0 ||
|
||||||
|
(int)h.UniqueProcessId == hInfo.pid ||
|
||||||
|
origProcInfo.userSid == hInfo.userSid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
to_add["Handle PID"] = hInfo.pid.ToString() + "(" + hInfo.userName + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (typeName == "file")
|
||||||
|
{
|
||||||
|
//StringBuilder filePath = new StringBuilder(2000);
|
||||||
|
//HandlersHelper.GetFinalPathNameByHandle(dupHandle, filePath, 2000, 0);
|
||||||
|
|
||||||
|
HandlesHelper.FILE_NAME_INFO fni = new HandlesHelper.FILE_NAME_INFO();
|
||||||
|
|
||||||
|
// Sometimes both GetFileInformationByHandle and GetFileInformationByHandleEx hangs
|
||||||
|
// So a timeput of 1s is put to the function to prevent that
|
||||||
|
var task = Task.Run(() =>
|
||||||
|
{
|
||||||
|
// FILE_NAME_INFO (2)
|
||||||
|
return Native.Kernel32.GetFileInformationByHandleEx(dupHandle, 2, out fni, (uint)Marshal.SizeOf(fni));
|
||||||
|
});
|
||||||
|
|
||||||
|
bool isCompletedSuccessfully = task.Wait(TimeSpan.FromMilliseconds(1000));
|
||||||
|
|
||||||
|
if (!isCompletedSuccessfully)
|
||||||
|
{
|
||||||
|
//throw new TimeoutException("The function has taken longer than the maximum time allowed.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string sFilePath = fni.FileName;
|
||||||
|
if (sFilePath.Length == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
List<string> permsFile = PermissionsHelper.GetPermissionsFile(sFilePath, Checks.Checks.CurrentUserSiDs, PermissionType.WRITEABLE_OR_EQUIVALENT);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
System.Security.AccessControl.FileSecurity fs = System.IO.File.GetAccessControl(sFilePath);
|
||||||
|
IdentityReference sid = fs.GetOwner(typeof(SecurityIdentifier));
|
||||||
|
string ownerName = sid.Translate(typeof(NTAccount)).ToString();
|
||||||
|
|
||||||
|
// If current user already have permissions over that file or the proc belongs to the owner of the file,
|
||||||
|
// handler not interesting to elevate privs
|
||||||
|
if (permsFile.Count > 0 || origProcInfo.userSid == sid.Value)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
to_add["File Path"] = sFilePath;
|
||||||
|
to_add["File Owner"] = ownerName;
|
||||||
|
}
|
||||||
|
catch (System.IO.FileNotFoundException)
|
||||||
|
{
|
||||||
|
// File wasn't found
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
catch (System.InvalidOperationException)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (typeName == "key")
|
||||||
|
{
|
||||||
|
HandlesHelper.KEY_RELEVANT_INFO kri = HandlesHelper.getKeyHandlerInfo(dupHandle);
|
||||||
|
if (kri.path.Length == 0 && kri.hive != null && kri.hive.Length> 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
RegistryKey regKey = Helpers.Registry.RegistryHelper.GetReg(kri.hive, kri.path);
|
||||||
|
if (regKey == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
List<string> permsReg = PermissionsHelper.GetMyPermissionsR(regKey, Checks.Checks.CurrentUserSiDs);
|
||||||
|
|
||||||
|
// If current user already have permissions over that reg, handle not interesting to elevate privs
|
||||||
|
if (permsReg.Count > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
to_add["Registry"] = kri.hive + "\\" + kri.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vulnHandlers.Add(to_add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vulnHandlers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
{
|
{
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public string Sddl { get; }
|
public string Sddl { get; }
|
||||||
|
public string CurrentUserPerms { get; }
|
||||||
|
|
||||||
public NamedPipeInfo(string name, string sddl)
|
public NamedPipeInfo(string name, string sddl, string currentUserPerms)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Sddl = sddl;
|
Sddl = sddl;
|
||||||
|
CurrentUserPerms = currentUserPerms;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ using System.IO;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.AccessControl;
|
using System.Security.AccessControl;
|
||||||
using winPEAS.Native;
|
using winPEAS.Native;
|
||||||
|
using System.Security.Principal;
|
||||||
|
|
||||||
|
|
||||||
namespace winPEAS.Info.SystemInfo.NamedPipes
|
namespace winPEAS.Info.SystemInfo.NamedPipes
|
||||||
{
|
{
|
||||||
@ -42,22 +44,26 @@ namespace winPEAS.Info.SystemInfo.NamedPipes
|
|||||||
foreach (var namedPipe in namedPipes)
|
foreach (var namedPipe in namedPipes)
|
||||||
{
|
{
|
||||||
string sddl;
|
string sddl;
|
||||||
|
string currentUserPerms;
|
||||||
bool isError = false;
|
bool isError = false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var security = File.GetAccessControl($"\\\\.\\pipe\\{namedPipe}");
|
var security = File.GetAccessControl($"\\\\.\\pipe\\{namedPipe}");
|
||||||
sddl = security.GetSecurityDescriptorSddlForm(AccessControlSections.All);
|
sddl = security.GetSecurityDescriptorSddlForm(AccessControlSections.All);
|
||||||
|
List<string> currentUserPermsList = winPEAS.Helpers.PermissionsHelper.GetMyPermissionsF(security, winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||||
|
currentUserPerms = string.Join(", ", currentUserPermsList);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
isError = true;
|
isError = true;
|
||||||
sddl = "ERROR";
|
sddl = "ERROR";
|
||||||
|
currentUserPerms = "ERROR";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isError && !string.IsNullOrEmpty(sddl))
|
if (!isError && !string.IsNullOrEmpty(sddl))
|
||||||
{
|
{
|
||||||
yield return new NamedPipeInfo(namedPipe, sddl);
|
yield return new NamedPipeInfo(namedPipe, sddl, currentUserPerms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,9 +160,13 @@ namespace winPEAS.Info.SystemInfo
|
|||||||
{
|
{
|
||||||
Dictionary<string, string> results = new Dictionary<string, string>();
|
Dictionary<string, string> results = new Dictionary<string, string>();
|
||||||
string whitelistpaths = "";
|
string whitelistpaths = "";
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
whitelistpaths = String.Join("\n ", RegistryHelper.GetRegValues("HKLM", @"SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths").Keys);
|
var keys = RegistryHelper.GetRegValues("HKLM", @"SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths");
|
||||||
|
if (keys != null)
|
||||||
|
whitelistpaths = String.Join("\n ", keys.Keys);
|
||||||
|
|
||||||
using (ManagementObjectSearcher wmiData = new ManagementObjectSearcher(@"root\SecurityCenter2", "SELECT * FROM AntiVirusProduct"))
|
using (ManagementObjectSearcher wmiData = new ManagementObjectSearcher(@"root\SecurityCenter2", "SELECT * FROM AntiVirusProduct"))
|
||||||
{
|
{
|
||||||
using (var data = wmiData.Get())
|
using (var data = wmiData.Get())
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.ConstrainedExecution;
|
using System.Runtime.ConstrainedExecution;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
using winPEAS.Info.SystemInfo.NamedPipes;
|
using winPEAS.Info.SystemInfo.NamedPipes;
|
||||||
|
|
||||||
namespace winPEAS.Native
|
namespace winPEAS.Native
|
||||||
@ -67,5 +68,34 @@ namespace winPEAS.Native
|
|||||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||||
internal static extern int GetPrivateProfileString(string? section, string? key, string defaultValue, [In, Out] char[] value, int size, string filePath);
|
internal static extern int GetPrivateProfileString(string? section, string? key, string defaultValue, [In, Out] char[] value, int size, string filePath);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
public static extern IntPtr OpenProcess(Helpers.HandlesHelper.ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
public static extern IntPtr OpenProcess(Helpers.HandlesHelper.ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, UIntPtr dwProcessId);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, ushort hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
public static extern uint GetProcessIdOfThread(IntPtr handle);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
public static extern uint GetProcessId(IntPtr handle);
|
||||||
|
|
||||||
|
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||||
|
public static extern uint GetFinalPathNameByHandle(IntPtr hFile, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpszFilePath, uint cchFilePath, uint dwFlags);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
public static extern uint GetFileInformationByHandleEx(IntPtr hFile, int infoClass, out Helpers.HandlesHelper.FILE_NAME_INFO lpFileInformation, uint dwBufferSize);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||||
|
public static extern unsafe int GetFullPathName(string lpFileName, int nBufferLength, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpBuffer, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpFilePart);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
winPEAS/winPEASexe/winPEAS/Native/Ntdll.cs
Normal file
28
winPEAS/winPEASexe/winPEAS/Native/Ntdll.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.ConstrainedExecution;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using winPEAS.Info.SystemInfo.NamedPipes;
|
||||||
|
|
||||||
|
namespace winPEAS.Native
|
||||||
|
{
|
||||||
|
internal class Ntdll
|
||||||
|
{
|
||||||
|
[DllImport("ntdll.dll")]
|
||||||
|
public static extern int NtQueryObject(IntPtr ObjectHandle, int ObjectInformationClass, IntPtr ObjectInformation, int ObjectInformationLength, ref int returnLength);
|
||||||
|
|
||||||
|
[DllImport("ntdll.dll")]
|
||||||
|
public static extern uint NtQuerySystemInformation(int SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength, ref int returnLength);
|
||||||
|
|
||||||
|
[DllImport("ntdll.dll")]
|
||||||
|
internal static extern int NtQueryInformationProcess(IntPtr ProcessHandle, int ProcessInformationClass, IntPtr[] ProcessInformation, int ProcessInformationLength, ref int ReturnLength);
|
||||||
|
|
||||||
|
[DllImport("ntdll.dll")]
|
||||||
|
internal static extern int NtQueryInformationThread(IntPtr hThread, int ThreadInformationClass, IntPtr[] ThreadInformation, int ThreadInformationLength, ref int ReturnLength);
|
||||||
|
|
||||||
|
[DllImport("ntdll.dll")]
|
||||||
|
internal static extern int NtDuplicateObject(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, ulong dwOptions);
|
||||||
|
|
||||||
|
[DllImport("ntdll.dll")]
|
||||||
|
public static extern uint NtQueryKey(IntPtr KeyHandle, int KeyInformationClass, byte[] KeyInformation, int Length, ref int ResultLength);
|
||||||
|
}
|
||||||
|
}
|
@ -26,5 +26,12 @@ namespace winPEAS.Native
|
|||||||
StringBuilder name,
|
StringBuilder name,
|
||||||
UInt32 nameSize
|
UInt32 nameSize
|
||||||
);
|
);
|
||||||
|
|
||||||
|
[DllImport("psapi.dll")]
|
||||||
|
internal static extern uint GetProcessImageFileName(
|
||||||
|
IntPtr hProcess,
|
||||||
|
[Out] StringBuilder lpImageFileName,
|
||||||
|
[In][MarshalAs(UnmanagedType.U4)] int nSize
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,34 +1,34 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
|
||||||
<StartArguments>
|
<StartArguments>
|
||||||
</StartArguments>
|
</StartArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
||||||
<StartArguments>fileAnalysis</StartArguments>
|
<StartArguments>fileanalysis</StartArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||||
<StartArguments>debug</StartArguments>
|
<StartArguments>debug</StartArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||||
<StartArguments>fast</StartArguments>
|
<StartArguments>fast</StartArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||||
<StartArguments>
|
<StartArguments>
|
||||||
</StartArguments>
|
</StartArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||||
<StartArguments>
|
<StartArguments>
|
||||||
</StartArguments>
|
</StartArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PublishUrlHistory>publish\</PublishUrlHistory>
|
<PublishUrlHistory>publish\</PublishUrlHistory>
|
||||||
<InstallUrlHistory />
|
<InstallUrlHistory />
|
||||||
<SupportUrlHistory />
|
<SupportUrlHistory />
|
||||||
<UpdateUrlHistory />
|
<UpdateUrlHistory />
|
||||||
<BootstrapperUrlHistory />
|
<BootstrapperUrlHistory />
|
||||||
<ErrorReportUrlHistory />
|
<ErrorReportUrlHistory />
|
||||||
<FallbackCulture>en-US</FallbackCulture>
|
<FallbackCulture>en-US</FallbackCulture>
|
||||||
<VerifyUploadedFiles>false</VerifyUploadedFiles>
|
<VerifyUploadedFiles>false</VerifyUploadedFiles>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue
Block a user