Skip to content

Instantly share code, notes, and snippets.

@iljavs
Created December 7, 2022 01:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iljavs/3d57fa554b1847e6fc6d4150eb110d5b to your computer and use it in GitHub Desktop.
Save iljavs/3d57fa554b1847e6fc6d4150eb110d5b to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <windows.h>
#include <sddl.h>
#pragma comment(lib, "advapi32.lib")
void error(char *msg) {
fprintf(stderr, "%s" , msg);
exit(1);
}
void displaySID(ACCESS_ALLOWED_ACE *pAce) {
PSID pSid;
char *pName;
char *pDomain;
DWORD dwNameSize = 0;
DWORD dwDomainSize = 0;
SID_NAME_USE snu;
DWORD dwRtnCode;
pSid = (PSID)&pAce->SidStart;
// First call to LookupAccountSid to get the buffer sizes.
BOOL r = LookupAccountSid(NULL,
pSid,
NULL,
&dwNameSize,
NULL,
&dwDomainSize,
&snu);
DWORD e = GetLastError();
if (r == TRUE || e == ERROR_INSUFFICIENT_BUFFER) {
// Allocate memory for the name and domain.
pName = (char *)malloc(dwNameSize);
pDomain = (char *)malloc(dwDomainSize);
if (pName == NULL || pDomain == NULL) {
error("Memory allocation failed");
}
// Second call to LookupAccountSid to get the account name.
if (!LookupAccountSid(NULL,
pSid,
pName,
&dwNameSize,
pDomain,
&dwDomainSize,
&snu)) {
pName[0] = '\0';
pDomain[0] = '\0';
}
} else {
pName = malloc(10);
pDomain = malloc(10);
if (pName == NULL || pDomain == NULL) {
error("Memory allocation failed");
}
pName[0] = '\0';
pDomain[0] = '\0';
}
// get string representation of a SID
char *pSidString = NULL;
ConvertSidToStringSid(pSid, &pSidString);
printf("USER: %s\\%s SID:%s (0x%x)\n",
pDomain,
pName,
pSidString,
pAce->Mask);
if (pSidString != NULL) {
LocalFree(pSidString);
}
free(pName);
free(pDomain);
return;
}
void displayPerms(ACCESS_ALLOWED_ACE *pAce) {
printf("Permissions: 0x%x\n", pAce->Mask);
// print permissions from the access mask
if (pAce->Mask & FILE_READ_DATA) {
printf("\tRead data\n");
}
if (pAce->Mask & FILE_WRITE_DATA) {
printf("\tWrite data\n");
}
if (pAce->Mask & FILE_APPEND_DATA) {
printf("\tAppend data\n");
}
if (pAce->Mask & FILE_READ_EA) {
printf("\tReadEA\n");
}
if (pAce->Mask & FILE_WRITE_EA) {
printf("\tWriteEA\n");
}
if (pAce->Mask & FILE_EXECUTE) {
printf("\tExecute\n");
}
if (pAce->Mask & FILE_DELETE_CHILD) {
printf("\tDeleteChild\n");
}
if (pAce->Mask & FILE_READ_ATTRIBUTES) {
printf("\tReadAttributes\n");
}
if (pAce->Mask & FILE_WRITE_ATTRIBUTES) {
printf("\tWriteAttributes\n");
}
if (pAce->Mask & DELETE) {
printf("\tDelete\n");
}
if (pAce->Mask & READ_CONTROL) {
printf("\tReadControl\n");
}
if (pAce->Mask & WRITE_DAC) {
printf("\tWriteDac\n");
}
if (pAce->Mask & WRITE_OWNER) {
printf("\tWriteOwner\n");
}
if (pAce->Mask & SYNCHRONIZE) {
printf("\tSynchronize\n");
}
if (pAce->Mask & STANDARD_RIGHTS_REQUIRED) {
printf("\tStdRightsRequired\n");
}
if (pAce->Mask & STANDARD_RIGHTS_ALL) {
printf("\tStdRightsAll\n");
}
if (pAce->Mask & SPECIFIC_RIGHTS_ALL) {
printf("\tSpecificRightsAll\n");
}
if (pAce->Mask & ACCESS_SYSTEM_SECURITY) {
printf("\tAccessSystemSecurity\n");
}
if (pAce->Mask & MAXIMUM_ALLOWED) {
printf("\tMaximumAllowed\n");
}
if (pAce->Mask & GENERIC_READ) {
printf("\tGenericRead\n");
}
if (pAce->Mask & GENERIC_WRITE) {
printf("\tGenericWrite\n");
}
if (pAce->Mask & GENERIC_EXECUTE) {
printf("\tGenericExecute\n");
}
if (pAce->Mask & GENERIC_ALL) {
printf("\tGenericAll\n");
}
return;
}
void displayAce(PACL pAcl, int i) {
ACCESS_ALLOWED_ACE *pAce;
if (!GetAce(pAcl, i, (LPVOID *)&pAce))
error("GetAce failed");
ACE_HEADER *aceHeader = (ACE_HEADER *)pAce;
printf("ACE %d: \n", i);
printf("ACE size: %d\n", aceHeader->AceSize);
switch (aceHeader->AceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
printf("ACCESS_ALLOWED_ACE_TYPE\n");
ACCESS_ALLOWED_ACE *accessAllowedAce = (ACCESS_ALLOWED_ACE *)pAce;
displaySID(pAce);
displayPerms(pAce);
break;
case ACCESS_DENIED_ACE_TYPE:
printf("ACCESS_DENIED_ACE_TYPE\n");
ACCESS_DENIED_ACE *accessDeniedAce = (ACCESS_DENIED_ACE *)pAce;
displaySID(pAce);
displayPerms(pAce);
break;
case SYSTEM_AUDIT_ACE_TYPE:
printf("SYSTEM_AUDIT_ACE_TYPE\n");
SYSTEM_AUDIT_ACE *systemAuditAce = (SYSTEM_AUDIT_ACE *)pAce;
displaySID(pAce);
displayPerms(pAce);
break;
case SYSTEM_ALARM_ACE_TYPE:
printf("SYSTEM_ALARM_ACE_TYPE\n");
SYSTEM_ALARM_ACE *systemAlarmAce = (SYSTEM_ALARM_ACE *)pAce;
displaySID(pAce);
displayPerms(pAce);
break;
default:
printf("Unknown ACE type\n");
break;
}
printf("\n");
}
void displayDacl(PSECURITY_DESCRIPTOR pSD) {
BOOL daclPresent;
BOOL daclDefaulted;
PACL pDacl;
// Retrieve the DACL from the security descriptor
if (GetSecurityDescriptorDacl(pSD, &daclPresent, &pDacl, &daclDefaulted))
{
// display the DACL
if (pDacl != NULL)
{
ACL_SIZE_INFORMATION aclSizeInfo;
if (GetAclInformation(pDacl,
&aclSizeInfo,
sizeof(ACL_SIZE_INFORMATION),
AclSizeInformation))
{
printf("DACL: %d ACEs (size %d bytes) %s default DACL\n",
aclSizeInfo.AceCount,
aclSizeInfo.AclBytesInUse,
daclDefaulted ? "is" : "is not");
printf("\n");
}
for (DWORD i = 0; i < aclSizeInfo.AceCount; i++)
{
displayAce(pDacl, i);
}
} else {
printf("DACL: NULL");
}
}
else
{
error("GetSecurityDescriptorDacl() failed\n");
}
return;
}
PSECURITY_DESCRIPTOR getFileSecurity(LPWSTR filePath) {
PSECURITY_DESCRIPTOR pSD;
DWORD sdSize = 0;
// Get the size of the security descriptor for the file
if (!GetFileSecurityW(filePath,
OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION,
NULL,
0,
&sdSize))
{
// get the last error
DWORD dwError = GetLastError();
if (dwError != ERROR_INSUFFICIENT_BUFFER) {
error("GetFileSecurity() failed1\n");
}
}
// Allocate memory for the security descriptor
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, sdSize);
if (!pSD)
{
error("LocalAlloc() failed\n");
}
// Retrieve the security descriptor for the file
if (!GetFileSecurityW(filePath,
OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION,
pSD,
sdSize,
&sdSize))
{
error("GetFileSecurity() failed2\n");
}
// Return the security descriptor
return pSD;
}
#define MAX_FILE_PATH 32768
LPWSTR ascii2wchar(char *str) {
size_t len = strlen(str);
if (len > MAX_FILE_PATH || len == 0) {
error("Path too long\n");
}
LPWSTR wstr = (LPWSTR)malloc((len + 1) * sizeof(WCHAR));
if (wstr == NULL) {
error("malloc() failed\n");
}
int r = MultiByteToWideChar(CP_ACP, 0, str, len, wstr, len);
if (r == 0) {
error("MultiByteToWideChar() failed\n");
}
wstr[len] = 0;
return wstr;
}
void FreeSecurityDescriptor(PSECURITY_DESCRIPTOR pSD) {
if (pSD)
{
LocalFree(pSD);
}
return;
}
int main(int argc, char **argv) {
PSECURITY_DESCRIPTOR pSD;
if (argc != 2) {
fprintf(stderr, "Usage: %s <file>\n" , argv[0]);
exit(1);
}
LPWSTR filePath = ascii2wchar(argv[1]);
pSD = getFileSecurity( filePath);
displayDacl(pSD);
FreeSecurityDescriptor(pSD);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment