Skip to content

Commit

Permalink
Added /GrantPerms and /DenyPerms
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
NoMoreFood committed Feb 9, 2020
1 parent 3e761de commit 4e9ded0
Show file tree
Hide file tree
Showing 85 changed files with 591 additions and 478 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=2FA35B20356EFEB88F9E9B5F20221693C57100E5
SET CERT=D4C06C609230B7BC433A428BFFD6EDC4F77FD166
set TSAURL=http://time.certum.pl/
set LIBNAME=Repacls
set LIBURL=https://github.com/NoMoreFood/Repacls
Expand Down
6 changes: 3 additions & 3 deletions Functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ std::wstring GenerateAccessMask(DWORD iCurrentMask);
std::wstring GenerateInheritanceFlags(DWORD iCurrentFlags);
HANDLE RegisterFileHandle(HANDLE hFile, std::wstring sOperation);
std::wstring GetAntivirusStateDescription();
std::wstring FileTimeToString(LPFILETIME tFileTime);
BOOL WriteToFile(std::wstring & sStringToWrite, HANDLE hFile);
std::wstring FileTimeToString(LPFILETIME const tFileTime);
BOOL WriteToFile(const std::wstring & sStringToWrite, HANDLE hFile);

// helper typedefs
typedef struct SidCompare
{
inline bool operator()(PSID p1, PSID p2) const
inline bool operator()(PSID p1, PSID p2) const noexcept
{
const DWORD iLength1 = GetLengthSid(p1);
const DWORD iLength2 = GetLengthSid(p2);
Expand Down
22 changes: 11 additions & 11 deletions Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ std::wstring GetNameFromSid(const PSID tSid, bool * bMarkAsOrphan)
if (LookupAccountSid(NULL, tSid, sAccountName,
&iAccountNameSize, sDomainName, &iDomainName, &tNameUse) == 0)
{
DWORD iError = GetLastError();
const DWORD iError = GetLastError();
if (iError == ERROR_NONE_MAPPED)
{
if (bMarkAsOrphan != NULL) *bMarkAsOrphan = true;
Expand Down Expand Up @@ -347,7 +347,7 @@ HANDLE RegisterFileHandle(HANDLE hFile, std::wstring sOperation)
static std::map<std::wstring, std::pair<HANDLE,std::wstring>> oFileLookup;

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

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

std::wstring FileTimeToString(LPFILETIME tFileTime)
std::wstring FileTimeToString(LPFILETIME const tFileTime)
{
// the date format function require system time structure
SYSTEMTIME tTime;
Expand All @@ -465,22 +465,22 @@ std::wstring FileTimeToString(LPFILETIME tFileTime)
return std::wstring(sTime);
}

BOOL WriteToFile(std::wstring & sStringToWrite, HANDLE hFile)
BOOL WriteToFile(const std::wstring& sStringToWrite, HANDLE hFile)
{
// see how many characters we need to store as utf-8
int iChars = WideCharToMultiByte(CP_UTF8, 0,
sStringToWrite.c_str(), (int) sStringToWrite.length(),
sStringToWrite.c_str(), (int)sStringToWrite.length(),
NULL, 0, NULL, NULL);
if (iChars == 0)
{
return FALSE;
}

// allocate and do the conversion
auto* sString = (BYTE *) malloc(iChars);
iChars = WideCharToMultiByte(CP_UTF8, 0,
sStringToWrite.c_str(), (int) sStringToWrite.length(),
(LPSTR) sString, iChars, NULL, NULL);
auto* sString = (BYTE*)malloc(iChars);
iChars = WideCharToMultiByte(CP_UTF8, 0,
sStringToWrite.c_str(), (int)sStringToWrite.length(),
(LPSTR)sString, iChars, NULL, NULL);
if (iChars == 0)
{
free(sString);
Expand All @@ -489,7 +489,7 @@ BOOL WriteToFile(std::wstring & sStringToWrite, HANDLE hFile)

// write to file, free memory, and return result
DWORD iBytes = 0;
BOOL bResult = WriteFile(hFile, sString, iChars, &iBytes, NULL);
const BOOL bResult = WriteFile(hFile, sString, iChars, &iBytes, NULL);
free(sString);
return bResult;
}
}
12 changes: 6 additions & 6 deletions InputOutput.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,37 @@ class InputOutput

public:

static bool & InQuietMode()
static bool & InQuietMode() noexcept
{
static bool bQuietMode = false;
return bQuietMode;
}

static bool & InWhatIfMode()
static bool & InWhatIfMode() noexcept
{
static bool bWhatIfMode = false;
return bWhatIfMode;
}

static bool & ExcludeHiddenSystem()
static bool & ExcludeHiddenSystem() noexcept
{
static bool bExcludeHiddenSystem = false;
return bExcludeHiddenSystem;
}

static short & MaxThreads()
static short & MaxThreads() noexcept
{
static short iMaxThreads = 5;
return iMaxThreads;
}

static bool & Log()
static bool & Log() noexcept
{
static bool bLog = false;
return bLog;
}

static std::vector<std::wstring> & ScanPaths()
static std::vector<std::wstring> & ScanPaths() noexcept
{
static std::vector<std::wstring> vScanPaths;
return vScanPaths;
Expand Down
48 changes: 24 additions & 24 deletions Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,22 @@ void AnalyzeSecurity(ObjectEntry & oEntry)
bool bGroupIsDirty = false;

// read security information from the file handle
PACL tAclDacl = NULL;
PACL tAclSacl = NULL;
PSID tOwnerSid = NULL;
PSID tGroupSid = NULL;
PSECURITY_DESCRIPTOR tDesc = NULL;
PACL tAclDacl = nullptr;
PACL tAclSacl = nullptr;
PSID tOwnerSid = nullptr;
PSID tGroupSid = nullptr;
PSECURITY_DESCRIPTOR tDesc = nullptr;
DWORD iError = 0;
if (iInformationToLookup != 0 &&
(iError = GetNamedSecurityInfo(oEntry.Name.c_str(), SE_FILE_OBJECT,
iInformationToLookup, (bFetchOwner) ? &tOwnerSid : NULL, (bFetchGroup) ? &tGroupSid : NULL,
(bFetchDacl) ? &tAclDacl : NULL, (bFetchSacl) ? &tAclSacl : NULL, &tDesc)) != ERROR_SUCCESS)
iInformationToLookup, (bFetchOwner) ? &tOwnerSid : nullptr, (bFetchGroup) ? &tGroupSid : nullptr,
(bFetchDacl) ? &tAclDacl : nullptr, (bFetchSacl) ? &tAclSacl : nullptr, &tDesc)) != ERROR_SUCCESS)
{
// attempt to look up error message
LPWSTR sError = NULL;
size_t iSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
LPWSTR sError = nullptr;
const size_t iSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL, iError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&sError, 0, NULL);
nullptr, iError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&sError, 0, nullptr);
InputOutput::AddError(L"Unable to read file security", (iSize == 0) ? L"" : sError);
if (iSize > 0) LocalFree(sError);

Expand All @@ -96,7 +96,7 @@ void AnalyzeSecurity(ObjectEntry & oEntry)
bool bSaclCleanupRequired = false;
bool bOwnerCleanupRequired = false;
bool bGroupCleanupRequired = false;
bool bDescCleanupRequired = (tDesc != NULL);
bool bDescCleanupRequired = (tDesc != nullptr);

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

Expand Down Expand Up @@ -273,7 +273,7 @@ void AnalyzingQueue()

// update object attributes object
OBJECT_ATTRIBUTES oAttributes;
InitializeObjectAttributes(&oAttributes, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL);
InitializeObjectAttributes(&oAttributes, nullptr, OBJ_CASE_INSENSITIVE, nullptr, nullptr);
oAttributes.ObjectName = &tPathU;

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

// done processing
if (Status == STATUS_NO_MORE_FILES) break;
Expand All @@ -324,7 +324,7 @@ void AnalyzingQueue()
}

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

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

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

// do the scan
ULONGLONG iTimeStart = GetTickCount64();
const ULONGLONG iTimeStart = GetTickCount64();
BeginFileScan();
ULONGLONG iTimeStop = GetTickCount64();
const ULONGLONG iTimeStop = GetTickCount64();

// print out statistics
wprintf(L"===============================================================================\n");
Expand Down
18 changes: 9 additions & 9 deletions Notes.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
This file contains various information that may be useful in understanding
various elements of ACL, ACE, or SID contructs.
various elements of ACL, ACE, or SID constructs.

IO CI OI DIR DOB SUB SOB
0 0 0 1 0 0 0 icacls Exact /grant Everyone:F
0 0 1 1 1 0 1 icacls Exact /grant Everyone:(OI)F
0 1 0 1 0 1 0 icacls Exact /grant Everyone:(CI)F
0 1 1 1 1 1 1 icacls Exact /grant Everyone:(CI)(OI)F
1 0 0 0 0 0 0 icacls Exact /grant Everyone:(IO)F
1 0 1 0 1 0 1 icacls Exact /grant Everyone:(OI)(IO)F
1 1 0 0 0 1 0 icacls Exact /grant Everyone:(CI)(IO)F
1 1 1 0 1 1 1 icacls Exact /grant Everyone:(CI)(OI)(IO)F
0 0 0 1 0 0 0 icacls Exact /grant Everyone:(F)
0 0 1 1 1 0 1 icacls Exact /grant Everyone:(OI)(F)
0 1 0 1 0 1 0 icacls Exact /grant Everyone:(CI)(F)
0 1 1 1 1 1 1 icacls Exact /grant Everyone:(CI)(OI)(F)
1 0 0 0 0 0 0 icacls Exact /grant Everyone:(IO)(F)
1 0 1 0 1 0 1 icacls Exact /grant Everyone:(OI)(IO)(F)
1 1 0 0 0 1 0 icacls Exact /grant Everyone:(CI)(IO)(F)
1 1 1 0 1 1 1 icacls Exact /grant Everyone:(CI)(OI)(IO)(F)

Bit Mapping
DIR = ~IO
Expand Down
4 changes: 2 additions & 2 deletions Operation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
bool Operation::ProcessAclAction(WCHAR * const sSdPart, ObjectEntry & tObjectEntry, PACL & tCurrentAcl, bool & bAclReplacement)
{
// return immediately if acl is null
if (tCurrentAcl == NULL) return false;
if (tCurrentAcl == nullptr) return false;

// flag to note whether a change was actually made
bool bMadeChange = false;
Expand Down Expand Up @@ -75,7 +75,7 @@ bool Operation::ProcessAclAction(WCHAR * const sSdPart, ObjectEntry & tObjectEnt
else
{
PBYTE const tNewAcl = (PBYTE)LocalAlloc(LMEM_FIXED, tAcl->AclSize + (iNewLen - iOldLen));
if (tNewAcl == NULL)
if (tNewAcl == nullptr)
{
wprintf(L"ERROR: Unable to allocate memory for new SID.\n");
exit(-1);
Expand Down
8 changes: 6 additions & 2 deletions Operation.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ typedef ACCESS_ACE *PACCESS_ACE;
#define HasNoPropogate(x) CheckBitSet((x)->Header.AceFlags,NO_PROPAGATE_INHERIT_ACE)
#define GetNonOiCiIoBits(x) ((~(CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE)) & (x)->Header.AceFlags)

// string helper operations
#define ConvertToUpper(_x) std::transform(_x.begin(), _x.end(), _x.begin(), \
[](const WCHAR c) noexcept { return static_cast<WCHAR>(::toupper(c)); });

typedef struct ObjectEntry
{
std::wstring Name;
Expand Down Expand Up @@ -80,7 +84,7 @@ class Operation
bool ExclusiveOperation = false;

DWORD SpecialCommitFlags = false;
PSID DefaultSidWhenEmpty = NULL;
PSID DefaultSidWhenEmpty = nullptr;

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

Operation(std::queue<std::wstring> & oArgList);
virtual ~Operation() = default;;
virtual ~Operation() = default;
};

#include "OperationFactory.h"
Loading

0 comments on commit 4e9ded0

Please sign in to comment.