How to adjust the Ace of device object

 
直接扔关键代码,不想写太多的说明,本来这些代码也只是副产品,眼尖的应该能看出来这些代码的来处和去处。


===============

PACCESS_ALLOWED_ACE
GetAceFromAcl(
    IN PACL Dacl,
    IN ULONG AceIndex
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/

{
    USHORT i = 0;
    PACCESS_ALLOWED_ACE Ace = NULL;

    if (Dacl && AceIndex < Dacl->AceCount)
    {
        for (Ace = FirstAce(Dacl); i < AceIndex; Ace = NextAce(Ace))
        {
            if (Ace >= (PACCESS_ALLOWED_ACE)((PUCHAR)Dacl + Dacl->AclSize))
            {
                break;
            }

            ++ i;   
        }

        if (i == AceIndex)
        {
            return Ace;
        }
    }

    return NULL;
}

BOOLEAN
NmCheckDaclForGroupSid(
    IN PACL Dacl
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/

{ 
    USHORT i = 0;
    USHORT gSidOffset, cSidOffset;
    BOOLEAN result = FALSE;
    PACCESS_ALLOWED_ACE pACE = NULL;
    SIZE_T retLong;

    if (g_GroupAce->Header.AceSize >= (USHORT)(sizeof(ACCESS_ALLOWED_ACE)))
    {
        gSidOffset = g_GroupAce->Header.AceSize -
              (USHORT)(sizeof(ACCESS_ALLOWED_ACE));  

        if (Dacl->AceCount)
        {
            do
            {
                pACE = GetAceFromAcl(Dacl, i);

                if (pACE)
                {
                    cSidOffset = pACE->Header.AceSize -
                          (USHORT)(sizeof(ACCESS_ALLOWED_ACE));

                    if (gSidOffset == cSidOffset)
                    {
                        retLong = RtlCompareMemory(
                            &(pACE->SidStart),
                            &(g_GroupAce->SidStart),
                            cSidOffset
                            );

                        result = (cSidOffset == retLong);

                        if (result == TRUE)
                        {
                            return result;
                        }
                    }
                 }

                 ++ i;

            } while (i < Dacl->AceCount);
        }
    }

    return result;
}

BOOLEAN
AddAceToAcl(
    IN PACL NewAcl,
    IN PACCESS_ALLOWED_ACE toAddAce
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/

{ 
    USHORT i = 0;
    PACCESS_ALLOWED_ACE Ace = FirstAce(NewAcl);

    if (NewAcl && toAddAce)
    {
        if (NewAcl->AceCount)
        {
            for (NOTHING; i < NewAcl->AceCount; Ace = NextAce(Ace))
            {
                if (Ace >= (PACCESS_ALLOWED_ACE)((PUCHAR)NewAcl + NewAcl->AclSize))
                {
                    break;
                }

                ++ i;
            }
         }

         if ((PACCESS_ALLOWED_ACE)((PUCHAR)Ace + toAddAce->Header.AceSize) >
                        (PACCESS_ALLOWED_ACE)((PUCHAR)NewAcl + NewAcl->AclSize))
         {
             return FALSE;
         }
         else
         {
             NdisMoveMemory(
                 Ace,
                 toAddAce,
                 toAddAce->Header.AceSize
                 );

             NewAcl->AceCount = i + 1;
         }
    }

    return TRUE;
}

NDIS_STATUS
NmModifyDacl(
    IN PACL oldDacl,
    OUT PACL* NewDacl
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/

{
    NDIS_STATUS result = NDIS_STATUS_SUCCESS;
    USHORT tSize;
    PACL tmpDacl = NULL;
    USHORT i = 0;
    PACCESS_DENIED_ACE pdACE = NULL;
    PACCESS_ALLOWED_ACE paACE = NULL;

    if (oldDacl)
    {
        tSize = oldDacl->AclSize + g_GroupAce->Header.AceSize;

        tmpDacl = (PACL)ExAllocatePoolWithTag(
            NonPagedPool,
            tSize,
            'dnTF'
            );
        if (tmpDacl)
        {
            tmpDacl->AclRevision = oldDacl->AclRevision;   
            tmpDacl->Sbz1 = oldDacl->Sbz1;
            tmpDacl->AceCount = 0;
            tmpDacl->AclSize = tSize;   
            tmpDacl->Sbz2 = oldDacl->Sbz2;

            if (oldDacl->AceCount)
            {
                do
                {
                    pdACE = (PACCESS_DENIED_ACE)GetAceFromAcl(
                        oldDacl,
                        i
                        );
                    if (pdACE->Header.AceType != ACCESS_DENIED_ACE_TYPE)
                    {
                        break;
                    }

                    AddAceToAcl(tmpDacl, (PACCESS_ALLOWED_ACE)pdACE);

                    ++ i;

                } while (i < oldDacl->AceCount);    
             }

             AddAceToAcl(tmpDacl, g_GroupAce);

             while(i < oldDacl->AceCount)
             {
                 paACE = GetAceFromAcl(oldDacl, i);

                 AddAceToAcl(tmpDacl, (PACCESS_ALLOWED_ACE)paACE);

                 ++ i;
             }

             *NewDacl= tmpDacl;
        }
    }   

    return result;
}

NDIS_STATUS
NmAddGroupAccessAce(
    IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:

Arguments:

Return Value:

--*/

{
    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
    PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
    PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL;

    ULONG csize = sizeof(SECURITY_DESCRIPTOR);
    PACL NewDdcl = NULL;
    HANDLE Handle = NULL;
    BOOLEAN DaclPresent, DaclDefaulted;
    PACL Dacl = NULL;

    if (DeviceObject && g_GroupAce)
    {
        Status = ObOpenObjectByPointer(
            DeviceObject,
            OBJ_KERNEL_HANDLE,
            NULL,
            WRITE_DAC,
            0,
            0,
            &Handle
            );
        if (Status == NDIS_STATUS_SUCCESS)
        {
            SecurityDescriptor = DeviceObject->SecurityDescriptor;

            Status = RtlGetDaclSecurityDescriptor(
                SecurityDescriptor,
                &DaclPresent,
                &Dacl,
                &DaclDefaulted
                );
            if (Status == NDIS_STATUS_SUCCESS)
            {
                ASSERT(DaclPresent);
                ASSERT(Dacl != NULL);

                if (NmCheckDaclForGroupSid(Dacl) != TRUE)
                {
                    csize = RtlLengthSecurityDescriptor(SecurityDescriptor);

                    NewSecurityDescriptor = ExAllocatePoolWithTag(
                        NonPagedPool,
                        g_GroupAce->Header.AceSize + csize,
                        'dnTF'
                        );
                    if (NewSecurityDescriptor)
                    {
                        RtlCreateSecurityDescriptor(
                            NewSecurityDescriptor,
                            SECURITY_DESCRIPTOR_REVISION
                            );

                        Status = NmModifyDacl(
                            Dacl,
                            &NewDdcl
                            );
                        if (Status == NDIS_STATUS_SUCCESS)
                        {
                            Status = RtlSetDaclSecurityDescriptor(
                                NewSecurityDescriptor,
                                TRUE,
                                NewDdcl,
                                FALSE
                                );
                            if (Status == NDIS_STATUS_SUCCESS)
                            {
                                Status = ZwSetSecurityObject(
                                    Handle,
                                    DACL_SECURITY_INFORMATION,
                                    NewSecurityDescriptor
                                    );
                            }
                        }
                    }
                }
            }
        }

        if (Handle)
        {
            ZwClose(Handle);
        }

        if (NewSecurityDescriptor)
        {
            ExFreePoolWithTag(NewSecurityDescriptor, 'dnTF');
        }

        if (NewDdcl)
        {
            ExFreePoolWithTag(NewDdcl, 'dnTF');
        }
    }

    return Status;
}

===============

在RegisterDevice之后加上即可,对于g_GroupAce,这个查询注册表或者自己获取,这些都是因时而异。
我这里是需要从注册表读过来的,然后加上去的:

===============

PACCESS_ALLOWED_ACE g_GroupAce = NULL;

//...省略...

       InitializeObjectAttributes(
           &ObjectAttributes,
           RegistryPath,
           OBJ_CASE_INSENSITIVE,
           NULL,
           NULL
           );

       Status = ZwOpenKey(
           &hHandle,
           KEY_READ,
           &ObjectAttributes
           );
       if (Status == STATUS_SUCCESS)
       {
           RtlInitUnicodeString(&DestinationString, L"GroupSid");

           Status = ZwQueryValueKey(
               hHandle,
               &DestinationString,
               KeyValueFullInformation,
               0,
               0,
               &ResultLength
               );
           if (Status == STATUS_BUFFER_OVERFLOW ||
               Status == STATUS_BUFFER_TOO_SMALL)
           {
               pBuffer = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePoolWithTag(
                   NonPagedPool,
                   ResultLength,
                   'dnTF'
                   );  
               if (pBuffer)
               {
                   Status = ZwQueryValueKey(
                       hHandle,
                       &DestinationString,
                       KeyValueFullInformation,
                       pBuffer,
                       ResultLength,
                       &ResultLength
                       );
                   if (Status == STATUS_SUCCESS)
                   {
                         g_GroupAce = (PACCESS_ALLOWED_ACE)ExAllocatePoolWithTag(
                              NonPagedPool,
                              pBuffer->DataLength + sizeof(ACCESS_ALLOWED_ACE),
                              'gamn'
                              );
                         if (g_GroupAce)
                         {
                              NdisZeroMemory(
                                  g_GroupAce,
                                  pBuffer->DataLength + sizeof(ACCESS_ALLOWED_ACE)
                                  );

                              g_GroupAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
                              g_GroupAce->Header.AceFlags = 0;
                              g_GroupAce->Header.AceSize =
                                   (USHORT)(pBuffer->DataLength +
                                   sizeof(ACCESS_ALLOWED_ACE));

                              g_GroupAce->Mask = SYNCHRONIZE |
                                   READ_CONTROL | FILE_READ_ATTRIBUTES |
                                   FILE_READ_DATA | FILE_READ_EA;

                              NdisMoveMemory(
                                  (PVOID)&(g_GroupAce->SidStart),
                                  (PVOID)((PUCHAR)pBuffer + pBuffer->DataOffset),
                                  pBuffer->DataLength
                                  );

//...省略...

===============

PS: 排版很麻烦,我改了半天。下篇把这个工程的真正精华部分放上来大家探讨。

随机日志


    Post a Comment