第二篇文章基于我们团队在OFFZONE-2018的表现结果。 这次,考虑与MainTrack“ Windows DPAPI”,“ Sekretiki”或“渗透测试者的DPAPI”进行讨论。
注意! 很多山毛榉!
在进行RedTeam活动时,我想减少BlueTeam反应的原因,但是可能有很多原因。 例如,运行mimikatz以获取用户密码或证书。 即使我们能够从卡巴斯基“ otmazyvat”他,BlueTeam也能够使用Sysmon,Microsoft ATA等专用工具进行跟踪。 同时,我想从受感染的用户计算机上获得最大的信息。 在RedTeam反复开展活动以对抗真正的BlueTeam团队的过程中,我们得出的结论是,有必要避免采取可作为系统危害指标的措施。 通过使用操作系统为用户提供的法律机制和措施,可以实现此目标。
DPAPI(Windows数据保护API)机制就是此类法律工具之一,操作系统和各种应用程序都使用该机制来加密敏感的用户数据(主要是密码,加密密钥等)。对于最终用户及其应用程序而言,DPAPI看起来非常简单:只有2个功能-“加密数据”和“解密数据”。 在本文中,我将考虑在RedTeam竞选期间这种机制对渗透测试者有用的方法。
什么是DPAPI? 仅简短地用俄语
自2000年以来,所有Windows操作系统都已开始使用DPAPI引擎来确保用户数据的安全。
如果跳过报告中检查的所有加密,以解密通过DPAPI加密的数据,则需要:主密钥,用户SID,用户密码哈希和DPAPI Blob本身(加密的DPAPI数据)。
通常,该过程如下所示:

在我们的“加密帽子”内部,有许多不同的加密机制,我们在本文中将不予考虑,以免使读者负担过重。 我们只注意到DPAPI的主要部分是所谓的万能钥匙(master key)。 简而言之,主密钥是使用预密钥加密的64字节随机数据,该预密钥由用户的密码及其SID生成。

其他参数也参与预密钥生成:迭代次数(IterN),salt和HMAC,具体情况可能会有所不同。 这些参数的值与主密钥一起存储在一个文件中。
因此,知道用户的密码,其SID并从主密钥文件(HMAC,Salt,InterN)中读取生成参数后,我们可以生成一个预密钥并解密主密钥,即 获得我们将用于解密DPAPI Blob的非常随机的64个字节。
如果我更改密码怎么办?
通常,用户密码会定期更改。 如果用户更改密码会怎样? 上一个去了哪里? 确实,要解密主密钥,您需要知道用户密码,并且每次都重新加密所有用户主密钥实在太昂贵了。 在这种情况下,一切都在Windows中考虑。
有一个特殊文件(CREDHIST),其任务是存储所有以前的用户密码。 它还使用用户的当前密码加密并存储在堆栈中。 如果系统突然无法解密主密钥,则其操作如下:使用当前密码,解密CREDHIST中的第一条记录。 密码尝试再次解密主密钥,依此类推,直到链中的密码用完或解密主密钥为止。
有关域控制器的私钥的一些知识
您可能已经猜到了,DPAPI应用于所有用户,包括域用户。 为了能够将密码重置给在某个周五晚上的聚会后成功忘记了密码的用户,您需要一个备用密钥,该备用密钥将存储在安全的地方。 根据Microsoft的说法,这样一个可靠的地方是域控制器。
重置用户密码后用于解密主密钥的机制的实质如下:在域控制器上创建了一对RSA密钥(私有和公共)。 私钥存储在NTDS数据库中的域控制器上,称为BCKUPKEY_xxxx(请参见下图),并且公钥分发到所有域系统,并在生成主密钥时用于生成主密钥的副本。
在域计算机上创建主密钥后,还将创建其重复副本(或者说,主密钥材料是其64字节),该副本与主主密钥一起存储在一个文件中,称为域密钥。 如果您丢失了主主密钥,即 重置用户密码时,系统会将其副本发送到域控制器,并要求对其进行解密。 授予用户权限的控制器对副本进行解密,然后将其返回给系统,此后,主密钥材料已使用新密码再次加密。

在域中具有适当的特权(通常是管理员),您可以通过复制机制从域控制器获取这些RSA私有密钥,并将其用于对在域计算机上创建的主密钥进行进一步的解密。 可以使用mimikatz或DSInternals完成。 您可以在mimikatz Wiki或
DSInternals博客中了解有关此内容的更多信息。
主密钥存储在哪里,它们是什么?
主密钥可以是用户密钥,也可以是系统密钥,具体取决于加密的机密。 用户主密钥通过以下方式存储在用户配置文件中:
Users\%USER%\AppData\Roaming\Microsoft\Protect\%SID%\
以防万一,系统会存储用户曾经使用过的所有主密钥。 毕竟,她事先不知道哪个主人需要使用密钥解密某些东西。 当前使用的密钥的GUID存储在“首选”文件中。

系统主密钥以以下方式存储:
windows\system32\Microsoft\Protect\S-1-5-18\
与用户相似-使用一个主密钥,其名称可以在“首选”文件中找到,该文件存储了曾经使用过的所有密钥。

那么,这个DPAPI能给Pentester带来什么?
由于DPAPI是合法且简单的机制,因此各种应用程序都尝试使用它。 因为它既方便又安全。 当然是暂时的。
例如,DPAPI用于加密客户端和系统证书的私钥,WIFI密钥,Chrome(Cookie,密码),DropBox,Skype,RSA SecurID(生成一次性密钥的软件应用程序)。 这绝不是详尽的清单。
pentester的任务是解密必要的blob并获取密码,cookie等。
有几种方法可以做到这一点。 一种或另一种方式,它们全都归结为两个成绩单-在线和离线。 在线解密是指在用户的机器上,我们只需调用系统函数来解密数据并将DPAPI Blob传递给输入,然后系统自行完成所有操作-它搜索使用Blob加密的主密钥,并使用用户的SID对其进行解密密码哈希存储在LSASS存储器中。
下图显示了在Powershell上调用DPAPI函数进行加密和解密的示例。

首先,我们通过调用[Security.Cryptography.ProtectedData] :: Protect()函数来加密我们的秘密(在本例中为单词“ Password”)。 我们执行了两次(第一种情况是使用用户的主键(参数CurrentUser),第二种是系统主键(参数LocalMachine)。 然后,我们可以通过调用反函数-[Security.Cryptography.ProtectedData] :: UnProtect()来解密生成的Blob。
此外,在这种情况下,CurrentUser或LocalMachine参数的值无关紧要,因为 系统本身会找到一个适合解码blob的主密钥,并执行所有必要的操作。 在这两种情况下,我们都得到了最初的秘密-单词“ Password”(按字节表示)。
在线解密时,重要的是要了解您在什么上下文中调用UnProtect()函数。 为了使解密成功,您必须处于用户会话中或以新会话登录。 事情是密码哈希,它存储在LSASS内存中。 如果您在用户会话之外进行呼叫(例如,您是通过psexec或meterpreter通过网络登录到系统的),那么您就不需要解密主密钥的密码哈希。 他当然在下届会议中,但是LSASS不会将其发送给您,因为 这是另一个会话,尽管它是在同一用户下创建的。 为了成功进行在线解密,您必须迁移到由用户通过GUI登录启动的任何进程,或者例如通过RDP完全登录到系统。
用于在线解密DPAPI Blob的powershell的替代方法可以是使用/ unprotect参数调用mimiktaz :: blob。 在输入处,给他一个带有DPAPI blob的二进制文件,在输出处,我们获得了解密的数据。 HarmJ0y
博客上介绍
了更多使用mimikatz
的案例。
母球掉落了。 用vidyuhi处理我的农场怎么办?
由于DPAPI主密钥是在用户密码上加密的事实,因此您可以尝试执行相反的过程-通过用户的主密钥对用户的密码进行暴力破解。 例如,我们从发送的docx文件的宏或DDE接收到反向连接。 我们可以获取用户的主密钥并还原用户的密码,而无需升级特权和启动mimikatz。
我可以使用Hashcat或JohnTheRipper进行密码暴力破解吗? 但是在此之前,您需要使用适当的脚本从John的构成中获取蛮力参数:
./DPAPImk2john.py –S <sid> -mk <masterkey> -c <domain|local>
然后,我们已经可以将脚本结果与视频卡一起发送到我们的服务器场,并希望用户输入的密码不正确,因为 主密钥蛮力速度大约可与WPA2枚举速度相媲美,即 相当慢。
在这里值得注意的是,如果在域Windows 10上生成主密钥,则将另外10,000轮PBKDF2算法添加到预密钥生成中。 但更糟糕的是,Hashcat和JohnTheRipper都不知道这一点(至少在撰写本文时),这意味着他们将无法从这样的主密钥中删除密码。
“拿走所有不好的东西,然后找出来……”
正如我们前面提到的,在用户机器上执行可疑动作可能会引起Blueteam团队的更多兴趣,因此,这充满了所有RedTeam都将在此处结束的事实。 一个例子是在会计师或秘书的计算机上启动Powershell,然后对该事件进行调查。 为了不引起不必要的怀疑,最好使用脱机方法来解码DPAPI Blob。 为此,您必须首先从计算机中提取所需的一切,即:
- 用户主密钥
- 系统主键
- CREDHIST文件(如果它不是域计算机);
- 用户密码(或其sha1 / ntlm哈希);
- 用户的SID;
- 我们要解密的DPAPI Blob。
对于离线模式的解密,我们离不开专门的工具。 这些工具可能是:
- 米米卡兹
- Impacket(从第18版开始,具有DPAPI功能);
- Dpapick框架。
关于dpapick框架,我们将详细讨论。
python dpapick框架本身是由研究人员Jean-Michel Pikode于2014年制作的,它是Python密码库上DPAPI机制的实现。 python的使用以及框架的结构使它易于适应各种DPAPI机制。 在其原始版本中,dpapick无法使用域备份密钥解密主密钥,并且缺少用于解密在域计算机模式下在Windows 10上创建的主密钥的机制。
在解决了这些缺点并扩展了用于解密DPAPI Blob的功能之后,dpapick变成了用于离线解码DPAPI的相当不错的工具。 下面作为示例,我们将显示使用此框架解密通过DPAPI加密的用户数据的选项。
Chrome-获取和解密Cookie和密码
Chrome
%localappdata%\Google\Chrome\User Data\Default\Cookies
存储在文件
%localappdata%\Google\Chrome\User Data\Default\Cookies
登录数据位于文件
%localappdata%\Google\Chrome\User Data\Default\Login Data
这两个文件都是sqlite3数据库,其中敏感数据存储为DPAPI Blob。 作为dpapick的一部分,该数据有一个现成的解剖器(解析器)(示例/ chrome.py)。 为了成功解密,他需要使用主密钥,用户的sid,他的密码或域控制器的私钥的位置以及Chrome中的sqlite3文件(cookie或登录数据)指定目录。
使用用户密码离线解密Chrome Cookie
./chrome.py --cookie <cookiefile> --sid <SID> --password <..> --masterkey <masterkeydir>
使用用户密码中的哈希值对Chrome Cookie进行脱机解密
./chrome.py --cookie <cookiefile> --sid <SID> --hash <..> --masterkey <masterkeydir>
使用域控制器中的私钥对Chrome密码进行脱机解密
./chrome.py --chrome <login file> --pkey <rsa-priv.pem> --masterkey <masterkeydir>
客户端证书的DPAPI
客户端证书被广泛用于-在VPN,Web应用程序等中生成OTP,EFS或身份验证。
公钥证书本身存储在用户配置文件中:
%APPDATA%\Microsoft\SystemCertificates\My\Certificates\
私有密钥(通过签名实际执行签名或其他加密操作)通过DPAPI进行加密,并且也位于路径中的用户配置文件中:
%APPDATA%\Roaming\Microsoft\Crypto\RSA\<SID>\
为了成功解密专用证书密钥,然后重新创建PFX文件,除了上述文件之外,我们还需要用户的主密钥以及他的SID和密码(或来自控制器的专用RSA密钥)。
使用Dpapick和用户密码,我们对此解密:
./efs.py --certificates <cert dir> --rsakyes <RSA dir> --sid <..> --password <..> --masterkey <masterkeydir>

屏幕快照中的可选rsaout参数允许您另外以PEM格式导出解密的RSA密钥。 脚本的结果是重新创建的没有密码的PFX文件,该文件已经可以导入到您自己并用于其预期目的。 如果在上述目录中有多个证书和私钥,则dpapick将尝试解密每个证书和私钥并制作多个pfx文件。
通过指定适当的参数,可以使用域私钥解密主密钥来执行相同的操作:
./efs.py --certificates <cert dir> --rsakyes <RSA dir> --masterkey <masterkeydir> --pkey <domain bkp key>
有关域“芯片”的更多信息
在谈到Active Directory域时,值得一提的是诸如凭据漫游(Credentials Roaming)这样的奇妙功能-当主密钥,加密密码和证书在整个Active Directory域中为用户“旅行”时的域功能。 它们没有绑定到特定的计算机,而是会“到达”域用户登录的计算机。
启用此“功能”后,用户导入的所有证书以及他的所有私钥和密码将飞入AD,并存储在相应的帐户属性中:msPKIAccountCrdentailas和msPKIDPAPIMasterKeys。
您可以通过ldapsearch查看它在AD中的外观:
ldapsearch -x -h dc1.lab.local -D “user1@lab.local" -s sub "samAccountname=user1" ldapsearch -x -h dc1.lab.local -D "admin@lab.local" -s sub "samAccountname=anyuser"

默认情况下,用户只能接收其帐户的DPAPI属性。 但是,使用提升的特权,可以对任何帐户(包括计算机帐户)执行此操作。
凭据漫游是一种非常方便的技术,不仅对于管理员来说,对于渗透测试者也是如此。 通过ldap访问域控制器后,您可以合并所有用户证书,其主密钥和通过DPAPI加密的密码(例如,用于连接网络驱动器的密码)。
我们想-为什么不为dpapick添加这样的功能-并教他如何通过ldap从域控制器中自动提取证书,对其进行解密并生成pfx文件。
./efs.py –ldap-server <..> --ldap-connect admin:Passw0rd@lab.local --ldap-user user1 --password Password1 ./efs.py –ldap-server <..> --ldap-connect admin:Passw0rd@lab.local --ldap-user user1 --pkey <rsa-priv.pem>

要执行该脚本,必须将域控制器指定为ldap服务器,连接该服务器的详细信息,我们要接收其证书的帐户的名称以及用于解密主密钥(或控制器的私有备份密钥)的密码。
投寄箱 60秒内消失...
Dropbox是使用DPAPI存储用户机密的另一个示例。 投寄箱的授权令牌存储在文件中:
c:\users\<username>\Appdata\Local\Dropbox\instance1\config.dbx c:\users\<username>\Appdata\Local\Dropbox\instance_db\instanse.dbx
这些是包含连接数据的加密sqlite3数据库。 为了进行加密,使用了对称密钥,该对称密钥又通过DPAPI加密并存储在注册表中:
HKCU\SOFTWARE\Dropbox\ks
HKCU\SOFTWARE\Dropbox\ks1
因此,保管箱劫持的一般顺序如下:
- 我们从计算机上获取两个数据库文件;
- 我们从注册表中获取密钥,并使用dpapick对其进行解密;
- 使用DPAPI,我们对接收到的密钥进行加密,并将其放入注册表中;
- 在我们的计算机上,我们替换数据库文件并运行Dropbox。
您应该注意,为上述注册表分支设置了特殊权限。 它们只能由用户读取。 管理员和系统都无法读取它们。 因此,如果您代表另一个用户(甚至是管理员)访问注册表,则必须首先在指定的注册表分支上设置适当的权限。 例如,所以(powershell):
$Sid="S-1-5-21-3463664321-2923530833-3546627382-1000"; $key=[Microsoft.Win32.Registry]::USERS.OpenSubKey("$sid\SOFTWARE\Dropbox\ks",[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::ChangePermissions); $acl = $key.GetAccessControl(); $rule = New-Object System.Security.AccessControl.RegistryAccessRule ("administrator","FullControl","Allow"); $acl.SetAccessRule($rule); $key.SetAccessControl($acl); $key_path = "REGISTRY::HKEY_USERS\$Sid\SOFTWARE\Dropbox\ks"; (Get-ItemProperty -Path $key_path -Name Client).Client;
ks和ks1键包含DPAPI Blob和md5 HMAC DPAPI Blob(最后16个字节)之前的dbx版本的标头(8个字节)。 DPAPI Blob本身以第9个字节0x01000000D0开头...这些字节必须以base64格式复制到文件,然后通过dpapick解密:
./filegeneric.py --sid <..> --password <..> --masterkey <..> --base64file <..>
然后,在您的计算机上,您需要使用我们的主密钥对在最后阶段收到的密钥进行加密,并将结果放入相应的注册表分支中。
对于加密,使用powershell最方便:
$hdata="4efebbdf394d4003317fc5c357beac4b"; [Byte[]] $dv0_entropy = 0xd1,0x14,0xa5,0x52,0x12,0x65,0x5f,0x74,0xbd,0x77,0x2e,0x37,0xe6,0x4a,0xee,0x9b; $data = ($hdata -split "(?<=\G\w{2})(?=\w{2})" | %{ [Convert]::ToByte( $_, 16 ) }); Add-Type -AssemblyName System.Security; $dk1 = [system.security.cryptography.protecteddata]::Protect($data,$dv0_entropy,[System.Security.Cryptography.DataProtectionScope]::CurrentUser); $pr=([System.BitConverter]::ToString($dk1));$pr $OBJ_hmac = New-Object System.Security.Cryptography.HMACMD5 $hmac = $OBJ_hmac.ComputeHash($dk1) $pr=([System.BitConverter]::ToString($hmac));$pr
在这种情况下,hdata是在解密阶段接收到的密钥。 dv0_entropy是DAPI在DPAPI中使用的熵常数。 对于生成的Blob,您需要在前面分配一个8字节的标头0x00000000F6000000,在后面分配HMACMD5 + 0x00
之后,您可以将数据写入相应的注册表项。
DPAPI和RSA SecurID
RSA SecurID是由RSA开发的用于生成一次性密码的客户端程序。
对于大型公司而言,这是相当流行的事情,并且还使用DPAPI,只是稍微复杂一点。 在这种情况下,RSA工程师决定混淆并应用更复杂的DPAPI方案。
令牌数据存储在文件
%LOCALAPPDATA%\RSA\SecurIDStorage
,该文件是sqlite3数据库。 每个加密令牌都包含其加密的EnTokenSid(用于代码生成算法的初始初始化的参数)。 EnTokenSid是基于DBKey,令牌的SID和用户SID生成的,并且DBAPI已经由DPAPI解密DBKeyEnc按以下顺序生成:
DBKeyEnc = DPAPI(CurrenUser, DPAPI(LocalSystem(DBKey))
即 首先,使用系统主密钥对DB密钥进行加密,然后再次使用用户主密钥对生成的DPAPI blob进行加密。
同样在数据库中,还有来自CheckSum的CryptoCheckSum:
CryptoCheckSum = DPAPI Blob(CurrenUser)
因此,为了使合并的SecurIDStorage在您的计算机上工作,您必须:
- 由于EncTokenSid的形成涉及到用户的SID,因此有必要将虚拟机上的当前用户SID设置为与从其SecurIDStorage数据库获取的用户的SID相同的值。 SysInternals的NewSid实用程序将为我们提供帮助;
- 使用用户的主密钥和密码或域私钥对DBKeyEnc进行解密(如果计算机是域);
- 使用系统主密钥和DPAPI_SYSTEM参数的值解密先前解密的结果;
- 使用用户的主密钥解密CryptoCheckSum
- 已在虚拟机上以相反的顺序加密接收到的DBKey和CheckSum值;
- 在某些版本的SecurID中,您还需要将虚拟机的HDD大小设置为与源计算机的HDD大小相同,例如 程序在启动时对其进行检查。
如上所述,为了解密DBKeyEnc,除了用户的主密钥之外,我们还需要一个系统主密钥以及值DPAPI_SYSTEM,使用该值解密系统主密钥。 DAPPI_SYSTEM实际上是已经形成的预键,参与系统主键的形成。 您可以从LSASS内存(通过mimikatz或通过分析进程转储)或从相应的注册表分支(HKLM \ SYSTEM,HKLM \ SECURITY)中获取它,将它们转储并分析相同的Impacket。
然后,我们可以使用获得的DPAPI_SYSTEM来使用dpapick解密必要的blob(解析器为examples / filegeneric.py),如以下屏幕快照所示:
1)通过mimikatz离线获取DPAPI_SYSTEM

2)通过Impacket脱机获取DPAPI_SYSTEM

3)使用用户和系统主密钥进行DPAPIck解密

备忘单
为了确保您不会忘记特定数据的位置,我们将它们放在单独的部分中:
自定义主键 %APPDATA%\Microsoft\Protect\<SID>\*
系统主键 Windows\System32\Microsoft\Protect\*
DPAPI_SYSTEM LSASecrets – online SYSTEM, SECURITY (reg save …, system\backup, etc)
用户证书 %APPDATA%\Microsoft\SystemCertificates\My\Certificates\ %APPDATA%\Microsoft\Crypto\RSA\<SID>\
系统证书 HKLM:\SOFTWARE\Microsoft\SystemCertificates\MY\Certificates\* C:\Programdata\Microsoft\Crypto\RSA\MachineKeys\
镀铬 %localappdata%\Google\Chrome\User Data\Default\Cookies %localappdata%\Google\Chrome\User Data\Default\Login Data
投寄箱 HKCU\SOFTWARE\Dropbox\ks HKCU\SOFTWARE\Dropbox\ks1 %APPDATA%\Local\Dropbox\instance1\config.dbx %APPDATA%\Local\Dropbox\instance_db\instanse.dbx
沙丁鱼 %LOCALAPPDATA%\RSA\SecurIDStorage
小结论
DPAPI是一件很了不起的事情-主要的事情是了解在进行笔测和RedTeam学习时如何使用它。
在本文中,我们仅考察了一些可以应用DPAPI解密的示例。 实际上,范围要广得多。 例如,我们没有考虑用于连接到Wi-Fi的RDP(* .rdg),Icloud(pList文件),Skype(* .Xml)密钥。 dpapick框架的任何地方都将应用DPAPI,并实现相应的解析器。
dpapick的修改版本可在我们的
GitHub上获得 。 我们敦促您使用此工具解密DPAPI,对于dpapick的进一步开发,我们将不胜感激。
在我们的频道中可以找到一些有趣的信息。 我们通过RedTeam讲述IB。
PS:感谢OFFZONE-2018的组织者举办了一个很棒的会议!
PPS本文第二部分