File created/modified audit settings with EventLog in C++

Hello Experts,

I want to write a C++ program for setting audit property settings.

I know we can audit file access EventLog like followings,

https://blogs.manageengine.com/it-security/eventloganalyzer/2012/06/20/object-access-auditing-simplified-find-the-who-what-where-when-of-file-folder-access.html

We have to set "Audit object access" to true in local security policy and set audit property to true of target folders manually.
I want to know how to set audit property of target folders(Folder->Property->Security->Advanced->Auditing->Create files / write data to TRUE) by C++ program.

Any idea welcome.

Nobuo Miwa
Nobuo MiwaSecurity EngineerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
First of all - be aware that you are delving into heavy stuff here.

You can do that using 'AddAuditAccessAce()' (https://msdn.microsoft.com/en-us/library/windows/desktop/aa374973%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396). Unfortunately, there isn't much sample code out there, but surprisingly there's an MSDN entry about a bugfix that comes with code illustrating how to use it, see http://support.microsoft.com/kb/274432/en-us

/*   

   The following sample code demonstrates how to add an access-control 
   entry (ACE) to an object's System Access Control List (SACL). The SACL 
   for an object lets the system know when to make entries in the system 
   security log when the object is accessed. See the documentation in the 
   Platform SDK for additional information on Auditing and Windows NT 
   Security.

   The sample adds a failure audit ACE for "Everyone" with read access.
   This audit ACE is added to an existing directory called C:\Test. The
   directory must exist.

   The procedure to add an ACE to an object's SACL is similar to that used
   for adding an ACE to an object's DACL. The exceptions are:

   DACL API                      SACL API

   GetSecurityDescriptorDacl     GetSecurityDescriptorSacl
   AddAccessAllowedAce           AddAuditAccessAce
   SetSecurityDescriptorDacl     SetSecurityDescriptorSacl

   The "rules" for ACE composition vary from object type to object type.
   This sample code generates an Audit ACE that works for a directory/file.
   A different type of object, for example, a registry key, may require       different access masks and inheritance flags. 

   This code sample requires the following import library:       
   
        advapi32.lib
*/ 

#include <windows.h>
#include <stdio.h>

#define SD_SIZE (65536 + SECURITY_DESCRIPTOR_MIN_LENGTH)

BOOL EnableSecurityName(void);
BOOL AddAuditAce(CHAR *pFileName, DWORD dwAccessMask);

int main(void)
{
    // Enable the SE_SECURITY_NAME privilege.

    if (!EnableSecurityName())
        return FALSE;

    // Do the work to add the ACE to the SACL.

    if (!AddAuditAce(
        "c:\\test",                                  // Name of directory.
        FILE_GENERIC_READ | ACCESS_SYSTEM_SECURITY)) // "Read" audit. 

    // 
    // The following audit mask combinations duplicate the
    // different audit settings that you can apply through
    // WinNT 4.0 Explorer
    // 
    // 
    // FILE_GENERIC_WRITE | ACCESS_SYSTEM_SECURITY // "Write"
    // FILE_GENERIC_EXECUTE                        // "Execute"
    // DELETE                                      // "Delete"   
    // WRITE_DAC                                   // "Change Permissions"
    // WRITE_OWNER                                 // "Write Owner"
    // 
        printf("Could not add audit entry to SACL\n");
    else
        printf("Added audit entry to SACL\n");

    return TRUE;
}

BOOL EnableSecurityName(void)
{
    // A process that tries to read or write a SACL needs
    // to have and enable the SE_SECURITY_NAME privilege.
    
    HANDLE hToken;
    LUID SecurityNameValue;
    TOKEN_PRIVILEGES tkp;

    if (!OpenProcessToken(GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    {
        printf("Error: OpenProcessToken (%lu)\n", GetLastError());
        return FALSE;
    }

    if (!LookupPrivilegeValue((LPSTR)NULL,
            SE_SECURITY_NAME,
            &SecurityNameValue))
    {
        printf("Error: LookupPrivilegeValue (%lu)\n", GetLastError());
        return FALSE;
    }

    tkp.PrivilegeCount = 1;
    tkp.Privileges[ 0 ]. Luid = SecurityNameValue;
    tkp.Privileges[ 0 ]. Attributes = SE_PRIVILEGE_ENABLED;

    if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES),
                (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL))
    {
        printf("Error: AdjustTokenPrivileges (%lu)\n", GetLastError());
        return FALSE;
    }

    return TRUE ;
}

BOOL AddAuditAce(CHAR *pFileName, DWORD dwAccessMask)
{ 
    // SID variables.

    SID_IDENTIFIER_AUTHORITY authWorld = SECURITY_WORLD_SID_AUTHORITY; 
    PSID psidWorld = NULL; 

    // Directory SD variables.

    UCHAR          ucSDbuf[SD_SIZE];
    PSECURITY_DESCRIPTOR pFileSD=(PSECURITY_DESCRIPTOR)ucSDbuf;
    DWORD          dwSDLengthNeeded;

    // ACL variables.

    PACL           pACL = NULL;
    BOOL           bSaclPresent;
    BOOL           bSaclDefaulted;
    ACL_SIZE_INFORMATION AclInfo;

    // New ACL variables.

    PACL           pNewACL = NULL;
    DWORD          dwNewACLSize;

    // New SD variables.

    UCHAR                NewSD[SECURITY_DESCRIPTOR_MIN_LENGTH];
    PSECURITY_DESCRIPTOR psdNewSD=(PSECURITY_DESCRIPTOR)NewSD;

    // Temporary ACE.

    PVOID          pTempAce;
    UINT           CurrentAceIndex;

    // New ACE variables.
    // Use flags compatible with what explorer uses for a container.

    BYTE bAceFlags = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
    
    BOOL bReturn = FALSE;

    __try
    {
        // Build the "Everyone" SID.
        if (!AllocateAndInitializeSid(
            &authWorld,     
            1, 
            SECURITY_WORLD_RID,     
            0,     
            0,     
            0,     
            0,     
            0,     
            0,     
            0, 
            &psidWorld))
        {
            printf("Error: AllocateAndInitializeSid (%lu)\n",GetLastError());
            __leave;
        }

        // Get security descriptor (SD) for directory.

        if (!GetFileSecurity(
            pFileName,
            (SECURITY_INFORMATION)(SACL_SECURITY_INFORMATION), 
            pFileSD,
            SD_SIZE,
            (LPDWORD)&dwSDLengthNeeded))
        {
            printf("Error %d:GetFileSecurity\n",GetLastError());
            __leave;
        }

        // Initialize new SD.

        if (!InitializeSecurityDescriptor(psdNewSD,SECURITY_DESCRIPTOR_REVISION))
        {
            printf("Error: InitializeSecurityDescriptor (%lu)\n",GetLastError());
            __leave;
        }

        // Get SACL from SD.

        if (!GetSecurityDescriptorSacl(
            pFileSD, 
            &bSaclPresent,
            &pACL,
            &bSaclDefaulted))
        {
            printf("Error: GetSecurityDescriptorSacl (%lu)\n",GetLastError());
            __leave;
        }

        // Get directory ACL size information.

        if (bSaclPresent && pACL)
        {
            if (!GetAclInformation(pACL,&AclInfo,sizeof(ACL_SIZE_INFORMATION),
                AclSizeInformation))
            {
                printf("Error: GetAclInformation (%lu)\n",GetLastError());
                __leave;
            }
        }
        else
        {
            // If you don't have a SACL, 
            // allow some room for the ACL header and flags.
            AclInfo.AclBytesInUse = sizeof(ACL) ;

            // Set the ACE count. 
            AclInfo.AceCount = 0;
        }

        // Compute size needed for the new ACL.

        dwNewACLSize = AclInfo.AclBytesInUse +
                      sizeof(ACCESS_ALLOWED_ACE) +
                      GetLengthSid(psidWorld) - sizeof(DWORD);
 

        // Allocate memory for new ACL.

        pNewACL = (PACL)LocalAlloc(LPTR, dwNewACLSize);

        // Initialize the new ACL

        if (!InitializeAcl(pNewACL, dwNewACLSize, ACL_REVISION2))
        {
            printf("Error %d:InitializeAcl\n",GetLastError());
            __leave;
        }
 
        // If SACL is present, copy it to a new SACL.

        if (bSaclPresent && pACL)  // Only copy if SACL was present.
        {
            printf("Copying SACL information to new SACL\n");

            // Copy the directory's ACEs to our new ACL.

            if (AclInfo.AceCount)
            {
                for(CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount;
                    CurrentAceIndex++)
                {
                    // Get an ACE.
                    if (!GetAce(pACL,CurrentAceIndex,&pTempAce))
                    {
                        printf("Error %d: GetAce\n",GetLastError());
                        __leave;
                    }

                    // Add the ACE to the new ACL.

                    if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
                        ((PACE_HEADER)pTempAce)->AceSize))
                    {
                        printf("Error %d:AddAce\n",GetLastError());
                        __leave;
                    }
                }
            }
        }

        // Add the audit ACE to the new SACL.

        printf("Adding new ACE to SACL\n");

        if (!AddAuditAccessAce(
            pNewACL,
            ACL_REVISION2,
            dwAccessMask, 
            psidWorld,
            FALSE,         // Do not audit successful access.
            TRUE))         // Audit unsuccessful access.
       {
            printf("Error: AddAuditAccessAce (%lu)",GetLastError());
            __leave;
       }

        // Get the ace you just added, so you can change the AceFlags.

        if (!GetAce(
            pNewACL,
            AclInfo.AceCount, // This is the zero-based index of the new ACE.
            &pTempAce))
        {
            printf("Error: GetAce (%lu)\n",GetLastError());
            __leave;
        }
   
        // Set AceFlags member with existing flags so you don't loose the 
        // success/unsuccess audit flags.

        ((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags = 
            bAceFlags | ((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags;

        // Set new SACL to the SD.

        printf("Setting SACL to SD\n");

        if (!SetSecurityDescriptorSacl(
            psdNewSD, 
            TRUE,
            pNewACL,
            FALSE))
        {
            printf("Error: SetSecurityDescriptorSacl (%lu)",GetLastError());
            __leave;
        }

        // Set the SD to the directory.

        printf("Set SD to directory\n");

        if (!SetFileSecurity(pFileName, SACL_SECURITY_INFORMATION,psdNewSD)) 
        {
            printf("Error: SetFileSecurity (%lu)\n",GetLastError());
            __leave;
        }

        bReturn = TRUE;
    }
    __finally
    {
        // Free the allocated SID.
        if (psidWorld) FreeSid(psidWorld);

        // Free the memory allocated for the new ACL.
        if (pNewACL) LocalFree((HLOCAL) pNewACL);
    }

    return bReturn;
}

Open in new window


There is also an article available at http://www.codeproject.com/Articles/10200/The-Windows-Access-Control-Model-Part ("The Windows Access Control Model: Part 2") which comes with helper classes to encapsulate that to some extent, but it's still not simple.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Nobuo MiwaSecurity EngineerAuthor Commented:
Thanks for the advice.
I will try this.
0
jkrCommented:
Thank you and good luck! ;o)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.