【内核与用户层同步】内核对象安全描述符降权

  • Post author:
  • Post category:其他

DriverEntry 创建一个命名的内核通知事件对象

	HANDLE g_hEvent = NULL;
	PKEVENT g_kEvent = NULL;
 	__debugbreak();
    
    UNICODE_STRING usEventName = RTL_CONSTANT_STRING(L"\\BaseNamedObjects\\test_event");
    g_kEvent = IoCreateNotificationEvent(&usEventName, &g_hEvent);
    KeClearEvent(g_kEvent);
    
	// 修改内核对象安全描述符
	SetEventACL(g_hEvent);

    DbgPrint("g_kEvent=%p g_hEvent=%p Name=%wZ \n",g_kEvent, g_hEvent, &usEventName);

用户层打开该对象,并创建线程,等待事件通知

HANDLE g_UserEvent = NULL;

DWORD WINAPI MyThreadFunction( LPVOID lpParam ) 
{ 
    if(WAIT_OBJECT_0 == WaitForSingleObject(g_UserEvent, INFINITE))
    {
        printf("User Mode Thread Signaled.\n");

    }

    printf("Loop Thread Exited.\n");

    return 0; 
} 


int main()
{

	do 
    {
          g_UserEvent =  OpenEventA(SYNCHRONIZE, NULL, "Global\\test_event");
          
    } while (!g_UserEvent);

    HANDLE hThread = CreateThread(0, NULL, MyThreadFunction, NULL, 0, NULL);

    printf("UserMode Loop Thread Wait for Kernel Event Siginal. hThread=%p g_UserEvent=%p\n",hThread, g_UserEvent);

}

此时用户层程序如果是普通用户权限,则打开Event失败,因为内核创建的对象,普通用户层是没有权限打开的

使用下面函数修改内核Event的安全描述符以后,加入SeAliasUsersSid,给普通用户也赋予权限,这样就可以打开内核的Event了,

NTSTATUS SetEventACL(HANDLE hObj)
{
    ULONG uACLSize = 0;
    PACL  pACL     = NULL;
    SECURITY_DESCRIPTOR SecurityDesc = {0};
    NTSTATUS Status = STATUS_UNSUCCESSFUL;

    do 
    {
        //
        // Calculate how big our ACL needs to be support one ACE 
        // (in this case we'll use a predefined Se Export for local system as the SID)
        //

        uACLSize = sizeof(ACL);
        uACLSize += RtlLengthSid(SeExports->SeLocalSystemSid);
        uACLSize += RtlLengthSid(SeExports->SeAliasAdminsSid);
        uACLSize += RtlLengthSid(SeExports->SeAliasUsersSid);
        
        //
        // Room for 3 ACEs (one for each SID above); note we don't
        // include the end of the structure as we've accounted for that length in the SID lengths already.
        //

        uACLSize += 3 * FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
        
        pACL = (PACL)ExAllocatePool(PagedPool, uACLSize);
        if(pACL == NULL)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }
        
        Status = RtlCreateAcl(pACL, uACLSize, ACL_REVISION);
        if(!NT_SUCCESS(Status))
        {
            break;
        }

        Status = RtlAddAccessAllowedAce(pACL, ACL_REVISION, GENERIC_ALL, SeExports->SeLocalSystemSid);
        if(!NT_SUCCESS(Status))
        {
            break;
        }

        Status = RtlAddAccessAllowedAce(pACL, ACL_REVISION, GENERIC_ALL, SeExports->SeAliasAdminsSid);
        if(!NT_SUCCESS(Status))
        {
            break;
        }

        Status = RtlAddAccessAllowedAce(pACL, ACL_REVISION, GENERIC_ALL, SeExports->SeAliasUsersSid);
        if(!NT_SUCCESS(Status))
        {
            break;
        }
        
        //
        // Create a SecurityDescriptor
        //

        Status = RtlCreateSecurityDescriptor(&SecurityDesc, SECURITY_DESCRIPTOR_REVISION);
        if(!NT_SUCCESS(Status))
        {
            break;
        }

        //
        // Associate the above pACL with the security descriptor
        //
        
        Status = RtlSetDaclSecurityDescriptor(&SecurityDesc, TRUE, pACL, FALSE);
        if(!NT_SUCCESS(Status))
        {
            break;
        }

        //
        // Set security on the object
        //

        Status = ZwSetSecurityObject(hObj, DACL_SECURITY_INFORMATION, &SecurityDesc);
        if(!NT_SUCCESS(Status))
        {
            break;
        }


    } while (false);

    if(pACL)
    {
        ExFreePool(pACL);
        pACL = NULL;
    }

    return Status;

}

版权声明:本文为cssxn原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。