Skip to content

Commit

Permalink
Baseline Version 2.0 Release
Browse files Browse the repository at this point in the history
- Added /RemoveDomain to remove any SIDs associated with the specified domain.
- Added /PathMode to specify registry and Active Directory paths.
- Added /MaxDepth to control how deep within containers to search ACLs.
- Modified /LocateShortcut to use COM smart pointers.
- Created helper routines for COM initialization.
  • Loading branch information
NoMoreFood committed Feb 16, 2022
1 parent 11e3140 commit cd29114
Show file tree
Hide file tree
Showing 64 changed files with 1,312 additions and 731 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.
54 changes: 28 additions & 26 deletions ConcurrentQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,49 @@
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>

template <typename T>
class ConcurrentQueue
{
public:
private:
std::condition_variable oItemAvailableCondition;
std::condition_variable oIsEmptyCondition;
std::queue<T> oQueue;
std::mutex oQueueMutex;
short iWaiters;

public:
ConcurrentQueue() = default;

T pop()
T Pop()
{
std::unique_lock<std::mutex> oMutexLock(oMutex);
while (oQueue.empty())
{
oCondition.wait(oMutexLock);
}
auto oVar = oQueue.front();
std::unique_lock<std::mutex> mlock(oQueueMutex);
if (--iWaiters == 0 && oQueue.empty()) oIsEmptyCondition.notify_one();
oItemAvailableCondition.wait(mlock, [&]() noexcept { return !oQueue.empty(); });
auto oQueueItem = oQueue.front();
oQueue.pop();
return oVar;
iWaiters++;
return oQueueItem;
}

void push(const T& oItem)
void Push(const T& oQueueItem)
{
std::unique_lock<std::mutex> oMutuxLock(oMutex);
oQueue.push(oItem);
oMutuxLock.unlock();
oCondition.notify_one();
{
std::lock_guard<std::mutex> mlock(oQueueMutex);
oQueue.push(oQueueItem);
}
oItemAvailableCondition.notify_one();
}

void pop(T& oItem)
void WaitForEmptyQueues()
{
std::unique_lock<std::mutex> mlock(oMutex);
while (oQueue.empty())
{
oCondition.wait(mlock);
}
oItem = oQueue.front();
oQueue.pop();
std::unique_lock<std::mutex> mlock(oQueueMutex);
oIsEmptyCondition.wait(mlock, [&]() noexcept { return iWaiters == 0; });
}

private:
std::condition_variable oCondition;
std::queue<T> oQueue;
std::mutex oMutex;
void SetWaiterCounter(short iWaitCounters)
{
iWaiters = iWaitCounters;
}
};
52 changes: 33 additions & 19 deletions Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
#include <shared_mutex>

#include "Operation.h"
#include "Functions.h"
#include "Helpers.h"

PSID GetSidFromName(const std::wstring & sAccountName)
PSID GetSidFromName(const std::wstring& sAccountName)
{
// for caching
static std::shared_mutex oMutex;
Expand Down Expand Up @@ -60,7 +60,7 @@ PSID GetSidFromName(const std::wstring & sAccountName)

// reallocate memory and copy sid to a smaller part of memory and
// then add the sid to the cache map
auto tSid = (PSID) memcpy(malloc(iSidSize), tSidFromName, iSidSize);
auto tSid = (PSID)memcpy(malloc(iSidSize), tSidFromName, iSidSize);

// scope lock for thread safety
{
Expand All @@ -72,7 +72,7 @@ PSID GetSidFromName(const std::wstring & sAccountName)
return tSid;
}

std::wstring GetNameFromSid(const PSID tSid, bool * bMarkAsOrphan)
std::wstring GetNameFromSid(const PSID tSid, bool* bMarkAsOrphan)
{
// return immediately if sid is null
if (tSid == NULL) return L"";
Expand Down Expand Up @@ -126,7 +126,7 @@ std::wstring GetNameFromSid(const PSID tSid, bool * bMarkAsOrphan)
}

// copy the sid for storage in our cache table
const DWORD iSidLength = GetLengthSid(tSid);
const DWORD iSidLength = SidGetLength(tSid);
auto tSidCopy = (PSID)memcpy(malloc(iSidLength), tSid, iSidLength);

// scope lock for thread safety
Expand All @@ -139,14 +139,14 @@ std::wstring GetNameFromSid(const PSID tSid, bool * bMarkAsOrphan)
return sFullName;
}

std::wstring GetNameFromSidEx(const PSID tSid, bool * bMarkAsOrphan)
std::wstring GetNameFromSidEx(const PSID tSid, bool* bMarkAsOrphan)
{
// if sid is resolvable then return the account name
std::wstring sName = GetNameFromSid(tSid, bMarkAsOrphan);
if (!sName.empty()) return sName;

// if sid is unresolvable then return sid in string form
WCHAR * sSidBuf;
WCHAR* sSidBuf;
ConvertSidToStringSid(tSid, &sSidBuf);
std::wstring sSid(sSidBuf);
LocalFree(sSidBuf);
Expand Down Expand Up @@ -181,7 +181,6 @@ std::wstring GenerateInheritanceFlags(DWORD iCurrentFlags)
return sFlags;
}


std::wstring GenerateAccessMask(DWORD iCurrentMask)
{
// define the aesthetic names of permission
Expand Down Expand Up @@ -265,8 +264,8 @@ VOID EnablePrivs() noexcept
return;
}

const WCHAR * sPrivsToSet[] = { SE_RESTORE_NAME, SE_BACKUP_NAME,
SE_TAKE_OWNERSHIP_NAME, SE_CHANGE_NOTIFY_NAME };
const WCHAR* sPrivsToSet[] = { SE_RESTORE_NAME, SE_BACKUP_NAME,
SE_TAKE_OWNERSHIP_NAME, SE_CHANGE_NOTIFY_NAME, SE_SECURITY_NAME };
for (auto& i : sPrivsToSet)
{
// populate the privilege adjustment structure
Expand Down Expand Up @@ -307,7 +306,7 @@ VOID EnablePrivs() noexcept

// convert the privilege name to a unicode string format
LSA_UNICODE_STRING sPrivilege;
sPrivilege.Buffer = (PWSTR) i;
sPrivilege.Buffer = (PWSTR)i;
sPrivilege.Length = (USHORT)(wcslen(i) * sizeof(WCHAR));
sPrivilege.MaximumLength = (USHORT)((wcslen(i) + 1) * sizeof(WCHAR));

Expand All @@ -317,7 +316,7 @@ VOID EnablePrivs() noexcept
{
LsaClose(hPolicyHandle);
wprintf(L"ERROR: Privilege '%s' was not able to be added with error '%lu'\n",
i, LsaNtStatusToWinError(iResult));
i, LsaNtStatusToWinError(iResult));
continue;
}

Expand All @@ -342,20 +341,20 @@ VOID EnablePrivs() noexcept
return;
}

HANDLE RegisterFileHandle(HANDLE hFile, const std::wstring & sOperation)
HANDLE RegisterFileHandle(HANDLE hFile, const std::wstring& sOperation)
{
// lookup do a reverse lookup on file name
static std::map<std::wstring, std::pair<HANDLE,std::wstring>> oFileLookup;
static std::map<std::wstring, std::pair<HANDLE, std::wstring>> oFileLookup;

// do a reverse lookup on the file name
const 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;
sPath.resize(iSize + 1);

// get the full name
if (GetFinalPathNameByHandle(hFile, (LPWSTR)sPath.data(), (DWORD)sPath.capacity(),
if (GetFinalPathNameByHandle(hFile, (LPWSTR)sPath.data(), (DWORD)sPath.capacity(),
FILE_NAME_NORMALIZED | VOLUME_NAME_NT) == 0)
{
wprintf(L"ERROR: The true path to the specified file could not be determined.\n");
Expand Down Expand Up @@ -400,7 +399,7 @@ std::wstring GetAntivirusStateDescription()
bool bIsEnabled = false;

// query the product list
IWSCProductList * PtrProductList = nullptr;
IWSCProductList* PtrProductList = nullptr;
if (FAILED(CoCreateInstance(__uuidof(WSCProductList), NULL, CLSCTX_INPROC_SERVER,
__uuidof(IWSCProductList), reinterpret_cast<LPVOID*> (&PtrProductList))))
{
Expand All @@ -425,7 +424,7 @@ std::wstring GetAntivirusStateDescription()
for (LONG i = 0; i < ProductCount; i++)
{
// get the product details
IWscProduct * PtrProduct = nullptr;
IWscProduct* PtrProduct = nullptr;
if (FAILED(PtrProductList->get_Item(i, &PtrProduct)))
{
PtrProductList->Release();
Expand Down Expand Up @@ -471,7 +470,7 @@ 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", (ULONGLONG) iFileSize.QuadPart);
wsprintf(sSize, L"%I64u", (ULONGLONG)iFileSize.QuadPart);
return std::wstring(sSize);
}

Expand Down Expand Up @@ -520,3 +519,18 @@ BOOL WriteToFile(const std::wstring& sStringToWrite, HANDLE hFile) noexcept
free(sString);
return bResult;
}

VOID InitThreadCom() noexcept
{
thread_local static bool bComInitialized = false;
if (!bComInitialized)
{
bComInitialized = true;
const HRESULT hComInit = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
if (hComInit != S_OK && hComInit != S_FALSE)
{
wprintf(L"Could not initialize COM.\n");
exit(-1);
}
}
}
9 changes: 6 additions & 3 deletions Functions.h → Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <sddl.h>
#include <string>

#include "Operation.h"

// helper functions
VOID EnablePrivs() noexcept;
PSID GetSidFromName(const std::wstring & sAccountName);
Expand All @@ -18,14 +20,15 @@ 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;
VOID InitThreadCom() noexcept;

// helper typedefs
typedef struct SidCompare
{
inline bool operator()(PSID p1, PSID p2) const noexcept
inline bool operator()(PSID p1, PSID p2) const
{
const DWORD iLength1 = GetLengthSid(p1);
const DWORD iLength2 = GetLengthSid(p2);
const DWORD iLength1 = SidGetLength(p1);
const DWORD iLength2 = SidGetLength(p2);
if (iLength1 != iLength2) return iLength1 < iLength2;
return memcmp(p1, p2, iLength1) > 0;
}
Expand Down
6 changes: 3 additions & 3 deletions InputOutput.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ class InputOutput
{
private:

static std::wstring & GetFileName()
static std::wstring & GetFileName() noexcept
{
thread_local std::wstring sScreenBuffer;
return sScreenBuffer;
}

static std::wstring & GetDetail()
static std::wstring & GetDetail() noexcept
{
thread_local std::wstring sScreenBuffer;
return sScreenBuffer;
Expand Down Expand Up @@ -116,7 +116,7 @@ class InputOutput
// output to screen if there is anything to write
if (!GetFileName().empty() && !GetDetail().empty())
{
wprintf(L"FILE: %s", (GetFileName() + L"\n" + GetDetail()).c_str());
wprintf(L"OBJECT: %s", (GetFileName() + L"\n" + GetDetail()).c_str());
}

// clear out buffer now that it's printed
Expand Down
Loading

0 comments on commit cd29114

Please sign in to comment.