Mimikatz Analysis

Hero

There are already many articles explaining how Mimikatz works, but I needed to examine the source code to better understand how it attacks the Windows system and steals credentials — specifically, how Mimikatz uses Windows APIs, NT APIs, and undocumented APIs.

Mimikatz Structure

At first, I downloaded mimikatz from the release.
After downloading it, I decompressed it:

7z e .\mimikatz_trunk.7z

And I checked the hash as always:

Get-FileHash -Path .\mimikatz.exe

Algorithm       Hash
---------       ----
SHA256          61C0810A23580CF492A6BA4F7654566108331E7A4134C968C2D6A05261B2D8A1

After decompression, the following files were extracted:

  • kiwi_passwords.yar: YARA rules for Mimikatz
  • mimicom.idl: Definitions of a COM interface
  • mimidrv.sys: Kernel driver
  • mimikatz.exe: Main executable
  • mimilib.dll: DLL which offers some features
  • mimilove.exe: Lightweight version of executable which works for Windows 2000 only
  • mimispool.dll: DLL related to Print Spooler
  • README.md: Description for the project

Mimikatz: Interpreting Commands

Banner

Once mimikatz.exe is executed, it interprets commands entered or passed as arguments through mimikatz_dispatchCommand.

mimikatz_dispatchCommand

In mimikatz_dispatchCommand, a different function is called depending on the command prefix (”!”, ”*”, or others).

Mimikatz: Kernel Operations with the ”!” Prefix

kuhl_m_kernel_do

If the command prefix is ​​”!”, kuhl_m_kernel_do is called to interpret the command following the ”!”. It then searches for the corresponding IOCTL code by comparing it to the third command name of each element in the KUHL_K_C kuhl_k_c_kernel[] list, which includes codes such as IOCTL_MIMIDRV_PING, IOCTL_MIMIDRV_BSOD, and others.

For example, we can input the following commands:

  • !+: Install and/or start mimikatz driver (mimidrv)
  • !-: Remove mimikatz driver (mimidrv)
  • !ping: Ping the driver
  • !bsod: Trigger a BSOD
  • !process: List processes
  • !processProtect: Protect process
  • !processToken: Duplicate process token
  • !processPrivilege: Set all privilege on process
  • !modules: List modules
  • !ssdt: List SSDT
  • !notifProcess: List process notify callbacks
  • !notifThread: List thread notify callbacks

… and others.

From here on, I will analyze the mimidrv.sys driver to gain a deeper understanding of how it operates in kernel mode.

Mimidrv: Dispatcher

I checked the DriverEntry function in the mimidrv.c and found the following line:

theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MimiDispatchDeviceControl;

The IOCTL code provided by the user appears to be handled by MimiDispatchDeviceControl. In this function, different operations are performed depending on the control code, as shown below:

MimiDispatchDeviceControl

!ping

This command sends the IOCTL_MIMIDRV_PING code to mimidrv.sys for printing the string “pong”.

status = kprintf(&kOutputBuffer, L"Input  : %s\nOutput : %s\n", bufferIn, L"pong");

!bsod

This command sends the IOCTL_MIMIDRV_BSOD code to mimidrv.sys for triggering a system crash (blue screen) and generating a crash dump.

KeBugCheck(MANUALLY_INITIATED_CRASH);

When this command is actually executed, a blue screen appears as shown below:

BSOD

!process

kkll-m-process-enum

This command sends the IOCTL_MIMIDRV_PROCESS_LIST code to mimidrv.sys, and the following processing is carried out in kkll_m_process_enum:

  1. References the global variable PsInitialSystemProcess to retrieve a pointer to the EPROCESS structure.
  2. Obtains a pointer to each process.
  3. In kkll_m_process_list_callback, retrieves the PID and process name using PsGetProcessId and PsGetProcessImageFileName with the process pointer.
  4. Displays the retrieved information.

!processToken

kkll-m-process-token

This command sends the IOCTL_MIMIDRV_PROCESS_TOKEN code to mimidrv.sys, and the following processing is carried out in kkll_m_process_token:

  1. Retrieves a pointer to the specified processusing PsLookupProcessByProcessId.
  2. Obtains a handle to the access token of the source process via ZwOpenProcessTokenEx.
  3. Creates a handle for a new access token by duplicating the source token using ZwDuplicateToken with the TokenPrimary type.
  4. Assigns the duplicated token to the destination process using ZwSetInformationProcess with the ProcessAccessToken information class.

!processProtect

kkll-m-process-protect

This command sends the IOCTL_MIMIDRV_PROCESS_PROTECT code to mimidrv.sys, and the following processing is carried out in kkll_m_process_protect:

  1. Retrieves a pointer to the specified process using PsLookupProcessByProcessId.
  2. If the Windows version is older than 8, modifies the ProtectedProcess bit in the Flags2 field of the EPROCESS structure using PROTECTED_PROCESS_MASK (0x00000800).
  3. If the Windows version is 8 or later, modifies the SignatureLevel, SectionSignatureLevel, and optionally Protection fields in the SignatureProtection structure inside the EPROCES structure.

!processPrivilege

kkll-m-processs-fullpriv

This command sends the IOCTL_MIMIDRV_PROCESS_FULLPRIV code to mimidrv.sys, and the following processing is performed in kkll_m_process_fullprivileges:

  1. Retrieves a pointer to the specified process using PsLookupProcessByProcessId or PsGetCurrentProcess.
  2. Obtains the primary token of the process via PsReferencePrimaryToken.
  3. Uses an offset within the token structure to locate the privilege pointer and forcibly enables all privileges.

!modules

This command sends to the IOCTL_MIMIDRV_MODULE_LIST code to mimidrv.sys for retrieving module information using AuxKlibQueryModuleInformation, then outputting the data to standard output via the callback function kkll_m_modules_list_callback.

!ssdt

This command sends to the IOCTL_MIMIDRV_SSDT_LIST code to mimidrv.sys and the following processing is performed in kkll_m_ssdt_list:

  1. Retrieves a pointer to the KeServiceDescriptorTable structure.
  2. Iterates through the table to obtain and print the address of each function.

Mimikatz: RPC Operation with the ”*” Prefix

Mimikatz can execute commands on a remote host within the local network via RPC using commands prefixed with ”*”.
To use this feature, it must first connect to an RPC endpoint with a command such as the following:

rpc::connect /remote:192.168.0.100 /noauth

After the above command, when a user executes a command with the prefix ”*”, Mimikatz calls kuhl_m_rpc_do which encrypts the command and invokes NdrClientCall2 to perform the remote call.

Prefixing a command with ”*” causes it to be executed on a remote host.

Mimikatz: Local Operations

A command without a prefix is executed on the local host. When the user inputs such a command, it calls mimikatz_doLocal, which finds the matching command from the list of available modules stored in mimikatz_modules, as shown below.

mimikatz_modules

Here, I will analyze only the commands that are likely to be used frequently.

standard::exit

Simply prints “Bye” and exits as the code below:

kprintf(L"Bye!\n");
return argc ? STATUS_THREAD_IS_TERMINATING : STATUS_PROCESS_IS_TERMINATING;

standard::cls

FillConsoleOutputCaracter is called to fill and clear the entire terminal screen with spaces.

GetConsoleScreenBufferInfo(hStdOut, &csbi);
FillConsoleOutputCharacter(hStdOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
SetConsoleCursorPosition(hStdOut, coord);

standard::sleep

Sleep function is simply called.

DWORD dwMilliseconds = argc ? wcstoul(argv[0], NULL, 0) : 1000;
kprintf(L"Sleep : %u ms... ", dwMilliseconds);
Sleep(dwMilliseconds);

standard::version

kuhl-m-standard-version

The version of mimikatz is displayed.

standard::cd

SetCurrentDirectory is called to switch the current directory to the specified location.

standard::localtime

It retrieves the system local time by calling GetSystemTimeAsFileTime and timezone information by calling GetTimeZoneInformation, then outputs this information.

standard::hostname

It retrieves the system hostname by calling GetComputerNameEx.

crypto::providers

kuhl-m-crypt-l-providers

  1. Enumerates cryptographic service providers (CSPs) by calling CryptEnumProviders.
  2. Obtains a pointer to the CSP using CryptAcquireContext.
  3. Retrieves details of each provider by calling CryptGetProvParam with the PP_IMPTYPE parameter.
  4. Displays the result.

crypto::stores

  1. Retrieves available System Stores by calling CertEnumSystemStore with the CERT_SYSTEM_STORE_CURRENT_USER flag.
  2. Outputs the store names.

crypto::certificates

kuhl-m-crypto-l-certificates-1

  1. Opens a handle to the specified certificate store by calling CertOpenStore.
  2. Retrieves a pointer to a CERT_CONTEXT structure in the store using CertEnumCertificatesInStore.
  3. Obtains the subject or issuer names from the context by calling CertGetNameString.
  4. Retrieves additional information from the context via CertGetCertificateContextProperty.
  5. Retrieves the provider type name as a string by referencing kull_m_crypto_provider_type_to_name.

kuhl-m-crypto-l-certificates-2

  1. Obtains the private key for the certificate by calling CryptAcquireCertificatePrivateKey.
  2. Retrieves a handle to the user’s public/private key pair using CryptGetUserKey.
  3. Gets property of the key object by calling NCryptGetProperty.
  4. Finally, displays this information.

crypto::keys

kuhl-m-crypto-l-keys-capi

  1. Lists CryptAPI keys for the specified provider by calling CryptGetProvParam and CryptAcquireContext.
  2. Retrieves properties of the keys using NCryptGetProperty and displays the information.

kuhl-m-crypto-l-keys-cng

  1. Initializes a CNG key storage provider by calling NCryptOpenStorageProvider.
  2. Lists CNG key names by calling NCryptEnumKeys.
  3. Obtains handles for each key by calling NCryptOpenKey with the key names.
  4. Retrieves properties for each key by calling NCryptGetProperty.

crypto::sc

This command displays key information for smart cards.

kuhl-m-crypto-l-sc-1

  1. Establishes a resource manager context by calling SCardEstablishContext.
  2. Lists smart card reader names using SCardListReaders.
  3. Establishes a connection to the smart card readers via SCardConnect.

kuhl-m-crypto-l-sc-2

  1. Retrieves attributes for each reader by calling SCardGetAttrib.
  2. Obtains provider names for the smart card using SCardGetCardTypeProviderName.
  3. Retrieves information about CryptAPI keys by calling CryptgetProvParam and CryptAcquireContext, then displays it.
  4. Retrieves information about CNG keys by calling NCryptEnumkeys and NCryptGetProperty, then displays it.

crypto::hash

huhl-m-crypto-l-hash-1

  1. Calculates the NTLM hash for the specified password by calling RtlCalculateNtOwfPassword (SystemFunction007).
  2. Calculates the DCC1 and DCC2 hashes for the specified username by using RtlCalculateNtOwfPassword, CryptCreateHash, CryptSetHashParam, and CryptGetHashParam, based on the previously calculated NTLM hash.

kuhl-m-crypto-l-hash-2

  1. Calculates the LM hash for the password by calling RtlCalculateLmOwfPassword (SystemFunction006).
  2. Calculates the MD5, SHA1, SHA256 hashes for the password by calling CryptCreateHash, CryptSetHashParam, and CryptGetHashParam.

crypto::system

This command extracts certificate information from a specified certificate file.

kuhl-m-crypto-system-1

  1. If the specified file path is a directory, enumerates files in that directory.

kuhl-m-crypto-system-2

  1. Extracts certificate information from the certificate file at the specified offset.

sekurlsa::msv

This command lists LM and NTLM credentials for logon sessions.

kuhl-m-sekurlsa-msv

  1. Calls kuhl_m_sekurlsa_acquireLSA to initialize access to the LSASS process and locate necessary memory structures for credential extraction.
  2. Retrieves information such as Logon ID, Session, Username, Credentials, etc., from the logon session list and displays it.

kuhl-m-sekurlsa-msv-enum-cred

  1. Obtains credentials by parsing internal structures of the msv1_0 authentication package, located within the lsasrv.dll module loaded in the LSASS process.
  2. Formats and prints the extracted credentials to the console.

sekurlsa::wdigest

This command lists WDigest credentials.

kuhl-m-sekurlsa-wdigest

  1. Calls kuhl_m_sekurlsa_acquireLSA to initialize access to the LSASS process and locate necessary memory structures for credential extraction.
  2. Retrieves and displayes information such as Logon ID, Session, Username, Credentials, etc., from the logon session list.

kuhl-m-sekurlsa-enum-logon-callback-wdigest

  1. If wdigest.dll is found in the LSASS memory, locates the WDIGEST_LIST_ENTRY structure and extracts plaintext credentials (if present) by reading memory from that structure.
  2. Formats and prints the extracted credentials to the console.

sekurlsa::kerberos

This command lists Kerberos credentials.

kuhl-m-sekurlsa-kerberos

  1. Calls kuhl_m_sekurlsa_acquireLSA to initialize access to the LSASS process and locate necessary memory structures for credential extraction.
  2. Retrieves and displays information such as Logon ID, Session, Username, Credentials, etc., from the logon session list.

kuhl-m-sekurlsa-enum-generic-callback-kerberos

kuhl-m-sekurlsa-enum-kerberos-callback-passwords

  1. If kerberos.dll is found in LSASS memory, locates the internal Kerberos logon session list and extracts credentials, including usernames, domains, and passwords.
  2. Formats and prints the extracted credentials to the console.

sekurlsa::tspkg

This command lists TsPkg (Terminal Server) credentials.

kuhl-m-seckurlsa-tspkg

  1. Calls kuhl_m_sekurlsa_acquireLSA to initialize access to the LSASS process and locate necessary memory structures for credential extraction.
  2. Retrieves and displays information such as Logon ID, Session, Username, Credentials, etc., from the logon session list.

kuhl-m-sekurlsa-enum-logon-callback-tspkg

  1. If tspkg.dll is found in LSASS memory, locates the TsPkg credentials structures (e.g. KIWI_TS_CREDENTIAL) using memory offsets and extracts plaintext credentials.
  2. Formats and prints the extracted credentials to the console.

sekurlsa::livessp

This command lists LiveSSP credentials.

kuhl-m-sekurlsa-livessp

  1. Calls kuhl_m_sekurlsa_acquireLSA to initialize access to the LSASS process and locate necessary memory structures for credential extraction.
  2. Retrieves and displays information such as Logon ID, Session, Username, Credentials, etc., from the logon session list.

kuhl-m-sekurlsa-enum-logon-callback-livessp

  1. If livessp.dll is found in LSASS memory, locates the KIWI_LIVESSP_LIST_ENTRY structure using version-specific offsets and extracts credentials such as logon ID, username, domain, and password.
  2. Formats and prints the extracted credentials to the console.

sekurlsa::cloudap

This command lists CloudAp credentials.

kuhl-m-sekurlsa-cloudap

  1. Calls kuhl_m_sekurlsa_acquireLSA to initialize access to the LSASS process and locate necessary memory structures for credential extraction.
  2. Retrieves and displays information such as Logon ID, Session, Username, Credentials, etc., from the logon session list.

kuhl-m-sekurlsa-enum-logon-callback-cloudap

  1. If cloudap.dll is found in the LSASS memory, locates the internal CloudApGlobalLogonSessionList and extracts credentials from each KIWI_CLOUDAP_CREDENTIAL_ENTRY, including usernames, domains, and passwords, etc.
  2. Formats and prints the extracted credentials to the console.

sekurlsa::ssp

kuhl-m-sekurlsa-ssp

  1. Calls kuhl_m_sekurlsa_acquireLSA to initialize access to the LSASS process and locate necessary memory structures for credential extraction.
  2. Retrieves and displays information such as Logon ID, Session, Username, Credentials, etc., from the logon session list.

kuhl-m-sekurlsa-enum-logon-callback-ssp

  1. If the ssp module is available (handled via msv1_0.dll in LSASS memory), locates the KIWI_SSP_CREDENTIAL_LIST_ENTRY structure and extracts credentials including usernames, domains, passwords, and logon IDs.
  2. Formats and prints the extracted credentials to the console.

sekurlsa::logonPasswords

This command lists all providers available credentials.

lsasspackages

kuhl-m-sekurlsa-all

  1. Calls kuhl_m_sekurlsa_acquireLSA to initialize access to the LSASS process and locate necessary memory structures for credential extraction.
  2. Retrieves and displays information such as Logon ID, Session, Username, Credentials, etc., from the logon session list.

kuhl-m-sekurlsa-enum-callback-logondata

  1. Enumerates provider packages (msv, wdigest, kerberos, tspkg, livessp, cloudap, ssp) and invokes the corresponding callback functions for each session.

sekurlsa::process

This command switches to the LSASS process context.

kuhl-m-sekurlsa-process

kuhl-m-sekurlsa-reset

kull-m-memory-close

  1. Closes the handle to the currently attached LSASS memory by calling kull_m_memory_close.

kuhl-m-sekurlsa-clean

  1. Frees each KEYLIST_ENTRY structure in the gCandidateKeys list to clean up candidate credential keys.

sekurlsa::minidump

This command switches to LSASS minidump context.

kuhl-m-sekurlsa-minidump

  1. Same as above the sekurlsa::process command, clear the current LSASS memory.
  2. Reteives a pointer to the specified minidump file.

sekurlsa::pth

This command performs Pass-The-Hash.

kuhl-m-sekurlsa-pth-1

  1. Parses the specified keys (either ntlm, aes128 or aes256) for later use.

kuhl-m-sekurlsa-pth-luid

  1. If the user specified the luid option, calls kuhl_m_sekurlsa_pth_luid to enable Pass-the-Hash operations for the specified logon session (LUID) by obtaining writable access to LSASS and injecting credentials.

kuhl-m-sekurlsa-pth-2

  1. If the user specified the user option, creates a SUSPENDED process by calling CreateProcessWithLogon with the specified parameters including user, domain and empty password. -> It generates a new logon session (LUID) but without valid credentials. And the following processing is executed:

  2. Obtains a handle to the process token by calling OpenProcessToken.

  3. Retrieves the Logon Session ID (LUID) from the token using GetTokenInformation.

  4. Reads LSASS process memory to locate the logon session matching the LUID.

  5. Finds the MSV1_0 credentials structure for the session and replace the NTLM hash with the one provided in the command.

  6. Resumes the suspended process.

sekurlsa::krbtgt

This command retrieves credentials from krbtgt account.

kuhl-m-sekurlsa-krbtgt

  1. Checks if the kdcsvc.dll module exists in the LSASS process.
  2. Locates the pointer to the internal DUAL_KRBTGT structure (which holds Kerberos keys) depending on the system version.

kuhl-m-sekurlsa-krbtgt-keys

  1. Extracts the Kerberos encryption keys from the DUAL_KRBTGT structure. The structure layout and key count depend on the Windows version.

sekurlsa::dpapisystem

This command retrieves DPAPI_SYSTEM secrets.

kuhl-m-sekurlsa-dpapi-system

  1. Checks if the dpapisrv.dll module exists in the LSASS process.
  2. Locates the memory containing credentials data in the LSASS process, depending on the system version.
  3. Extracts DPAPI secrets, including the machine key and user key used for decryption.

sekurlsa::backupkeys

This command retrieves the preferred Backup Master Keys used to decrypt DPAPI-encrypted data.

kuhl-m-sekurlsa-bkeys

  1. Checks if the dpapisrv.dll module exists in the LSASS process.

kuhl-m-sekurlsa-bkey

  1. Locates the pointer to the internal KIWI_BACKUP_KEY structure containing the backup RSA private keys, depending on the system version.

kuhl-m-lsadump-analyzekey

  1. Extracts the RSA private key by calling the following APIs:

    • For RSA keys (CNG): NCryptOpenKey, NCryptGetProperty, NCryptExportKey
    • For legacy keys (CryptAPI): CryptGetProvParam, CryptExportParam

sekurlsa::tickets

This command lists Kerberos tickets.

kuhl-m-sekurlsa-kerberos-tickets

  1. Enumerates all logon sessions by calling kuhl_m_sekurlsa_enum.

kurl-m-sekurlsa-enum-1

  1. Locates the KIWI_BASIC_SECURITY_LOGON_SESSION_DATA structure in the LSASS process.

kurl-m-sekurlsa-enum-2

  1. Extracts credentials from the session data, including logon ID, session, username, domain, and others.

kuhl-m-sekurlsa-enum-generic-callback-kerberos

  1. Depending on the Windows version, locates the Kerberos ticket entries in memory either via a linked list or an AVL tree.

kuhl-m-sekurlsa-enum-kereros-callback-tickets

  1. Extracts Kerberos tickets (such as TGT and TGS) from LSASS memory and displays or exports them for reuse in Pass-the-Tickets attacks.

sekurlsa::ekeys

This command lists Kerberos Encryption Keys.

Its process is almost the same as sekurlsa::tickets, except the last callback function is kuhl_m_sekurlsa_enum_kerberos_callback_keys.

kuhl-m-sekurlsa-enum-kerberos-callback-keys

  1. Enumerates all logon sessions and locates the KIWI_BASIC_SECURITY_LOGON_SESSION_DATA structure in LSASS memory.
  2. For each session, extracts Kerberos encryption keys (such as session keys, TGT keys, and service ticket keys) by reading internal structures at known offsets depending on the OS version.
  3. Displays the keys in a readable format (e.g., in hex), which can be reused in Kerberos-related attacks or analysis.

sekurlsa::dpapi

This command lists Cached MasterKeys.

kuhl-m-sekurlsa-dpapi

  1. Enumerates all logon sessions by calling kuhl_m_sekurlsa_enum.
  2. For each session, calls the callback function kuhl_m_sekurlsa_enum_callback_dpapi.

kuhl-m-sekurlsa-enum-callback-dpapi

  1. Prints basic logon data including logon ID, username, SID, etc.
  2. Locates the internal KIWI_MASTERKEY_CACHE_ENTRY structure in the logon session.
  3. Enumerates the Cached MasterKeys list and extracts each key’s:
  • GUID
  • Timestamp
  • SHA1 hash of the master key
  1. Prints the extracted key hashes and metadata to the console.

sekurlsa::credman

This command lists Credentials Manager.

kuhl-m-sekurlsa-credman

  1. Calls kuhl_m_sekurlsa_acquireLSA to initialize access to the LSASS process and locate necessary memory structures for credential extraction.
  2. Acquires each part of information (Logon Id, Session, Username, Credentials, etc.) from the logon session list and displays that information.

kuhl-m-sekurlsa-enum-logon-callback-credman

  1. If the lsasrv.dll module exists in the LSASS memory, locates the internal KIWI_CREDMAN_SET_LIST_ENTRY structure.
  2. Extracts credentials such as username, domain, and password by reading memory at calculated offsets within the structure, depending on Windows version.

kerberos::ptt

This command performs Pass-The-Ticket.

kuhl-m-kerberos-ptt

  1. If the user specifies the directory path as command line arguments, find a Kerberos ticket file (.kirbi) from that directory.

kuhl-m-kerberos-ptt-directory-file

kuhl-m-kerberos-ptt-data

  1. For each Kerberos ticket file, reads the data and injects it into the current logon session by calling LsaCallAuthenticationPackage with the Kerberos authentication package.

kerberos::list

This command lists Kerberos tickets.

  1. Requests Kerberos ticket cache using LsaCallAuthenticationPackage function.
  2. If the request is successful, display the information of the retrieved cached ticket.

kerberos::ask

This command asks or get TGT tickets.

kuhl-m-kerberos-ask-1

  1. Checks if the user specifies the target option for the remote host.
  2. Prepares the request data with the KERB_RETRIEVE_TKT_REQUEST structure.

kuhl-m-kerberos-ask-2

  1. Retrieves encoded Kerberos ticket by calling LsaCallAuthenticationPackage with the request data.
  2. Extracts the response data including the following items:
  • Service
  • Domain
  • Target domain
  • Key
  • Key type
  • Ticket
  • Ticket flags

kuhl-m-kerberos-ask-3

  1. If the user specifies the tkt flag, write the encoded ticket to a file with the .tkt extension.
  2. If the user specifies the export flag, retrieves encoded Kerberos Credentials by calling LsaCallAuthenticationPackage again with the KERB_RETRIEVE_TICKET_AS_KERB_CRED option at this time. Then, write the encoded ticket to a file with the .kirbi extension.

kerberos::tgt

This command retrieves current TGT.

kuhl-m-kerberos-tgt

  1. Retrieves current Kerberos ticket by calling LsaCallAuthenticationPackage.
  2. Extracts the response data including the following items:
  • Service
  • Domain
  • Target domain
  • Key
  • Key type
  • Ticket
  • Ticket flags

kerberos::purge

This command purges Kerberos tickets.

kuhl-m-kerberos-purge

It requests to purge tickets by calling LsaCallAuthenticationPackage with the KERB_PURGE_TKT_CACHE_REQUEST.

kerberos::golden

This command forges a Golden Ticket, a fake Ticket Granting Ticket (TGT), using the KRBTGT account hash. It allows persistent domain access as any user.

kuhl-m-kerberos-golden-1

  1. Checks if the user specifies the admin option or the user option, and also checks if the domain option is specified.
  2. Sets the key type depending on the specified key option such as des, rc4, aes128, aes256.

kuhl-m-kerberos-golden-2

  1. Gets the pointer to the KERB_ECRYPT structure by calling CDLocateCSystem.
  2. Sets the lifetime for the fake TGT from the local system time by calling GetSystemTimeAsAsFileTime.
  3. Prepares the information (SID, User Id, Groups Id, etc.) which is used for the fake TGT.

kuhl-m-kerberos-golden-data-1

kuhl-m-kerberos-golden-data-2

kuhl-m-kerberos-golden-data-3

  1. Issues the fake TGT by calling kuhl_m_kerberos_golden_data which processes as below:

    1. Prepares the ticket data with the KIWI_KERBEROS_TICKET structure.
    2. Converts the ticket data -> KERB_VALIDATION_INFO -> PACTYPE.
    3. Signs the PAC data by calling kuhl_m_pac_signature.
    4. Generates the EncTicketPart by calling kuhl_m_kerberos_ticket_createAppEncTicketPart.
    5. Encrypts the EncTicketPart by calling kuhl_m_kerberos_encrypt which uses the CSystem’s Encrypt function.
    6. Generates a KrbCred by calling kuhl_m_kerberos_ticket_createAppKrbCred.
  2. After generating the fake TGT, if the user specifies the ptt option, the specified ticket is injected into the current logon session by calling LsaCallAuthenticationPackage to make it active and usable by the system, otherwise the ticket is saved to a file.

kerberos::hash

This command generates a password hash to keys.

kuhl-m-kerberos-hash-data-raw

  1. Gets the pointer to the KERB_ECRYPT structure by calling CDLocateCSystem.
  2. Calculates the NT hash by calling HashPassword_NT5 or HashPassword_NT6 depending on the system version.
  3. Prints the NT hash to the console.

kerberos::decrypt

This command decrypts encoded tickets.

kuhl-m-kerberos-decode

  1. Sets the key type and the key length depending on the specified options including rc4, aes128, aes256, and des.

kuhl-m-kerberos-encrypt

  1. Gets the pointer to the KERB_ECRYPT structure by calling CDLocateCSystem.
  2. Decrypt the specified key by calling pCSystem->Decrypt.

privilege::debug

This command asks debug privilege.

Calls RtlAdjustPrivilege with the SE_DEBUG flag.

privilege::driver

This commands asks load driver privilege.

Calls RtlAdjustPrivilege with the SE_LOAD_DRIVER flag.

privilege::security

This command asks security privilege.

Calls RtlAdjustPrivilege with the SE_SECURITY flag.

privilege::tcb

This command asks tcp privilege.

Calls RtlAdjustPrivilege with the SE_TCB flag.

privilege::backup

This command asks backup privilege.

Calls RslAdjustPrivilege with the SE_BACKUP flag.

privilege::restore

This command asks restore privilege.

Calls RtlAdjustPrivilege with the SE_RESTORE flag.

privilege::sysenv

This command asks system environment privilege.

Calls RtlAdjustPrivilege with the SE_SYSTEM_ENVIRONMENT

privilege::id

This command asks privilege by its ID.

It is the same as the above commands except that it takes the privilege flag ID as a command argument.
For example, run privilege::id 20 for asking debug privilege.

privilege::name

This command asks privilege by its name.

It is the same as the above commands except that it takes the privilege name as a command argument.
Looks up the privilege ID from the specified privilege name by calling LookupPrivilegeValue.

For example, run privilege::name SeDebugPrivilege for asking debug privilege.

process::list

This command lists processes.

kuhl-m-process-getprocessinformation

  1. Gets the current process information by calling NtQuerySystemInformation.

kuhl-m-process-list-callback-process

  1. For each process, display its PID and name with the pSystemProcessInformation->UniqueProcessId and the pSystemProcessInformation->ImageName.
  2. In addition, enumerate threads for each process and display the thread ID with the pSystemProcessInformation->Threads[i].ClientId.UniqueThread.

process::exports

This command lists exports.

kuhl-m-process-callbackprocess

  1. If the user specifies the pid option, get the handle to the process from the specified PID by calling OpenProcess.

kull-m-process-getverybasicmoduleinformations

  1. Gets the pointer to the PEB structure for the process and get the Dll base address and the size.

kull-m-process-getexportedentryinformations

  1. For each module, parses the IMAGE_EXPORT_DIRECTORY structure to enumerate exported symbols.
  2. Extracts each function’s name, ordinal, and Relative Virtual Address (RVA). This allows users to resolve actual API addresses or detect function forwarding.

process::imports

This command lists imports.

kuhl-m-process-imports-callback-module-importedentry

It is almost the same as process::exports, but it enumerates imported functions.

process::start

This command starts a process.

Creates a new process by calling CreateProcess with the specified command line.

status = CreateProcess(NULL, dupCommandLine, NULL, NULL, FALSE, iProcessFlags, NULL, NULL, &startupInfo, ptrProcessInfos);

process::stop

This command terminates a process.

  1. Opens the process for the specified PID by calling OpenProcess.
  2. Terminates the process by calling NtTerminateProcess.
hProcess = OpenProcess(access, FALSE, pid)
status = NtTerminateProcess(hProcess, STATUS_SUCCESS);

process::suspend

This command suspends a process.

It uses NtSuspendProcess internally.

  1. Opens the process for the specified PID by calling OpenProcess.
  2. Suspends the process by calling NtSuspendProcess.
hProcess = OpenProcess(access, FALSE, pid)
status = NtSuspendProcess(hProcess);

process::resume

This command resumes a process.

  1. Opens the process for the specified PID by calling OpenProcess.
  2. Resumes the process by calling NtResumeProcess.
hProcess = OpenProcess(access, FALSE, pid)
status = NtResumeProcess(hProcess);

process::run

This command starts a process with current token.

kull-m-process-run-data

  1. Creates a pipe by calling CreatePipe and gets handles to the read and write.
  2. Sets the HANDLE_FLAG_INHERIT flag to the read handle by calling SetHandleInformation.
  3. Gets the pointer to the environment block by calling CreateEnvironmentBlock. As a result, the current process’ environment is herited.
  4. Creates a new process in the context of the current token by calling CreateProcessAsUser with the specified command line.

process::runp

This command starts a process with a token of a parent process.

kuhl-m-process-runparent

  1. Checks if the user specifies the ppid or pid option. If neither is specified, the LSASS is used as parent process by default.
  2. Dynamic API resolution for InitializeProcThreadAttributeList, UpdateProcThreadAttribute, DeleteProcThreadAttributeList by calling *GetProcAddress with the kernel32.dll module.
  3. Get the handle to the parent process by calling OpenProcess with the *PROCESS_CREATE_PROCESS for letting a new process to be created in the process.
  4. Locates the current process’s attribute list for the newly created process.
  5. Initializes the attribute list by calling InitializeProcThreadAttributeList.
  6. Updates the attribute list for inheriting the parent process by calling UpdateProcThreadAttribute with the PROC_THREAD_ATTRIBUTE_PARENT_PROCESS parameter.
  7. Creates a new process by calling CreateProcess with the specified command line and the attribute list.
  8. Displays the token information for the process.

service::start

This command starts a service.

kull-m-service-start

  1. Gets the handle to the service control manager by calling OpenSCManager.
  2. Gets the handle to the specified service by calling OpenService.
  3. Starts the service by calling StartService.

service::remove

This command removes a service.

Its operation is almost the same as the service::start but it calls DeleteService instead of StartService.

service::stop

This command stops a service.

Its operation is almost the same as service::start but it calls ControlService with the SERVICE_CONTROL_STOP control code instead of StartServer.

service::suspend

This command suspends a service.

Its operation is almost the same as service::stop but it specifies the SERVICE_CONTROL_PAUSE control code.

service::resume

This command resumes a service.

Its operation is almost the same as service::stop but it specifies the SERVICE_CONTROL_CONTINUE control code.

service::preshutdown

This command preshutdowns a service.

Its operation is almost the same as service::stop but it specifies the SERVICE_CONTROL_PRESHUTDOWN control code.

service::shutdown

This command shutdowns a service.

Its operation is almost the same as service::shutdown but it specifies the SERVICE_CONTROL_SHUTDOWN control code.

service::list

This command lists services.

However, as far as I can see, the corresponding function just returns STATUS_SUCCESS…

lsadump::sam

This command gets the SysKey to decrypt SAM entries.

kuhl-m-lsadump-sam

  1. If the user specifies the system option, opens the SYSTEM hive file by calling CreateFile.

kull-m-registry-open

  1. Maps the file into memory by calling CreateFileMapping and MapViewOfFile.

kuhl-m-lsadump-getcomputerandsyskey

  1. Gets the computer name by retrieving the data from HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName.
  2. Gets the SysKey by retrieving the data from HKLM\SYSTEM\CurrentControlSet\Control\LSA with concatenating the SysKey names including JD, Skew1, GBG, Data.

kuhl-m-lsadump-sam-2

  1. If the user specifies the sam option, opens the SAM hive file by calling CreateFile.
  2. Maps the file into memory by calling CreateFileMapping and MapViewOfFile.

kuhl-m-lsadump-getusersandsamkey

  1. Gets the local SID from HKLM\SAM\SAM\Domains\Account\V and prints it to the console.

kuhl-m-lsadump-getusersandsamkey-2

  1. Retrieves the SAM key from HKLM\SAM\SAM\Domains\Account\F and decrypts it with MD5 by calling RtlDecryptData2.
  2. Enumerates the users under HKLM\SAM\SAM\Domains\Account\Users and gets the handle to the registry for each user.
  3. Gets hashes (LM, NTLM, LM History, HTLM History) from HKLM\SAM\SAM\Domains\Account\Users\[user]\V.
  4. Decrypts each hash depending on the key type (CryptAPI or CNG).

lsadump::secrets

This command gets the SysKey to decrypt SECRETS entries.

  1. The steps up to getting the SysKey are the same as the lsadump::sam above.

kuhl-m-lsadump-getlsakeyandsecrets-1

  1. Gets the handle to the registry for HKLM\SECURITY\Policy.

kuhl-m-lsadump-getlsakeyandsecrets-2

  1. Gets the data for HKLM\SECURITY\Policy\PolRevision.
  2. If the pPolRevision->Minor is greater than 9, gets the data from HKLM\SECURITY\Policy\PolEKList, and decrypts PolEKList or PolSecretEncryptionKey using the SysKey to obtain the LSA encryption key, which is then used to decrypt the actual Secrets (CurrVal).

kuhl-m-lsadump-getlsakeyandsecrets

  1. If the pPolRevision->Minor is 9 or less, gets the data from HKLM\SECURITY\Policy\PolSecretEncryptionKey and decrypts the keys with the SysKey using MD5.

kuhl-m-lsadump-getsecrets

  1. Open the handle to the registry for HKLM\SECURITY\Policy\Secrets.
  2. Enumerates the subkeys from the registry.
  3. For each subkey, gets the data for HKLM\SECURITY\Policy\Secrets\[secret]\CurrVal and decrypts it.

lsadump::cache

This command gets the SysKey to decrypt NL$KM then MSCache(v2).

kuhl-m-lsadump-secretsorcache-1

  1. If the user specifies the user option, enters the cache replace mode.

    1. If the user specifies the dcc, the hash is stored to cacheData.dcc.
    2. If the user specifies the ntlm, the hash is stored to cacheData.ntlm.
    3. If the user specifies neither, the password is retrieved as a command line argument and calculates NTLM hash, then stores it to cacheData.ntlm.

kuhl-m-lsadump-secretsorcache-2

  1. If the user specifies the subject option, opens the cert store named “My” and finds the subject from the store.
  2. Gets the corresponding private key from the certificate by calling CryptAcquireCertificatePrivateKey and stores phCryptProvOrNCryptKey to cacheData.hProv, and also stores pdwKeySpec to cacheData.keySpec.

lsadump::lsa

This command asks LSA Server to retrieve SAM/AD entries.

kuhl-m-lsadump-lsa-1

  1. If the user specifies the patch option…

    1. Gets the pointer to the service status information for the “SamSs” service.
    2. Gets the handle to the process for the PID stored in the status information.
    3. Gets the information of the samsrv.dll in the process.
    4. Patches the module to apply PAGE_READWRITE or PAGE_EXECUTE_READWRITE protection.

kuhl-m-lsadump-lsa-2

  1. Otherwise, if the user specifies the inject option…

    1. Gets the pointer to the service status information for the “SamSs” service.
    2. Gets the handle to the process for the PID stored in the status information.
    3. Copies the address of kuhl_sekurlsa_samsrv_thread to the remote function.

kuhl-m-lsadump-lsa-3

  1. Gets the handle to the Policy object and the policy account domain information by calling LsaQueryInformationPolicy.
  2. Gets the handle to the SAM object by calling SamConnect.
  3. Gets the handle to the policy account domain by calling SamOpenDomain with the domain SID for the policy account domain information.

kuhl-m-lsadump-lsa-4

  1. If the user specifies the id option, looks up the specified ID by calling SamLookupIdsInDomain and gets the user credentials (LM and NTLM hashes) from SamQueryInformationUser.
  2. If the user specifies the name option, looks up the name by calling SamLookupNamesInDomain and gets the user credentials (same as above) from SamQueryInformationUser.
  3. If the user specifies neither, enumerates users by calling SamEnumerateUsersInDomain and gets credentials for each user.

lsadump::trust

This command asks LSA Server to retrieve Truth Auth Information.

kuhl-m-lsadump-trust-1

  1. If the user specifies the patch option, applies to in-memory patch to lsasrv.dll or lsadb.dll to enable dumping trust information.

kuhl-m-lsadump-trust-2

  1. Otherwise, enumerates domains trusted to authenticate logon credentials by calling LsaEnumerateTrustedDomains.
  2. For each domain, calls LsaQueryTrustedDomainInfoByName to retrieve the information and NT hashes the passwords and display them.

lsadump::backupkeys

This command dumps backup keys.

kuhl-m-lsadump-bkey

  1. If the user specifies the guid option, retrieves the backup key name from the GUID. The key name is prefixed with “G$BCKUPKEY_” and is used for finding the secret in the following process:

    1. If the user specifies the secret option, calls LsaQuerySecret to dump the LSA secret.
    2. Otherwise, the LSA secret is dumped by calling LsaRetrievePrivateData.
  2. After dumping, it is decrypted and exported to a file with .pfx or .key extension.

lsadump::rpdata

This command dumps a LSA secret from a specified key name.

kuhl-m-lsadump-rpdata

Calls LsaRetrievePrivateData to dump the LSA secrets from the specified key name, and display them.

lsadump::dcsync

This command asks a DC to synchronize an object and dumps credentials.

kull-m-net-getdc

  1. Gets the pointer to the DOMAIN_CONTROLLER_INFO structure for the specified domain.
  2. Gets the name of the domain controller from DomainControllerName in the structure.

kull-m-lda-getldapandrootdn

  1. Initializes the session with the LDAP server running on the domain controller by calling ldap_init.

  2. Searches the LDAP directory by calling ldap_search_s with filtering by “(dn=RootDSE)”.

  3. If the user specifies the laps option…

    1. Gets the RootDN by calling ldap_get_values_len from the search result.
    2. Searches the LDAP directory by calling ldap_search_s with filtering by ”(&(objectclass=attributeSchema)(attributeID=” TEXT(szOID_ANSI_msMcsAdmPwd) L”))”.
    3. Gets the distinguished name and the identifier.

kull-m-rpc-createbinding

  1. Builds a RPC binding by calling RpcBindingFromStringBinding, RpcBindingSetAuthInfoEx, RpcBindingSetOption.

kull-m-rpc-drsr-getdcbind

  1. Establishes the DRS (Directory Replication Service) binding by calling IDL_DRSBind.
  2. Gets the GUID for the NTDS DSA object by calling IDL_DRSDomainControllerInfo.
  3. Also establishes the DRS binding for the corresponding GUID by calling IDL_DRSBind.

kuhl-m-lsadump-dcsync-1

  1. Asks updates from the NC replica on the server by calling IDL_DRSGetNCChanges.
  2. After retrieving the updates, enumerate the REPLNTINFLIST structure for the object.
  3. For each REPLINTINFLIST structure, extracts the corresponding value and decrypts it with MD5.
  4. Dumps the result with the standard format or the CSV format. It depends on the command line argument.

lsadump::dcshadow

This command injects a data to DC.

kuhl-m-lsadump-dcshadow-encode

  1. If the user specifies the stack option, the specified data — including the object, attribute, and value — is queued for later use.
  2. If the user specifies the push option, all previously queued changes are replicated to the domain controller.

kuhl-m-lsadump-dcshadow-init-ldap

  1. Initializes the session with the LDAP server on the specified domain controller by calling ldap_init.

  2. Sets the LDAP version to 3.0 and enables the LDAP signing, and establishes a connection with the LDAP server by calling ldap_connect then authenticates the client by calling ldap_bind_s.

  3. Gets the domain information via the RootDSE by calling ldap_search_s to find it.

  4. Gets the information for the fake computer account by calling ldap_search_s.

  5. Gets the information for the account containing objectGUID, invocationId, msDS-ReplicationEpoch. Build the replication data.

  6. If the user specifies the addentry option, calls IDL_DRSAddEntry to inject the replication data.

  7. If the server start option, once the replication data injected, the RPC server starts by calling the corresponding APIs such as RpcServerUseProtseqEp, RpcServerRegisterAuthInfo, RpcServerRegisterIf2, RpcServerInqBindings, RpcEpRegister, RpcServerListen.

  8. If the user specifies neigher addentry nor startServer, performs the following processing:

    1. If the user specifies the push, manualregister or kill option, registers the specified object to Active Directory via LDAP by calling ldap_add_s, ldap_modify_s, IDL_DRSAddEntry.
    2. Once it succeeds, if the user specifies the push or manualpush option, force sync by adding the replication data the target domain controller by calling IDL_DRSReplicaAdd, and immediately delete the link by calling IDL_DRSReplicaDel.
    3. If the user specifies the kill option, triggers to remove the LingeringObject by calling ldap_modify_s.
    4. If the user specifies the manualunregister option, unregister the fake DC from Active Directory by calling ldap_delete_s.

lsadump::setntlm

This command asks a server to set a new password/ntlm for one user.

kuhl-m-lsadump-setntlm

  1. Initializes the SAMPR_USER_INFO_BUFFER structure with NTLM and LM password hashes to prepare it for use in later.
  2. If the user specifies the password option, calls RtlCalculateNtOwfPassword to calculate NT hash from the password.
  3. If the user specifies the ntlm option, converts the specified hash to Hex.
  4. Gets the handle to the specified server by calling SamConnect.
  5. Enumerates domains in the Sam server by calling SamEnumerateDomainsInSamServer.
  6. For each domain, gets the handle to the domain by calling SamOpenDomain.
  7. If the user specifies the name, looks up the account name by calling SamLookupNamesInDomain to get the RID.
  8. Gets the handle to the user by calling SamOpenUser.
  9. Overwrites the password/ntlm with the new one by calling SamSetInformationUser against the user.

lsadump::changentlm

This command asks a server to change a password/ntlm for one user.

The processing here is similar to the lsadump::setntlm, but the last function called is SamiChangePasswordUser instead of SamSetInformationUser.

lsadump::netsync

This command retrieves NTLM hashes by abusing the NETLOGON protocol.

kuhl-m-lsadump-netsync-1

  1. Gets the server challenge (the NETLOGON_CREDENTIAL structure) from the server by calling I_NetServerReqChallenge with the client challenge.
  2. Calculates MD5 hashes for the decimal 0, the client challenge data, and the server challenge data.
  3. Calculates the HMAC with MD5 by calling CryptAcquireContext, CryptCreateHash, CryptSetHashParam, CryptHashData, CryptGetHashParam to get the session key.
  4. Encrypts the client challenge and the server challenge data by calling RtlEncryptBlock to get the client credential and the candidate server credential.
  5. Authenticates the specified remote host by calling I_NetServerAuthenticate2 with the client credential to get the server credential.

kuhl-m-lsadump-netsync-2

  1. If it succeeds, compare the candidate server credential and the server credential.

  2. Enumerates secure channels including WorkstationSecureChannel, ServerSecureChannel, TrustedDnsDomainSecureChannel, CdcServerSecureChannel.

  3. For each secure channel, the following processing is executed:

    1. Adds the timestamp and encrypted client credential for the Authenticator by calling RtlEncryptBlock.
    2. Gets the encrypted new and old passwords by calling I_NetServerTrustPasswordsGet for the specified account.
    3. Decrypts the passwords by calling RtlDecryptNtOwfPwdWithUserKey with the session key to get the NTLM hashes.

lsadump::packages

This command lists security packages.

kuhl-m-lsadump-packages

  1. Calls EnumerateSecurityPackages to enumerate the security packages.
  2. Displays each package information including name, description, capabilities, version, etc.

lsadump::mbc

This command dumps the MachineBoundCertificate.

kuhl-m-lsadump-mbc

  1. Gets the data form the registry path HKLM\System\CurrentControlSet\Lsa\Kerberos\Parameters\MachineBoundCertificate.
  2. Extracts data from that.

lsadump::zerologon

This command abuses the ZeroLogon vulnerability for the NETLOGON protocol.

kuhl-m-lsadump-zerologon

  1. Prepares the NETLOGON_AUTHENTICATOR Authenticator = {{0}, 0} for abusing the the ZeroLogon vulnerability.

  2. Creates the RPC binding by calling the corresponding APIs such as RpcStringBindingCompose, RpcBindingFromStringBinding, RpcBindingSetAuthInfoEx, RpcBindingSetOption.

  3. The following processing will be attempted up to 2000 times:

    1. Gets the server challenge by calling NetrServerReqChallenge with the zero padding authenticator credential.
    2. Authenticates by calling NetrServerAuthenticate2.
    3. If it succeeds, reset the password of the domain controller by calling NetrServerPasswordSet2.

lsadump::postzerologon

This command sets a new password for one user after ZeroLogon.

kuhl-m-lsadump-update-dc-password

  1. Enumerates accounts of the specified server by calling the corresponding APIs such as SamConnect, SamEnumerateDomainsInSamServer, SamLookupDomainInSamServer, SamOpenDomain.
  2. If the specified account is found, get the RID by calling SamLookupNamesInDomain.
  3. Gets the handle to the account by calling SamOpenUser and sets the new password by calling SamSetInformationUser.
  4. Once updated, set the new password for the LSA secret by calling LsaSetSecret.

ts::sessions

This command lists sessions on a terminal server.

  1. Gets the handle to the specified terminal server by calling WinStationOpenServerW.
  2. Enumerates sessions on the server by calling WinStationEnumerateW.
  3. Gets the information for each session by calling WinStationQueryInformationW.
  4. Prints the result to the console.

ts::remote

This command connects a remote terminal server.

It connects to the specified terminal server by calling WinStationConnectW.

event::clear

This command clear an Windows event log.

  1. Gets the handle to the specified log by calling OpenEventLog.
  2. Checks the number of the event logs by calling GetNumberOfEventLogRecords.
  3. Clears the event log by calling ClearEventLog.
  4. Checks again the number of the event logs by calling GetNumberOfEventLogRecords.

token::whoami

This command displays current identity.

  1. Gets the handle to the token for current process, and uses GetTokenInformation to get the information of the token then displays them. Also, calls LookupPrivilegeName to display the privileges.
  2. Get the handle to the token for current thread, and do the same processing as above.
  3. If the user specifies the domainadmin or enterpriseadmin option, gets the domain information by calling LsaQueryInformationPolicy.
  4. Gets the SID and the name by calling CreateWellKnownSid and LookupAccountSid.

vault::list

This command lists Windows Vaults.

  1. Enumerates vaults by calling VaultEnumerateVaults.
  2. For each vault, opens the handle to the vault by calling VaultOpenVault.
  3. Gets the information for the vault by calling VaultGetInformation and displays it.
  4. Enumerates the vault items by calling VaultEnumerateItems and displays each information for the item.
  5. Gets the Authenticator for the item by calling VaultGetItem7 and displays the information.

dpapi::blob

This command describes a DPAPI blob.

  1. If the user specifies the in option (file path), reads the data from the file path.
  2. If the user specifies the raw option, converts the specified data to the Hex buffer.
  3. Extracts the information from the specified blob such as the description, the version, the GUID of the provider, the HMAC key, the salt, etc. And display them.
  4. Gets the master key entry from the GUID.
  5. Decrypts the blob with the master key by calling CryptDecrypt. The cryptographic algorithm depends on that blob.

dpapi::masterkey

This command describes a MasterKey file and unprotect each MasterKey.

  1. Reads buffer from the specified MasterKey file.

  2. Extracts the master key, the backup key, the credential history, and the domain key from the offset for the buffer.

  3. Displays the information for the master key such as version, GUID, flags.

  4. If the credential history exists in the master key, find the corresponding credential entry from a global list.

  5. Displays the information of the entry including SID, GUID, MD4 hash, SHA1 hash, MD4p hash.

  6. Gets the derived key depending on the masterKeys->dwFlag.

  7. Decrypts the master key with the derived key in the following method:

    1. Derives the decryption kay (session key) and IV with PBKDF2.
    2. Decrypts the master key by calling CryptDecrypt.
    3. Verifies the decrypted master key with HMAC.
    4. Displays the decrypted master key.

dpapi::cred

This command describes a Credentials file and unprotect it.

Its operation is almost the same as the dpapi::masterkey, but it reads a Credentials file and decrypts the credentials information.

dpapi::chrome

  1. Initializes the SQLite library by calling sqlite3_initialize.
  2. Opens the specified database file by calling sqlite3_open.
  3. Checks if the “logins” table exists in the database by executing the “select count(*) from sqlite_master where type=‘table’ and name=logins” query.
  4. If it exists, execute the “select signon_realm, origin_url, username_value, password_value from logins” query to extract the information from the table.
  5. Enumerates the result and display the URL, username, and password which is decrypt by calling BCryptDecrypt.
  6. Checks if the “cookies” table exist in the database by executing the “select count(*) from sqlite_master where type=‘table’ and name=cookies” query.
  7. If it exists, execute the “select host_key, path, name, creation_utc, expires_utc, encrypted_value from cookies order by host_key, path, name” query to extract the information from the table.
  8. Enumerate the result and display the information. The encrypted cookie value is decrypted by calling BCryptDecrypt.

IOCs

Files

  • mimikatz.exe: 61c0810a23580cf492a6ba4f7654566108331e7a4134c968c2d6a05261b2d8a1