sekurlsa
sekurlsa模块的主要命令和功能在kuhl_m_c_sekurlsa中定义
1 | const KUHL_M_C kuhl_m_c_sekurlsa[] = { |
Lists credentials
获取凭据的主要逻辑都在kuhl_m_sekurlsa_enum中的callback,函数原型如下
1 | NTSTATUS kuhl_m_sekurlsa_enum(PKUHL_M_SEKURLSA_ENUM callback, LPVOID pOptionalData) |
callback对应了各个小功能的逻辑,比如sekurlsa::msv的callback就是kuhl_m_sekurlsa_enum_callback_logondata
在kuhl_m_sekurlsa_enum中,首先会调用kuhl_m_sekurlsa_acquireLSA去打开lsass进程并初始化一些信息,先看看kuhl_m_sekurlsa_acquireLSA的内部。
打开lsass的DesiredAccess为
1 | DWORD processRights = PROCESS_VM_READ | ((MIMIKATZ_NT_MAJOR_VERSION < 6) ? PROCESS_QUERY_INFORMATION : PROCESS_QUERY_LIMITED_INFORMATION); |
之后还会检查lsass中某些模块是否加载
1 | BOOL CALLBACK kuhl_m_sekurlsa_findlibs(PKULL_M_PROCESS_VERY_BASIC_MODULE_INFORMATION pModuleInformation, PVOID pvArg) |
回到kuhl_m_sekurlsa_enum中,接下来会获取一些sessionData,然后调用callback,进入关键逻辑
1 | sessionData.LogonId = (PLUID) ((PBYTE) aBuffer.address + helper->offsetToLuid); |
总的来说,无论用哪种方式获取凭据,都需要先获取lsass的内存。
pth
pth即pass the hash,在mimikatz中使用的例子如下
1 | sekurlsa::pth /user:Administrateur /domain:chocolate.local /ntlm:cc36cf7a8514893efccd332446158b1a |
该功能主要逻辑在kuhl_m_sekurlsa_pth中,该函数原型如下
1 | NTSTATUS kuhl_m_sekurlsa_pth(int argc, wchar_t * argv[]) |
在该函数中,会用CreateProcessWithLogonW创建一个新的进程,调用如下
1 | CreateProcessWithLogonW(user, domain, password, iLogonFlags, NULL, dupCommandLine, iProcessFlags, NULL, NULL, &startupInfo, ptrProcessInfos) |
在sekurlsa::pth中lpPassword为空,dwLogonFlags为LOGON_NETCREDENTIALS_ONLY,msdn对该参数的描述如下
LOGON_NETCREDENTIALS_ONLY
0x00000002
Log on, but use the specified credentials on the network only. The new process uses the same token as the caller, but the system creates a new logon session within LSA, and the process uses the specified credentials as the default credentials.
This value can be used to create a process that uses a different set of credentials locally than it does remotely. This is useful in inter-domain scenarios where there is no trust relationship.The system does not validate the specified credentials. Therefore, the process can start, but it may not have access to network resources.
然后调用kuhl_m_sekurlsa_pth_luid进行pth的核心操作,在该函数内部,首先进一步获取对lsass的写权限。
1 | status = NtQueryObject(cLsass.hLsassMem->pHandleProcess->hProcess, ObjectBasicInformation, &bi, sizeof(OBJECT_BASIC_INFORMATION), &szNeeded); |
接下来进行凭据替换
1 | BOOL CALLBACK kuhl_m_sekurlsa_msv_enum_cred_callback_pth(IN PKUHL_M_SEKURLSA_CONTEXT cLsass, IN PKIWI_MSV1_0_PRIMARY_CREDENTIALS pCredentials, IN DWORD AuthenticationPackageId, IN PKULL_M_MEMORY_ADDRESS origBufferAddress, IN OPTIONAL LPVOID pOptionalData) |
其中的LsaProtectMemory和LsaUnprotectMemory的实际调用分别是BCryptEncrypt和BCryptDecrypt
总的来说,pth需要对lsass进行写操作来替换凭据。