Developing a kernel-mode security package
KSecRegisterSecurityProvider called from DriverEntryRegistering a built-in package
Registration happens in ksecpkg!KsecExRegisterOneExtension. ksecdd!KsecRegisterExtension (called from KsecInstallBuiltinPackages) does the work, through IOCTL 0x390038 (CTL_CODE(FILE_DEVICE_KSEC, 0xE, FILE_ANY_ACCESS, METHOD_BUFFERED)) to \device\ksecdd.
The input buffer is 0x10 bytes, two 8-byte values:
- First:
0x2(the code) - Second: a pointer to an array of structures
Each structure holds two pointers:
- A pointer to
SECPKG_KERNEL_FUNCTION_TABLE(seentsecpkg.h) - A pointer to a
UNICODE_STRING
A zeroed structure ends the array. The Negotiate package lives in ksecdd itself.
Initializing a built-in package
ksecdd initializes the packages when LSA starts:
ksecpkg!NtLmInitKernelPackage ksecdd!InitializePackages+0x327 ksecdd!CreateClient+0xfe ksecdd!IsOkayToExec+0x1c ksecdd!InitSecurityInterfaceW+0xb ksecdd! ?? ::NNGAKEGL::`string'+0x48c ksecdd!KsecDispatch+0x9a nt!IopXxxControlFile+0x607 nt!NtDeviceIoControlFile+0x56 nt!KiSystemServiceCopyEnd+0x13 ntdll!ZwDeviceIoControlFile+0xa lsass!LsapOpenKsec+0xec lsass!main+0x14f lsass!MIDL_user_free+0x1b5 kernel32!BaseThreadInitThunk+0xd ntdll!RtlUserThreadStart+0x1d
Call KSecRegisterSecurityProvider() from the DriverEntry of a legacy driver. ksecdd.sys exports it.
SERVICE_BOOT_START, after ksecpkg.sys and before lsass.exe. Installing it takes a reboot.
KSecRegisterSecurityProvider function signatureRegistered after lsass.exe starts, the package works on its own but NegoEx fails: LocatePackageById returns NULL, because LSA maps package names to IDs only at startup. Load a kernel-mode security package without a reboot shows how to skip the reboot, and the crash this lookup failure can cause.
Debug output
Turn on verbose debug output:
ed nt!Kd_KSECDD_Mask 0xFFFFFFFF e ksecpkg!KsecInfoLevel 6
Sample output from a checked build:
0xe100b30.0xe302060> KSec: Calling TlsDecryptMessage() 0xe100b30.0xe302060> KSec: Calling SslDecryptPacket() 0xe100b30.0xe302060> KSec: SslDecryptPacket: returned 0x0 0xe100b30.0xe302060> KSec: TlsDecryptMessage returned 0x0 0xe100b30.0xe302060> KSec: Read Sequence [IN]: 2 0xe100b30.0xe302060> KSec: Header (plaintext): cbBuffer:0x5, pvBuffer:0x02a52d70 0xe100b30.0xe302060> KSec: Data (plaintext): cbBuffer:0x121, pvBuffer:0x02a52d75 0xe100b30.0xe302060> KSec: Trailer (plaintext): cbBuffer:0x1f, pvBuffer:0x02a52e96 (...) 0xcd1f740.0xe5117b0> KSec: NegoExtsQueryContextAttributes returned 0 0xcd1f740.0xe5117b0> KSec: NegoExtsGetContextToken called