Skip to content

Commit

Permalink
Added /LocateHash
Browse files Browse the repository at this point in the history
- Added /LocateHash which can search a file system for a file with the specified hash.
- Optimized /Locate so it does not need to re-query the file system for file system attributes and can leverage the information gathered on the initial directory enumeration.
- Corrected issue with /GrantPerms was being parsed as /DenyPerms.
- Bumped version to 1.12.0.0.
  • Loading branch information
NoMoreFood committed May 26, 2020
1 parent e9ace6b commit 3a2aa66
Show file tree
Hide file tree
Showing 17 changed files with 309 additions and 66 deletions.
Binary file modified Build/Release/x64/repacls.exe
Binary file not shown.
Binary file modified Build/Release/x86/repacls.exe
Binary file not shown.
Binary file modified Build/Repacls.zip
Binary file not shown.
2 changes: 1 addition & 1 deletion Build/build.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ CLS
SET PATH=%WINDIR%\system32;%WINDIR%\system32\WindowsPowerShell\v1.0

:: cert info to use for signing
SET CERT=D4C06C609230B7BC433A428BFFD6EDC4F77FD166
SET CERT=193A6FACBFBFC43ADB74ABB669543FCBC1C4F26C
set TSAURL=http://time.certum.pl/
set LIBNAME=Repacls
set LIBURL=https://github.com/NoMoreFood/Repacls
Expand Down
8 changes: 5 additions & 3 deletions Functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@

// helper functions
VOID EnablePrivs();
PSID GetSidFromName(std::wstring & sAccountName);
PSID GetSidFromName(const std::wstring & sAccountName);
std::wstring GetNameFromSid(const PSID tSid, bool * bMarkAsOrphan = nullptr);
std::wstring GetNameFromSidEx(const PSID tSid, bool * bMarkAsOrphan = nullptr);
std::wstring GetDomainNameFromSid(const PSID tSid);
std::wstring GenerateAccessMask(DWORD iCurrentMask);
std::wstring GenerateInheritanceFlags(DWORD iCurrentFlags);
HANDLE RegisterFileHandle(HANDLE hFile, const std::wstring & sOperation);
std::wstring GetAntivirusStateDescription();
std::wstring FileTimeToString(LPFILETIME const tFileTime);
BOOL WriteToFile(const std::wstring & sStringToWrite, HANDLE hFile);
std::wstring FileTimeToString(const FILETIME tFileTime);
std::wstring FileSizeToString(const LARGE_INTEGER iFileSize);
std::wstring FileAttributesToString(const DWORD iAttributes);
BOOL WriteToFile(const std::wstring & sStringToWrite, HANDLE hFile) noexcept;

// helper typedefs
typedef struct SidCompare
Expand Down
35 changes: 31 additions & 4 deletions Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <atlstr.h>
#include <wscapi.h>
#include <iwscapi.h>
#include <locale.h>

#include <string>
#include <map>
Expand All @@ -18,7 +19,7 @@
#include "Operation.h"
#include "Functions.h"

PSID GetSidFromName(std::wstring & sAccountName)
PSID GetSidFromName(const std::wstring & sAccountName)
{
// for caching
static std::shared_mutex oMutex;
Expand Down Expand Up @@ -449,11 +450,11 @@ std::wstring GetAntivirusStateDescription()
return (bIsEnabled) ? L"On" : L"Off";
}

std::wstring FileTimeToString(LPFILETIME const tFileTime)
std::wstring FileTimeToString(const FILETIME tFileTime)
{
// the date format function require system time structure
SYSTEMTIME tTime;
FileTimeToSystemTime(tFileTime, &tTime);
FileTimeToSystemTime(&tFileTime, &tTime);

// convert the date to a string and return
WCHAR sTime[24];
Expand All @@ -465,7 +466,33 @@ std::wstring FileTimeToString(LPFILETIME const tFileTime)
return std::wstring(sTime);
}

BOOL WriteToFile(const std::wstring& sStringToWrite, HANDLE hFile)
std::wstring FileSizeToString(const LARGE_INTEGER iFileSize)
{
// convert the file size to a string
WCHAR sSize[32];
_wsetlocale(LC_NUMERIC, L"");
wsprintf(sSize, L"%I64u", iFileSize.QuadPart);
return std::wstring(sSize);
}

std::wstring FileAttributesToString(const DWORD iAttributes)
{
// decode attributes
std::wstring sAttributes;
if (iAttributes & FILE_ATTRIBUTE_READONLY) sAttributes += L"R";
if (iAttributes & FILE_ATTRIBUTE_HIDDEN) sAttributes += L"H";
if (iAttributes & FILE_ATTRIBUTE_SYSTEM) sAttributes += L"S";
if (iAttributes & FILE_ATTRIBUTE_DIRECTORY) sAttributes += L"D";
if (iAttributes & FILE_ATTRIBUTE_ARCHIVE) sAttributes += L"A";
if (iAttributes & FILE_ATTRIBUTE_TEMPORARY) sAttributes += L"T";
if (iAttributes & FILE_ATTRIBUTE_COMPRESSED) sAttributes += L"C";
if (iAttributes & FILE_ATTRIBUTE_OFFLINE) sAttributes += L"O";
if (iAttributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) sAttributes += L"N";
if (iAttributes & FILE_ATTRIBUTE_ENCRYPTED) sAttributes += L"E";
return sAttributes;
}

BOOL WriteToFile(const std::wstring& sStringToWrite, HANDLE hFile) noexcept
{
// see how many characters we need to store as utf-8
int iChars = WideCharToMultiByte(CP_UTF8, 0,
Expand Down
12 changes: 11 additions & 1 deletion Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,10 @@ void AnalyzingQueue()
// construct the entry
ObjectEntry oSubEntry;
oSubEntry.IsRoot = false;
oSubEntry.FileSize = { oInfo->EndOfFile.LowPart, oInfo->EndOfFile.HighPart };
oSubEntry.Attributes = oInfo->FileAttributes;
oSubEntry.CreationTime = { oInfo->CreationTime.LowPart, (DWORD) oInfo->CreationTime.HighPart };
oSubEntry.ModifiedTime = { oInfo->LastWriteTime.LowPart, (DWORD) oInfo->LastWriteTime.HighPart };
oSubEntry.Name += oEntry.Name + ((oEntry.IsRoot && oEntry.Name.back() == '\\') ? L"" : L"\\")
+ std::wstring(oInfo->FileName, oInfo->FileNameLength / sizeof(WCHAR));

Expand Down Expand Up @@ -399,7 +402,14 @@ VOID BeginFileScan()

// copy it to a null terminated string
oEntryFirst.Name = std::wstring(tPathU.Buffer, tPathU.Length / sizeof(WCHAR));
oEntryFirst.Attributes = GetFileAttributes(oEntryFirst.Name.c_str());

// get common file attributes
WIN32_FILE_ATTRIBUTE_DATA tData;
GetFileAttributesExW(oEntryFirst.Name.c_str(), GetFileExInfoStandard, &tData);
oEntryFirst.FileSize = { tData.nFileSizeLow, (LONG) tData.nFileSizeHigh };
oEntryFirst.Attributes = tData.dwFileAttributes;
oEntryFirst.CreationTime = tData.ftCreationTime;
oEntryFirst.ModifiedTime = tData.ftLastWriteTime;

// free the buffer returned previously
RtlFreeUnicodeString(&tPathU);
Expand Down
3 changes: 3 additions & 0 deletions Operation.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ typedef struct ObjectEntry
{
std::wstring Name;
DWORD Attributes;
FILETIME CreationTime;
FILETIME ModifiedTime;
LARGE_INTEGER FileSize;
bool IsRoot;
}
ObjectEntry;
Expand Down
4 changes: 1 addition & 3 deletions OperationGrantDenyPerms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ OperationGrantDenyPerms::OperationGrantDenyPerms(std::queue<std::wstring>& oArgL
}

// populate default values
std::wstring sCommandUpper(sCommand);
ConvertToUpper(sCommandUpper);
tEa.grfAccessMode = (sCommandUpper == GetCommandAdd()) ? GRANT_ACCESS : DENY_ACCESS;
tEa.grfAccessMode = (_wcsicmp(sCommand.c_str(), GetCommandAdd().c_str()) == 0) ? GRANT_ACCESS : DENY_ACCESS;
tEa.grfInheritance = NO_INHERITANCE;
tEa.grfAccessPermissions = 0;
tEa.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
Expand Down
11 changes: 9 additions & 2 deletions OperationHelp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,21 @@ Commands That Do Not Alter Security
Reports any instance of a null ACL. A null ACL, unlike an empty ACL, allows
all access (i.e., similar to an ACE with 'Everyone' with 'Full Control')
/Locate <FileName> <RegularExpression>
/Locate <FileName> <FileRegularExpression>
This command will write a comma separated value file with the fields of
filename, creation time, file modified time, file size and file attributes.
The regular expression will perform a case insensitive regular expression
search against file name or directory name. To report all data, pass .*
as the regular expression.
/Report <FileName> <RegularExpression>
/LocateHash <FileName> <FileRegularExpression>[:<SearchHash>[:<SearchSize>]]
Similar to /Locate, but the report file will also contain the SHA256 hash
of files that match the search criteria. The search criteria can optionally
include a SHA256 hash (in hex) and file size. Specifying file size can
dramatically increase search performance since only files with matching
sizes are read for hash comparison.
/Report <FileName> <AccountRegularExpression>
This command will write a comma separated value file with the fields of
filename, security descriptor part (e.g., DACL), account name, permissions,
and inheritance flags. The regular expression will perform a case
Expand Down
34 changes: 6 additions & 28 deletions OperationLocate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,37 +71,15 @@ void OperationLocate::ProcessObjectAction(ObjectEntry & tObjectEntry)
if (wcsrchr(sFileName, '\\') != nullptr) sFileName = wcsrchr(sFileName, '\\') + 1;
if (!std::regex_match(sFileName, tRegex)) return;

// fetch file attribute data
WIN32_FILE_ATTRIBUTE_DATA tData;
if (GetFileAttributesExW(tObjectEntry.Name.c_str(), GetFileExInfoStandard, &tData) == 0)
{
InputOutput::AddError(L"ERROR: Unable to read file attributes.");
}

// convert the file size to a string
WCHAR sSize[32] = { 0 };
ULARGE_INTEGER iFileSize;
iFileSize.LowPart = tData.nFileSizeLow;
iFileSize.HighPart = tData.nFileSizeHigh;
setlocale(LC_NUMERIC, "");
wsprintf(sSize, L"%I64u", iFileSize.QuadPart);

// decode attributes
std::wstring sAttributes = L"";
if (tData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) sAttributes += L"R";
if (tData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) sAttributes += L"H";
if (tData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) sAttributes += L"S";
if (tData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) sAttributes += L"D";
if (tData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) sAttributes += L"A";
if (tData.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) sAttributes += L"T";
if (tData.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) sAttributes += L"C";
if (tData.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) sAttributes += L"O";
if (tData.dwFileAttributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) sAttributes += L"N";
if (tData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) sAttributes += L"E";
// get common file attributes
const std::wstring sSize = FileSizeToString(tObjectEntry.FileSize);
const std::wstring sAttributes = FileAttributesToString(tObjectEntry.Attributes);
const std::wstring sModifiedTime = FileTimeToString(tObjectEntry.ModifiedTime);
const std::wstring sCreationTime = FileTimeToString(tObjectEntry.CreationTime);

// write the string to a file
std::wstring sToWrite = std::wstring(L"") + Q(tObjectEntry.Name) + L"," +
Q(FileTimeToString(&tData.ftCreationTime)) + L"," + Q(FileTimeToString(&tData.ftLastWriteTime)) +
Q(sCreationTime) + L"," + Q(sModifiedTime) +
L"," + Q(sSize) + L"," + Q(sAttributes) + L"\r\n";
if (WriteToFile(sToWrite, hReportFile) == 0)
{
Expand Down
Loading

0 comments on commit 3a2aa66

Please sign in to comment.