Skip to content

Commit 4e9ded0

Browse files
committed
Added /GrantPerms and /DenyPerms
- Added /GrantPerms and /DenyPerms which use a similar syntax to ICACLS. This will enumerate a directory structure and apply the specific permissions wherever they are broken. - Various refactoring. - Updated build for latest signing certificate. - Corrected variety of typos in help. - Updated & Signed Binaries For 1.12.0.0.
1 parent 3e761de commit 4e9ded0

File tree

85 files changed

+591
-478
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+591
-478
lines changed

Build/Release/x64/repacls.exe

-7.88 KB
Binary file not shown.

Build/Release/x86/repacls.exe

9.12 KB
Binary file not shown.

Build/Repacls.zip

-4.98 KB
Binary file not shown.

Build/build.cmd

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ CLS
44
SET PATH=%WINDIR%\system32;%WINDIR%\system32\WindowsPowerShell\v1.0
55

66
:: cert info to use for signing
7-
SET CERT=2FA35B20356EFEB88F9E9B5F20221693C57100E5
7+
SET CERT=D4C06C609230B7BC433A428BFFD6EDC4F77FD166
88
set TSAURL=http://time.certum.pl/
99
set LIBNAME=Repacls
1010
set LIBURL=https://github.com/NoMoreFood/Repacls

Functions.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ std::wstring GenerateAccessMask(DWORD iCurrentMask);
1414
std::wstring GenerateInheritanceFlags(DWORD iCurrentFlags);
1515
HANDLE RegisterFileHandle(HANDLE hFile, std::wstring sOperation);
1616
std::wstring GetAntivirusStateDescription();
17-
std::wstring FileTimeToString(LPFILETIME tFileTime);
18-
BOOL WriteToFile(std::wstring & sStringToWrite, HANDLE hFile);
17+
std::wstring FileTimeToString(LPFILETIME const tFileTime);
18+
BOOL WriteToFile(const std::wstring & sStringToWrite, HANDLE hFile);
1919

2020
// helper typedefs
2121
typedef struct SidCompare
2222
{
23-
inline bool operator()(PSID p1, PSID p2) const
23+
inline bool operator()(PSID p1, PSID p2) const noexcept
2424
{
2525
const DWORD iLength1 = GetLengthSid(p1);
2626
const DWORD iLength2 = GetLengthSid(p2);

Helpers.cpp

+11-11
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ std::wstring GetNameFromSid(const PSID tSid, bool * bMarkAsOrphan)
106106
if (LookupAccountSid(NULL, tSid, sAccountName,
107107
&iAccountNameSize, sDomainName, &iDomainName, &tNameUse) == 0)
108108
{
109-
DWORD iError = GetLastError();
109+
const DWORD iError = GetLastError();
110110
if (iError == ERROR_NONE_MAPPED)
111111
{
112112
if (bMarkAsOrphan != NULL) *bMarkAsOrphan = true;
@@ -347,7 +347,7 @@ HANDLE RegisterFileHandle(HANDLE hFile, std::wstring sOperation)
347347
static std::map<std::wstring, std::pair<HANDLE,std::wstring>> oFileLookup;
348348

349349
// do a reverse lookup on the file name
350-
auto iSize = (size_t) GetFinalPathNameByHandle(hFile, NULL, 0, VOLUME_NAME_NT);
350+
const auto iSize = (size_t) GetFinalPathNameByHandle(hFile, NULL, 0, VOLUME_NAME_NT);
351351

352352
// create a string that can accommodate that size (plus null terminating character)
353353
std::wstring sPath;
@@ -449,7 +449,7 @@ std::wstring GetAntivirusStateDescription()
449449
return (bIsEnabled) ? L"On" : L"Off";
450450
}
451451

452-
std::wstring FileTimeToString(LPFILETIME tFileTime)
452+
std::wstring FileTimeToString(LPFILETIME const tFileTime)
453453
{
454454
// the date format function require system time structure
455455
SYSTEMTIME tTime;
@@ -465,22 +465,22 @@ std::wstring FileTimeToString(LPFILETIME tFileTime)
465465
return std::wstring(sTime);
466466
}
467467

468-
BOOL WriteToFile(std::wstring & sStringToWrite, HANDLE hFile)
468+
BOOL WriteToFile(const std::wstring& sStringToWrite, HANDLE hFile)
469469
{
470470
// see how many characters we need to store as utf-8
471471
int iChars = WideCharToMultiByte(CP_UTF8, 0,
472-
sStringToWrite.c_str(), (int) sStringToWrite.length(),
472+
sStringToWrite.c_str(), (int)sStringToWrite.length(),
473473
NULL, 0, NULL, NULL);
474474
if (iChars == 0)
475475
{
476476
return FALSE;
477477
}
478478

479479
// allocate and do the conversion
480-
auto* sString = (BYTE *) malloc(iChars);
481-
iChars = WideCharToMultiByte(CP_UTF8, 0,
482-
sStringToWrite.c_str(), (int) sStringToWrite.length(),
483-
(LPSTR) sString, iChars, NULL, NULL);
480+
auto* sString = (BYTE*)malloc(iChars);
481+
iChars = WideCharToMultiByte(CP_UTF8, 0,
482+
sStringToWrite.c_str(), (int)sStringToWrite.length(),
483+
(LPSTR)sString, iChars, NULL, NULL);
484484
if (iChars == 0)
485485
{
486486
free(sString);
@@ -489,7 +489,7 @@ BOOL WriteToFile(std::wstring & sStringToWrite, HANDLE hFile)
489489

490490
// write to file, free memory, and return result
491491
DWORD iBytes = 0;
492-
BOOL bResult = WriteFile(hFile, sString, iChars, &iBytes, NULL);
492+
const BOOL bResult = WriteFile(hFile, sString, iChars, &iBytes, NULL);
493493
free(sString);
494494
return bResult;
495-
}
495+
}

InputOutput.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -23,37 +23,37 @@ class InputOutput
2323

2424
public:
2525

26-
static bool & InQuietMode()
26+
static bool & InQuietMode() noexcept
2727
{
2828
static bool bQuietMode = false;
2929
return bQuietMode;
3030
}
3131

32-
static bool & InWhatIfMode()
32+
static bool & InWhatIfMode() noexcept
3333
{
3434
static bool bWhatIfMode = false;
3535
return bWhatIfMode;
3636
}
3737

38-
static bool & ExcludeHiddenSystem()
38+
static bool & ExcludeHiddenSystem() noexcept
3939
{
4040
static bool bExcludeHiddenSystem = false;
4141
return bExcludeHiddenSystem;
4242
}
4343

44-
static short & MaxThreads()
44+
static short & MaxThreads() noexcept
4545
{
4646
static short iMaxThreads = 5;
4747
return iMaxThreads;
4848
}
4949

50-
static bool & Log()
50+
static bool & Log() noexcept
5151
{
5252
static bool bLog = false;
5353
return bLog;
5454
}
5555

56-
static std::vector<std::wstring> & ScanPaths()
56+
static std::vector<std::wstring> & ScanPaths() noexcept
5757
{
5858
static std::vector<std::wstring> vScanPaths;
5959
return vScanPaths;

Main.cpp

+24-24
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,22 @@ void AnalyzeSecurity(ObjectEntry & oEntry)
6666
bool bGroupIsDirty = false;
6767

6868
// read security information from the file handle
69-
PACL tAclDacl = NULL;
70-
PACL tAclSacl = NULL;
71-
PSID tOwnerSid = NULL;
72-
PSID tGroupSid = NULL;
73-
PSECURITY_DESCRIPTOR tDesc = NULL;
69+
PACL tAclDacl = nullptr;
70+
PACL tAclSacl = nullptr;
71+
PSID tOwnerSid = nullptr;
72+
PSID tGroupSid = nullptr;
73+
PSECURITY_DESCRIPTOR tDesc = nullptr;
7474
DWORD iError = 0;
7575
if (iInformationToLookup != 0 &&
7676
(iError = GetNamedSecurityInfo(oEntry.Name.c_str(), SE_FILE_OBJECT,
77-
iInformationToLookup, (bFetchOwner) ? &tOwnerSid : NULL, (bFetchGroup) ? &tGroupSid : NULL,
78-
(bFetchDacl) ? &tAclDacl : NULL, (bFetchSacl) ? &tAclSacl : NULL, &tDesc)) != ERROR_SUCCESS)
77+
iInformationToLookup, (bFetchOwner) ? &tOwnerSid : nullptr, (bFetchGroup) ? &tGroupSid : nullptr,
78+
(bFetchDacl) ? &tAclDacl : nullptr, (bFetchSacl) ? &tAclSacl : nullptr, &tDesc)) != ERROR_SUCCESS)
7979
{
8080
// attempt to look up error message
81-
LPWSTR sError = NULL;
82-
size_t iSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
81+
LPWSTR sError = nullptr;
82+
const size_t iSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
8383
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
84-
NULL, iError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&sError, 0, NULL);
84+
nullptr, iError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&sError, 0, nullptr);
8585
InputOutput::AddError(L"Unable to read file security", (iSize == 0) ? L"" : sError);
8686
if (iSize > 0) LocalFree(sError);
8787

@@ -96,7 +96,7 @@ void AnalyzeSecurity(ObjectEntry & oEntry)
9696
bool bSaclCleanupRequired = false;
9797
bool bOwnerCleanupRequired = false;
9898
bool bGroupCleanupRequired = false;
99-
bool bDescCleanupRequired = (tDesc != NULL);
99+
bool bDescCleanupRequired = (tDesc != nullptr);
100100

101101
// used for one-shot operations like reset children or inheritance
102102
DWORD iSpecialCommitMergeFlags = 0;
@@ -188,14 +188,14 @@ void AnalyzeSecurity(ObjectEntry & oEntry)
188188
if (!InputOutput::InWhatIfMode())
189189
{
190190
if ((iError = SetNamedSecurityInfo((LPWSTR) oEntry.Name.c_str(), SE_FILE_OBJECT, iInformationToCommit,
191-
(bOwnerIsDirty) ? tOwnerSid : NULL, (bGroupIsDirty) ? tGroupSid : NULL,
192-
(bDaclIsDirty) ? tAclDacl : NULL, (bSaclIsDirty) ? tAclSacl : NULL)) != ERROR_SUCCESS)
191+
(bOwnerIsDirty) ? tOwnerSid : nullptr, (bGroupIsDirty) ? tGroupSid : nullptr,
192+
(bDaclIsDirty) ? tAclDacl : nullptr, (bSaclIsDirty) ? tAclSacl : nullptr)) != ERROR_SUCCESS)
193193
{
194194
// attempt to look up error message
195-
LPWSTR sError = NULL;
196-
size_t iSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
195+
LPWSTR sError = nullptr;
196+
const size_t iSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
197197
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
198-
NULL, iError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &sError, 0, NULL);
198+
nullptr, iError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &sError, 0, NULL);
199199
InputOutput::AddError(L"Unable to update file security", (iSize == 0) ? L"" : sError);
200200
if (iSize > 0) LocalFree(sError);
201201

@@ -273,7 +273,7 @@ void AnalyzingQueue()
273273

274274
// update object attributes object
275275
OBJECT_ATTRIBUTES oAttributes;
276-
InitializeObjectAttributes(&oAttributes, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
276+
InitializeObjectAttributes(&oAttributes, nullptr, OBJ_CASE_INSENSITIVE, nullptr, nullptr);
277277
oAttributes.ObjectName = &tPathU;
278278

279279
// get an open file handle
@@ -310,9 +310,9 @@ void AnalyzingQueue()
310310
// enumerate files in the directory
311311
for (bool bFirstRun = true; true; bFirstRun = false)
312312
{
313-
Status = NtQueryDirectoryFile(hFindFile, NULL, NULL, NULL, &IoStatusBlock,
313+
Status = NtQueryDirectoryFile(hFindFile, nullptr, nullptr, nullptr, &IoStatusBlock,
314314
DirectoryInfo, MAX_DIRECTORY_BUFFER, (FILE_INFORMATION_CLASS)FileDirectoryInformation,
315-
FALSE, NULL, (bFirstRun) ? TRUE : FALSE);
315+
FALSE, nullptr, (bFirstRun) ? TRUE : FALSE);
316316

317317
// done processing
318318
if (Status == STATUS_NO_MORE_FILES) break;
@@ -324,7 +324,7 @@ void AnalyzingQueue()
324324
}
325325

326326
for (auto* oInfo = (FILE_DIRECTORY_INFORMATION *)DirectoryInfo;
327-
oInfo != NULL; oInfo = (FILE_DIRECTORY_INFORMATION *)((BYTE *)oInfo + oInfo->NextEntryOffset))
327+
oInfo != nullptr; oInfo = (FILE_DIRECTORY_INFORMATION *)((BYTE *)oInfo + oInfo->NextEntryOffset))
328328
{
329329
// continue immediately if we get the '.' or '..' entries
330330
if (IsDirectory(oInfo->FileAttributes))
@@ -384,7 +384,7 @@ VOID BeginFileScan()
384384
// make a local copy of the path since we may have to alter it
385385
// handle special case where a drive root is specified
386386
// we must ensure it takes the form x:\. to resolve correctly
387-
size_t iSemiColon = sPath.rfind(L':');
387+
const size_t iSemiColon = sPath.rfind(L':');
388388
if (iSemiColon != std::wstring::npos)
389389
{
390390
std::wstring sEnd = sPath.substr(iSemiColon);
@@ -396,7 +396,7 @@ VOID BeginFileScan()
396396

397397
// convert the path to a long path that is compatible with the other call
398398
UNICODE_STRING tPathU;
399-
RtlDosPathNameToNtPathName_U(sPath.c_str(), &tPathU, NULL, NULL);
399+
RtlDosPathNameToNtPathName_U(sPath.c_str(), &tPathU, nullptr, nullptr);
400400

401401
// copy it to a null terminated string
402402
oEntryFirst.Name = std::wstring(tPathU.Buffer, tPathU.Length / sizeof(WCHAR));
@@ -517,9 +517,9 @@ int wmain(int iArgs, WCHAR * aArgs[])
517517
wprintf(L"===============================================================================\n");
518518

519519
// do the scan
520-
ULONGLONG iTimeStart = GetTickCount64();
520+
const ULONGLONG iTimeStart = GetTickCount64();
521521
BeginFileScan();
522-
ULONGLONG iTimeStop = GetTickCount64();
522+
const ULONGLONG iTimeStop = GetTickCount64();
523523

524524
// print out statistics
525525
wprintf(L"===============================================================================\n");

Notes.txt

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
This file contains various information that may be useful in understanding
2-
various elements of ACL, ACE, or SID contructs.
2+
various elements of ACL, ACE, or SID constructs.
33

44
IO CI OI DIR DOB SUB SOB
5-
0 0 0 1 0 0 0 icacls Exact /grant Everyone:F
6-
0 0 1 1 1 0 1 icacls Exact /grant Everyone:(OI)F
7-
0 1 0 1 0 1 0 icacls Exact /grant Everyone:(CI)F
8-
0 1 1 1 1 1 1 icacls Exact /grant Everyone:(CI)(OI)F
9-
1 0 0 0 0 0 0 icacls Exact /grant Everyone:(IO)F
10-
1 0 1 0 1 0 1 icacls Exact /grant Everyone:(OI)(IO)F
11-
1 1 0 0 0 1 0 icacls Exact /grant Everyone:(CI)(IO)F
12-
1 1 1 0 1 1 1 icacls Exact /grant Everyone:(CI)(OI)(IO)F
5+
0 0 0 1 0 0 0 icacls Exact /grant Everyone:(F)
6+
0 0 1 1 1 0 1 icacls Exact /grant Everyone:(OI)(F)
7+
0 1 0 1 0 1 0 icacls Exact /grant Everyone:(CI)(F)
8+
0 1 1 1 1 1 1 icacls Exact /grant Everyone:(CI)(OI)(F)
9+
1 0 0 0 0 0 0 icacls Exact /grant Everyone:(IO)(F)
10+
1 0 1 0 1 0 1 icacls Exact /grant Everyone:(OI)(IO)(F)
11+
1 1 0 0 0 1 0 icacls Exact /grant Everyone:(CI)(IO)(F)
12+
1 1 1 0 1 1 1 icacls Exact /grant Everyone:(CI)(OI)(IO)(F)
1313

1414
Bit Mapping
1515
DIR = ~IO

Operation.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
bool Operation::ProcessAclAction(WCHAR * const sSdPart, ObjectEntry & tObjectEntry, PACL & tCurrentAcl, bool & bAclReplacement)
88
{
99
// return immediately if acl is null
10-
if (tCurrentAcl == NULL) return false;
10+
if (tCurrentAcl == nullptr) return false;
1111

1212
// flag to note whether a change was actually made
1313
bool bMadeChange = false;
@@ -75,7 +75,7 @@ bool Operation::ProcessAclAction(WCHAR * const sSdPart, ObjectEntry & tObjectEnt
7575
else
7676
{
7777
PBYTE const tNewAcl = (PBYTE)LocalAlloc(LMEM_FIXED, tAcl->AclSize + (iNewLen - iOldLen));
78-
if (tNewAcl == NULL)
78+
if (tNewAcl == nullptr)
7979
{
8080
wprintf(L"ERROR: Unable to allocate memory for new SID.\n");
8181
exit(-1);

Operation.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ typedef ACCESS_ACE *PACCESS_ACE;
4141
#define HasNoPropogate(x) CheckBitSet((x)->Header.AceFlags,NO_PROPAGATE_INHERIT_ACE)
4242
#define GetNonOiCiIoBits(x) ((~(CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE)) & (x)->Header.AceFlags)
4343

44+
// string helper operations
45+
#define ConvertToUpper(_x) std::transform(_x.begin(), _x.end(), _x.begin(), \
46+
[](const WCHAR c) noexcept { return static_cast<WCHAR>(::toupper(c)); });
47+
4448
typedef struct ObjectEntry
4549
{
4650
std::wstring Name;
@@ -80,7 +84,7 @@ class Operation
8084
bool ExclusiveOperation = false;
8185

8286
DWORD SpecialCommitFlags = false;
83-
PSID DefaultSidWhenEmpty = NULL;
87+
PSID DefaultSidWhenEmpty = nullptr;
8488

8589
virtual bool ProcessSdAction(std::wstring & sFileName, ObjectEntry & tObjectEntry, PSECURITY_DESCRIPTOR & tDescriptor, bool & bDescReplacement) { return false; }
8690
virtual bool ProcessAclAction(WCHAR * const sSdPart, ObjectEntry & tObjectEntry, PACL & tCurrentAcl, bool & bAclReplacement);
@@ -89,7 +93,7 @@ class Operation
8993
virtual void ProcessObjectAction(ObjectEntry & tObjectEntry) { return; }
9094

9195
Operation(std::queue<std::wstring> & oArgList);
92-
virtual ~Operation() = default;;
96+
virtual ~Operation() = default;
9397
};
9498

9599
#include "OperationFactory.h"

0 commit comments

Comments
 (0)