DPAPI概述
前言
微软在Windows2000之后提供了一个操作系统级的对数据保护加解密的接口DPAPI(Data Protection API),操作系统级是指由操作系统本身提供的服务,不需要任何额外的库。其属于Crypt32.dll的一部分,可供任何加载它的用户进程使用。DPAPI有两套接口分别是用户接口和系统接口,在使用DPAPI加密的数据在解密时会使用用户身份的上下文解密,使得被加密的数据只能由当前用户解密。
下图为微软官方给出的DPAPI的架构图
CryptProtectData 和CryptUnprotectData
DPAPI(Data Protection API),Win32 DPAPI中有4个函数,分别是CryptProtectData、CryptUnProtectData、CryptProtectMemory和CryptUnProtectMemory。其中CryptProtectData加密数据,CryptUnprotectData解密数据,加密后的数据由应用程序负责安全存储,应用无需解析加密后的数据格式。但是,加密后的数据存储需要一定的机制,因为该数据可以被其他任何进程用来解密,当然CryptProtectData也提供了用户输入额外数据
来参与对用户数据进行加密的参数,但依然无法放于暴力破解。两个函数的结构如下所示。
输入数据参数pDataIn是一个DATA_BLOB结构,该结构的定义如下:
typedef struct _CRYPTOAPI_BLOB {
DWORD cbData; //数据的长度
BYTE* pbData; //指向数据的指针
} DATA_BLOB;
当dwFlags标志位设置0时,DPAPI会使用当前用户的master key进行加密操作。
MasterKey
DPAPI会生成一个叫masterkey的强密钥,这个是在解密DPAPI加密数据中所需的最重要的一部分。该密钥受用户密码的保护,使用用户登录密码、SID和16字节随机数加密后保存在Master Key file中默认的有效期是三个月。前文我们提到masterkey。从文章《tbal-dpapi-backdoor》分析中我们知道masterkey是解密dpapi中最关键的一部分。
注册表
HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography\Protect\Providers\GUID
存储了masterkey在生成时的迭代次数。
· 用户master key文件位于%APPDATA%\Microsoft\Protect%SID%
· 系统master key文件位于%WINDIR%\System32\Microsoft\Protect\S-1-5-18\User
其中preferred文件记录了正在使用的Masterkey及其过期时间,另外高版本的操作系统需在文件选项中取消勾选隐藏受保护文件选项才能看到。
在渗透测试中的部分利用
mimikatz
在最理想的状态(拥有管理员以上权限的shell)下使用mimikatz运行以下命令
privilege::debug
sekurlsa::dpapi
我们知道mimikatz中的sekurlsa模块都是操作lsass进程内存实现的。因此在无法做到对mimikatz或者其他什么无法直接在目标机器上运行mimikatz的情况下,我们可以利用微软开发的procdump工具将lsass进程内存dump下来。
再使用以下两个命令对dump下来的lsass.dmp读取dpapi
sekurlsa::minidump lsass.dmp
sekurlsa::dpapi
前面提到过很多第三方应用也使用了DPAPI的函数来对数据进行保护,mimikatz中自带了对chrome的利用模块。可使用以下两个命令获取DPAPI中的cookies和登录信息。
dpapi::chrome /in:”%localappdata%\Google\Chrome\User Data\Default\Cookies” /unprotect
dpapi::chrome /in:”%localappdata%\Google\Chrome\User Data\Default\login data” /unprotect
Preferred文件
上面提到过在DPAPI的masterkey文件下存储了masterkey和preferred文件,masterkey作为解密的关键有着重要的作用。通过对preferred解析可以显示并延长masterkey的有效时间。以下是preferred的数据结构。
typedef struct _tagPreferredMasterKey
{
GUID guidMasterKey;
FILETIME ftCreated;
} PREFERREDMASTERKEY, *PPREFERREDMASTERKEY;
使用16进制编辑器打开preferred
如图所示前16个字节对应的是guid,后8字节表示的是过期时间,可使用以下代码读取preferred文件
#include <windows.h>
#include<stdio.h>
int main(void)
{
FILE* fp;
unsigned char buf[24];
fopen_s(&fp, “C://Users/Administrator/Desktop/tmp/Preferred”, “rb”);
fread(buf, 1, 24, fp);
printf(“Data: “);
for (int i = 0; i < 24; i++)
{
printf(“%02x”, buf[i]);
}
fclose(fp);
printf(“\nguidMasterKey: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n”, buf[3], buf[2], buf[1], buf[0], buf[5], buf[4], buf[7], buf[6], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
char lowDateTime[9], highDateTime[9];
sprintf_s(lowDateTime, 9, “%02X%02X%02X%02X”, buf[19], buf[18], buf[17], buf[16]);
sprintf_s(highDateTime, 9, “%02X%02X%02X%02X”, buf[23], buf[22], buf[21], buf[20]);
printf(“dwLowDateTime:%s\n”, lowDateTime);
printf(“dwHighDateTime:%s\n”, highDateTime);
FILETIME ftUTC;
SYSTEMTIME stUTC2;
sscanf_s(lowDateTime, “%x”, &ftUTC.dwLowDateTime);
sscanf_s(highDateTime, “%x”, &ftUTC.dwHighDateTime);
FileTimeToSystemTime(&ftUTC, &stUTC2);
printf(“”);
printf(“Expiry time: %d-%d-%d %d:%d:%d\n”, stUTC2.wYear, stUTC2.wMonth, stUTC2.wDay, stUTC2.wHour, stUTC2.wMinute, stUTC2.wSecond);
return 0;
}
总结
DPAPI是Windows提供的对数据保护的api,有四个核心的函数CryptProtectData、CryptUnProtectData、CryptProtectMemory和CryptUnProtectMemory。CryptProtectData负责加密数据,CryptUnProtectData负责解密数据
masterkey是DPAPI加密解密的关键,默认90更新一次,masterkey存储位置的文件下一个preferred,对preferred文件解析可查看并修改masterkey的过期时间。
使用mimikatz可直接获取到目标机器的masterkey,同时mimikatz自带有对部分使用了DPAPI应用的解密功能,如Chrome的cookies和login data。