Created
December 7, 2022 01:11
-
-
Save iljavs/3d57fa554b1847e6fc6d4150eb110d5b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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