Merge pull request #350 from Donovoi/master

fix path too long
This commit is contained in:
Carlos Polop 2023-04-25 17:05:49 +02:00 committed by GitHub
commit df4f122a53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 304 additions and 40 deletions

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using winPEAS.Helpers;
using winPEAS.Helpers.Search;
using Path = Alphaleonis.Win32.Filesystem.Path;
namespace winPEAS.Tests
{
[TestClass]
public class SearchHelperTests
{
[TestMethod]
public void TestGetFilesFastBypassesMAX_PATHLimit()
{
// Create a folder with files that have names longer than 260 characters
string folder = "C:\\Temp\\TestFolder";
var createdirectory = new DirectoryInfo(folder);
createdirectory.Create();
for (int i = 0; i < 10; i++)
{
string longName = new string('a', 300);
string fileName = Path.Combine(folder, $"{longName}_{i}.txt");
// Use the fsutil command to create a file with a long name
ProcessStartInfo startInfo = new ProcessStartInfo("fsutil", $"file createnew {fileName} 0")
{
UseShellExecute = true,
CreateNoWindow = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
ErrorDialog = true,
WindowStyle = ProcessWindowStyle.Normal
};
Process.Start(startInfo);
}
// Call the GetFilesFast method to get a list of all the files in the folder
List<CustomFileInfo> files = SearchHelper.GetFilesFast(folder);
// Get a list of all the files in the folder using System.IO.Directory.GetFiles
string[] directoryFiles = System.IO.Directory.GetFiles(folder);
List<FileInfo> expectedFiles = directoryFiles.Select(f => new FileInfo(f)).ToList();
// Make sure the lists have the same number of elements
Assert.AreEqual(expectedFiles.Count, files.Count);
}
}
}

View File

@ -318,6 +318,74 @@ namespace winPEAS.Checks
Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value)); 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 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> { };
// var timer = new Stopwatch();
// if (Checks.IsDebug)
// {
// timer.Start();
// }
// try
// {
// string text = 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
// }
// if (Checks.IsDebug)
// {
// timer.Stop();
// TimeSpan timeTaken = timer.Elapsed;
// if (timeTaken.TotalMilliseconds > 20000)
// Beaprint.PrintDebugLine($"\nThe regex {regex.regex} took {timeTaken.TotalMilliseconds}s in {f.FullPath}");
// }
// }
// }
// pb += (double)100 / files.Count;
// progress.Report(pb / 100); //Value must be in [0..1] range
// });
// }, Checks.IsDebug);
//}
double pb = 0; double pb = 0;
using (var progress = new ProgressBar()) using (var progress = new ProgressBar())
{ {
@ -332,7 +400,6 @@ namespace winPEAS.Checks
Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = num_threads }, f => Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = num_threads }, f =>
{ {
foreach (var regex_obj in config.regular_expresions) foreach (var regex_obj in config.regular_expresions)
{ {
foreach (var regex in regex_obj.regexes) foreach (var regex in regex_obj.regexes)
@ -342,7 +409,7 @@ namespace winPEAS.Checks
continue; continue;
} }
List<string> results = new List<string> { }; Dictionary<string, List<string>> fileResults = new Dictionary<string, List<string>>();
var timer = new Stopwatch(); var timer = new Stopwatch();
if (Checks.IsDebug) if (Checks.IsDebug)
@ -350,18 +417,31 @@ namespace winPEAS.Checks
timer.Start(); timer.Start();
} }
try try
{ {
string text = File.ReadAllText(f.FullPath); using (StreamReader sr = new StreamReader(f.FullPath))
{
string line;
while ((line = sr.ReadLine()) != null)
{
List<string> results = SearchContent(line, regex.regex, (bool)regex.caseinsensitive);
if (results.Count > 0)
{
if (!fileResults.ContainsKey(f.FullPath))
{
fileResults[f.FullPath] = new List<string>();
}
fileResults[f.FullPath].AddRange(results);
}
}
}
results = SearchContent(text, regex.regex, (bool)regex.caseinsensitive); if (fileResults.Count > 0)
if (results.Count > 0)
{ {
if (!foundRegexes.ContainsKey(regex_obj.name)) foundRegexes[regex_obj.name] = new Dictionary<string, Dictionary<string, List<string>>> { }; 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>> { }; 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; foundRegexes[regex_obj.name][regex.name] = fileResults;
} }
} }
catch (System.IO.IOException) catch (System.IO.IOException)
@ -385,6 +465,7 @@ namespace winPEAS.Checks
}, Checks.IsDebug); }, Checks.IsDebug);
} }
// Print results // Print results
foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, List<string>>>> item in foundRegexes) foreach (KeyValuePair<string, Dictionary<string, Dictionary<string, List<string>>>> item in foundRegexes)
{ {

View File

@ -5,6 +5,8 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using FileInfo = Alphaleonis.Win32.Filesystem.FileInfo;
using DirectoryInfo = Alphaleonis.Win32.Filesystem.DirectoryInfo;
namespace winPEAS.Helpers.Search namespace winPEAS.Helpers.Search
{ {
@ -37,14 +39,133 @@ namespace winPEAS.Helpers.Search
".bmp", ".emf", ".gif", ".pm", ".bmp", ".emf", ".gif", ".pm",
".jif", ".jfi", ".jfif", ".jpe", ".jpeg", ".jpg", ".jif", ".jfi", ".jfif", ".jpe", ".jpeg", ".jpg",
".png", ".psd", ".raw", ".svg", ".svgz", ".tif", ".tiff", ".webp", ".png", ".psd", ".raw", ".svg", ".svgz", ".tif", ".tiff", ".webp",
}; };
//public static List<CustomFileInfo> GetFilesFast(string folder, string pattern = "*", HashSet<string> excludedDirs = null, bool isFoldersIncluded = false)
//{
// ConcurrentBag<CustomFileInfo> files = new ConcurrentBag<CustomFileInfo>();
// IEnumerable<DirectoryInfo> startDirs = GetStartDirectories(folder, files, pattern, isFoldersIncluded);
// IList<DirectoryInfo> startDirsExcluded = new List<DirectoryInfo>();
// IList<string> known_dirs = new List<string>();
// if (excludedDirs != null)
// {
// foreach (var startDir in startDirs)
// {
// bool shouldAdd = true;
// string startDirLower = startDir.FullName.ToLower();
// shouldAdd = !excludedDirs.Contains(startDirLower);
// if (shouldAdd)
// {
// startDirsExcluded.Add(startDir);
// }
// }
// }
// else
// {
// startDirsExcluded = startDirs.ToList();
// }
// Parallel.ForEach(startDirsExcluded, (d) =>
// {
// Parallel.ForEach(GetStartDirectories(d.FullName, files, pattern, isFoldersIncluded), (dir) =>
// {
// GetFiles(dir.FullName, pattern).ForEach(
// (f) =>
// {
// if (!StaticExtensions.Contains(f.Extension.ToLower()))
// {
// // It should always be lesss than 260, but some times it isn't so this will bypass that file
// //if (Checks.Checks.IsLongPath || f.FullName.Length <= 260)
// //{
// CustomFileInfo file_info = new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false);
// 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);
// }
// //}
// //else if (f.FullName.Length > 260)
// //Beaprint.LongPathWarning(f.FullName);
// }
// }
// );
// });
// });
// return files.ToList();
//}
//private static List<FileInfo> GetFiles(string folder, string pattern = "*")
//{
// DirectoryInfo dirInfo;
// DirectoryInfo[] directories;
// try
// {
// dirInfo = new DirectoryInfo(folder);
// directories = dirInfo.GetDirectories();
// if (directories.Length == 0)
// {
// return new List<FileInfo>(dirInfo.GetFiles(pattern));
// }
// }
// catch (UnauthorizedAccessException)
// {
// return new List<FileInfo>();
// }
// catch (PathTooLongException)
// {
// return new List<FileInfo>();
// }
// catch (DirectoryNotFoundException)
// {
// return new List<FileInfo>();
// }
// catch (Exception)
// {
// return new List<FileInfo>();
// }
// List<FileInfo> result = new List<FileInfo>();
// foreach (var d in directories)
// {
// result.AddRange(GetFiles(d.FullName, pattern));
// }
// try
// {
// result.AddRange(dirInfo.GetFiles(pattern));
// }
// catch (UnauthorizedAccessException)
// {
// }
// catch (PathTooLongException)
// {
// }
// catch (DirectoryNotFoundException)
// {
// }
// catch (Exception)
// {
// }
// return result;
//}
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>();
IEnumerable<DirectoryInfo> startDirs = GetStartDirectories(folder, files, pattern, isFoldersIncluded); IEnumerable<DirectoryInfo> startDirs = GetStartDirectories(folder, files, pattern, isFoldersIncluded);
IList<DirectoryInfo> startDirsExcluded = new List<DirectoryInfo>(); IList<DirectoryInfo> startDirsExcluded = new List<DirectoryInfo>();
IList<string> known_dirs = new List<string>(); ConcurrentDictionary<string, byte> known_dirs = new ConcurrentDictionary<string, byte>();
if (excludedDirs != null) if (excludedDirs != null)
{ {
@ -68,37 +189,27 @@ namespace winPEAS.Helpers.Search
Parallel.ForEach(startDirsExcluded, (d) => Parallel.ForEach(startDirsExcluded, (d) =>
{ {
Parallel.ForEach(GetStartDirectories(d.FullName, files, pattern, isFoldersIncluded), (dir) => var foundFiles = GetFiles(d.FullName, pattern);
foreach (var f in foundFiles)
{ {
GetFiles(dir.FullName, pattern).ForEach( if (f != null && !StaticExtensions.Contains(f.Extension.ToLower()))
(f) => {
CustomFileInfo file_info = new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false);
files.Add(file_info);
CustomFileInfo file_dir = new CustomFileInfo(f.Directory.Name, "", f.Directory.FullName, 0, true);
if (known_dirs.TryAdd(file_dir.FullPath, 0))
{ {
if (!StaticExtensions.Contains(f.Extension.ToLower())) files.Add(file_dir);
{
// It should always be lesss than 260, but some times it isn't so this will bypass that file
if (Checks.Checks.IsLongPath || f.FullName.Length <= 260)
{
CustomFileInfo file_info = new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false);
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);
}
}
else if (f.FullName.Length > 260)
Beaprint.LongPathWarning(f.FullName);
}
} }
); }
}); }
}); });
return files.ToList(); return files.ToList();
} }
private static List<FileInfo> GetFiles(string folder, string pattern = "*") private static List<FileInfo> GetFiles(string folder, string pattern = "*")
{ {
DirectoryInfo dirInfo; DirectoryInfo dirInfo;
@ -130,16 +241,22 @@ namespace winPEAS.Helpers.Search
return new List<FileInfo>(); return new List<FileInfo>();
} }
List<FileInfo> result = new List<FileInfo>(); ConcurrentBag<FileInfo> result = new ConcurrentBag<FileInfo>();
foreach (var d in directories) Parallel.ForEach(directories, (d) =>
{ {
result.AddRange(GetFiles(d.FullName, pattern)); foreach (var file in GetFiles(d.FullName, pattern))
} {
result.Add(file);
}
});
try try
{ {
result.AddRange(dirInfo.GetFiles(pattern)); foreach (var file in dirInfo.GetFiles(pattern))
{
result.Add(file);
}
} }
catch (UnauthorizedAccessException) catch (UnauthorizedAccessException)
{ {
@ -154,7 +271,7 @@ namespace winPEAS.Helpers.Search
{ {
} }
return result; return result.ToList();
} }
private static IEnumerable<DirectoryInfo> GetStartDirectories(string folder, ConcurrentBag<CustomFileInfo> files, string pattern, bool isFoldersIncluded = false) private static IEnumerable<DirectoryInfo> GetStartDirectories(string folder, ConcurrentBag<CustomFileInfo> files, string pattern, bool isFoldersIncluded = false)

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AlphaFS" version="2.2.6" targetFramework="net452" />
</packages>

View File

@ -114,12 +114,16 @@
</StartupObject> </StartupObject>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="AlphaFS, Version=2.2.0.0, Culture=neutral, PublicKeyToken=4d31a58f7d7ad5c9, processorArchitecture=MSIL">
<HintPath>..\packages\AlphaFS.2.2.6\lib\net452\AlphaFS.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.DirectoryServices.AccountManagement" /> <Reference Include="System.DirectoryServices.AccountManagement" />
<Reference Include="System.Management" /> <Reference Include="System.Management" />
<Reference Include="System.Security" /> <Reference Include="System.Security" />
<Reference Include="System.ServiceProcess" /> <Reference Include="System.ServiceProcess" />
<Reference Include="System.Transactions" />
<Reference Include="System.Web.Extensions" /> <Reference Include="System.Web.Extensions" />
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
@ -696,6 +700,7 @@
<Link>sensitive_files.yaml</Link> <Link>sensitive_files.yaml</Link>
</EmbeddedResource> </EmbeddedResource>
<None Include="App.config" /> <None Include="App.config" />
<None Include="packages.config" />
<None Include="TaskScheduler\V1\TaskSchedulerV1Schema.xsd"> <None Include="TaskScheduler\V1\TaskSchedulerV1Schema.xsd">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>