Mimikatz 中 sekurlsa__wdigest 的实现

发布于 2024-09-07 11:44:03 字数 9124 浏览 12 评论 0

0x00 前言

Mimikatz 中 sekurlsa::wdigest 是渗透测试中经常会用到的功能,它能够从 lsass 进程中提取凭据,通常可获得已登录用户的明文口令(Windows Server 2008 R2 及更高版本的系统默认无法获得,需要修改注册表等待用户再次登录才能获得)

XPN 在他的博客中记录了对 WDigest 的研究心得,开源了一个 POC,通过 C++实现了在 Win10_1809 x64 下从 lsass 进程中提取凭据

本文将会对 XPN 的 POC 进行扩展,使其支持 Win7/Win8/Windows Server2008/Windows Server2008 R2/Windows Server2012/Windows Server2012 R2,记录程序实现的细节与过程

0x02 简介

本文将要介绍以下内容:

  • 实现思路
  • 程序实现细节

0x03 实现思路

  1. 提升至 Debug 权限
  2. 获得 lsass 进程句柄
  3. 枚举 lsass 进程中全部模块的句柄,定位 wdigest.dll 和 lsasrv.dll 在内存中的位置
  4. 从 lsasrv.dll 中获得 InitializationVector,AES 和 3DES 的值,用于解密
  5. 从 wdigest.dll 中获得每条凭据的信息,判断加密算法,解密获得明文口令

具体说明如下:

1. 提升至 Debug 权限

代码可直接使用之前的代码:

https://github.com/3gstudent/Homework-of-C-Language/blob/master/CheckCriticalProess.cpp

2. 获得 lsass 进程句柄

  • 通过 CreateToolhelp32Snapshot 创建进程快照
  • 遍历进程列表
  • 搜索进程 lsass.exe,获得 pid
  • 获得 lsass 进程句柄

3. 枚举 lsass 进程中全部模块的句柄,定位 wdigest.dll 和 lsasrv.dll 在内存中的位置

通过 EnumProcessModules 枚举 lsass 进程中全部模块的句柄

4. 从 lsasrv.dll 中获得 InitializationVector,AES 和 3DES 的值,用于解密

不同系统的偏移位置不同,详细可参考 mimikatz 的源码:https://github.com/gentilkiwi/mimikatz/blob/68ac65b426d1b9e1354dd0365676b1ead15022de/mimikatz/modules/sekurlsa/crypto/kuhl_m_sekurlsa_nt6.c

偏移不同的位置有以下四个:

  • LsaInitializeProtectedMemory_KEY
  • int IV_OFFSET
  • int DES_OFFSET
  • int AES_OFFSET

不同系统下 AES 和 3DES 的数据结构也不同:

Win7:

typedef struct _KIWI_BCRYPT_KEY {
    ULONG size;
    ULONG tag;    // 'MSSK'
    ULONG type;
    ULONG unk0;
    ULONG unk1;
    ULONG bits;
    KIWI_HARD_KEY hardkey;
} KIWI_BCRYPT_KEY, *PKIWI_BCRYPT_KEY;

注:来源于: https://github.com/gentilkiwi/mimikatz/blob/master/modules/kull_m_crypto.h

Win8 和 Win10:

typedef struct _KIWI_BCRYPT_KEY81 {
    ULONG size;
    ULONG tag;    // 'MSSK'
    ULONG type;
    ULONG unk0;
    ULONG unk1;
    ULONG unk2; 
    ULONG unk3;
    ULONG unk4;
    PVOID unk5;    // before, align in x64
    ULONG unk6;
    ULONG unk7;
    ULONG unk8;
    ULONG unk9;
    KIWI_HARD_KEY hardkey;
} KIWI_BCRYPT_KEY81, *PKIWI_BCRYPT_KEY81;

注:来源于: https://github.com/gentilkiwi/mimikatz/blob/master/mimikatz/modules/sekurlsa/crypto/kuhl_m_sekurlsa_nt6.h

其中,KIWI_BCRYPT_KEY 和 KIWI_BCRYPT_KEY81 中的 KIWI_HARD_KEY 存储 AES 和 3DES 的数据,结构如下:

typedef struct _KIWI_HARD_KEY {
    ULONG cbSecret;
    BYTE data[ANYSIZE_ARRAY]; // etc...
} KIWI_HARD_KEY, *PKIWI_HARD_KEY;

注:来源于: https://github.com/gentilkiwi/mimikatz/blob/master/modules/kull_m_crypto.h

ULONG cbSecret 表示长度, BYTE data[ANYSIZE_ARRAY] 为实际加密内容

5. 从 wdigest.dll 中获得每条凭据的信息,解密出明文口令

凭据信息位于固定偏移位置,可通过搜索固定结构( BYTE PTRN_WIN6_PasswdSet[] = {0x48, 0x3b, 0xd9, 0x74}; ) 定位

注:来源于: https://github.com/gentilkiwi/mimikatz/blob/master/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_wdigest.c

每条凭据以双链表的格式存储,格式如下:

typedef struct _KIWI_WDIGEST_LIST_ENTRY {
    struct _KIWI_WDIGEST_LIST_ENTRY *Flink;
    struct _KIWI_WDIGEST_LIST_ENTRY *Blink;
    ULONG    UsageCount;
    struct _KIWI_WDIGEST_LIST_ENTRY *This;
    LUID LocallyUniqueIdentifier;
} KIWI_WDIGEST_LIST_ENTRY, *PKIWI_WDIGEST_LIST_ENTRY;

注:来源于: https://github.com/gentilkiwi/mimikatz/blob/master/mimikatz/modules/sekurlsa/packages/kuhl_m_sekurlsa_wdigest.h

每个节点偏移 48 的位置存储凭据信息,格式如下:

typedef struct _KIWI_GENERIC_PRIMARY_CREDENTIAL
{
    LSA_UNICODE_STRING UserName;
    LSA_UNICODE_STRING Domaine;
    LSA_UNICODE_STRING Password;
} KIWI_GENERIC_PRIMARY_CREDENTIAL, *PKIWI_GENERIC_PRIMARY_CREDENTIAL;

注:来源于: https://github.com/gentilkiwi/mimikatz/blob/master/mimikatz/modules/sekurlsa/globals_sekurlsa.h

每条凭据会根据加密数据的长度选择算法:

  • 如果加密后的数据长度为 8 的倍数,那么在 CFB 模式下使用 AES
  • 否则,在 CBC 模式下使用 3DES

0x04 程序实现细节

XPN 的 POC 支持在 Win10_1809 x64 下从 lsass 进程中提取凭据,地址如下:https://gist.github.com/xpn/12a6907a2fce97296428221b3bd3b394

为了使其支持 Win7/Win8/Windows Server2008/Windows Server2008 R2/Windows Server2012/Windows Server2012 R2,需要考虑如下问题:

1. 添加提升至 Debug 权限的代码

BOOL EnableDebugPrivilege(BOOL fEnable)
{
    BOOL fOk = FALSE;
    HANDLE hToken;
    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
    {
        TOKEN_PRIVILEGES tp;
        tp.PrivilegeCount = 1;
        LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
        tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
        AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
        fOk = (GetLastError() == ERROR_SUCCESS);
        CloseHandle(hToken);
    }
    return(fOk);
}

2. 判断操作系统版本

这里可以使用之前的代码,地址如下:https://github.com/3gstudent/Homework-of-C-Language/blob/master/GetOSVersion.cpp

需要注意的是代码对 Win10 的具体版本没有进行判断,而不同的 Win10 系统,偏移会有不同,例如 Win10_1507 和 Win10_1903

注:来源于 https://github.com/gentilkiwi/mimikatz/blob/master/mimikatz/modules/sekurlsa/crypto/kuhl_m_sekurlsa_nt6.c

3. 不同操作系统版本对应不同的偏移

影响以下四个参数:

  • LsaInitializeProtectedMemory_KEY
  • int IV_OFFSET
  • int DES_OFFSET
  • int AES_OFFSET

4. 不同操作系统版本对应不同的 AES 和 3DES 数据结构

Win7:

KIWI_BCRYPT_KEY extracted3DesKey, extractedAesKey;

Win8 和 Win10:

KIWI_BCRYPT_KEY81 extracted3DesKey, extractedAesKey;

5.对每条凭据中加密数据的长度进行判断

使用不同的解密算法并在输出上进行体现:

  • 如果加密后的数据长度为 8 的倍数,那么在 CFB 模式下使用 AES
  • 否则,在 CBC 模式下使用 3DES

完整代码已开源,地址如下:https://github.com/3gstudent/Homework-of-C-Language/blob/master/sekurlsa-wdigest.cpp

代码实现了对 64 位系统的凭据读取,输出信息同 mimikatz 的 sekurlsa::wdigest 结果相同,支持以下操作系统:

  • Win7 x64/Windows Server 2008 x64/Windows Server 2008R2 x64
  • Win8 x64/Windows Server 2012 x64/Windows Server 2012R2 x64
  • Win10_1507(and before 1903) x64

如果想要支持 Win10_1903,可添加对 Win10_1903 及更高版本的系统进行识别,加上对应的偏移计算即可

如果想要支持 32 位系统,修改对应变量的偏移即可

0x05 补充

对于 Windows Server 2008 R2 及更高版本的系统,默认配置下无法在凭据中保存明文信息,也就无法导出明文口令,可通过修改注册表启用 Wdigest Auth 解决这个问题,方法如下:

cmd:

reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 1 /f

or powershell:

Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest -Name UseLogonCredential -Type DWORD -Value 1

等待用户再次登录,就能获得凭据中的明文信息

0x06 小结

本文对 XPN 的 POC 进行扩展,使其支持 Win7/Win8/Windows Server2008/Windows Server2008 R2/Windows Server2012/Windows Server2012 R2, 实现了 Mimikatz 中 sekurlsa::wdigest 的功能,记录程序实现的细节与过程。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

妖妓

暂无简介

0 文章
0 评论
520 人气
更多

推荐作者

lee_heart

文章 0 评论 0

往事如风

文章 0 评论 0

春风十里

文章 0 评论 0

纸短情长

文章 0 评论 0

qq_pdEUFz

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文