gpt4 book ai didi

C++解密Chrome80版本数据库的方法示例代码

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章C++解密Chrome80版本数据库的方法示例代码由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

谷歌浏览器Google Chrome 80正式版例行更新详细版本80.0.3987.163。Google Chrome浏览器又称谷歌浏览器采用Chromium内核全球最受欢迎的免费网页浏览器追求速度、隐私安全的网络浏览器.

先说下吧。chrome80以前的版本是直接可以通过DPAPI来进行解密的。关于DPAPI 大家可以 看这里的介绍 。

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

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

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

废话不多说我们且来看看新版的Chrome是怎么一个加密流程。首先。我们需要大致清楚新版chrome用到的加密。无非就是2个 划重点 。

DPAPI AES-GCM 。

先给大家看一用python写的解密吧 。

aes.pyimport osimport sysimport sqlite3from urllib.parse import urlencodeimport json, base64import aesgcmimport binasciidef 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 resultdef aes_decrypt(encrypted_txt): encrypted_txt = binascii.unhexlify(encrypted_txt) encoded_key = "RFBBUEkBAAAA0Iyd3wEV0RGMegDAT8KX6wEAAAAFBcVfgeqrR6TWICu+11nQAAAAAAIAAAAAABBmAAAAAQAAIAAAADGFDG3ftjedfJDzI98JL+tPfbE3tgNumX5v+PGs9eEgAAAAAA6AAAAAAgAAIAAAAHMoKUPxu+eC153jdAcreqzjPCvccip33ZQPvnOZstQBMAAAAFCQh824CftlmS+gbu8NK1Gev4EVvODPwV6T33S9AXilInJ26Z09nTULJE3pF+9XtEAAAACndz8ZGF2V7IMxQDK6kFAk6wOUv/Bx9hZhZtiyu2urYfKYbCPvMSWg4e9+/oQrEL2NEG+fFjX/EP6SrLzE8Xqy" encrypted_key = base64.b64decode(encoded_key) print("encrypted_key="+encrypted_key.hex()+" Len="+str(len(encrypted_key))+"\r\n"); encrypted_key = encrypted_key[5:] print("encrypted_key="+encrypted_key.hex()+"\r\n"); key = dpapi_decrypt(encrypted_key) print("key="+key.hex()+"\r\n");  nonce = encrypted_txt[3:15] print("nonce="+nonce.hex()+"\r\n"); cipher = aesgcm.get_cipher(key) ##print("cipher="+cipher.hex()+"\r\n"); print("encrypted_txt="+encrypted_txt[15:].hex()+"\r\n"); return aesgcm.decrypt(cipher,encrypted_txt[15:],nonce)print(aes_decrypt("76313068C3E4957EC879AD4483CBFA7476E7B77C035D8355A5D73FCFA9A87007D908896061DDD79471"))

然后是aes-gcm 。

import osimport sysfrom cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives.ciphers import ( Cipher, algorithms, modes)NONCE_BYTE_SIZE = 12def 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

如此即可解密。说下简单的流程吧.

大致流程从C:\Users\0ops\AppData\Local\Google\Chrome\UserData\LocalState这个Json中读取一个值os_crypt下的encrypted_key 。

然后取解密秘钥(encrypted_key)去除前5个字符再通过对其dpapi解密出这个值保存为key.并且截取15位去除前3位字符保存为Nonce. 。

然后使用asegcm进行解密key最终使用aesgcm解密.

大致就是如此。为了证明我的屁眼代码可以用。上一个图。稍等。。我去安装下chrome80。。。影子系统还原了。。。我安装好了 。

取下encrypted_key和被加密的value的HEX。在这之前 我们先看下加密的内容 。

C++解密Chrome80版本数据库的方法示例代码

包含V10和V11的是chrme80的加密。好了 我们来找找freebuf的值 。

C++解密Chrome80版本数据库的方法示例代码

把加密值HEX[v10mC1^ĻI~\`ql>t^c+EO0bJKp1YRn˭F$O]一下得到7631306D43A786939231E0A4D6DC5E**BB497E5C60716CFEFDDB3E74A7ABE2E5F1BAF45EF5F163BC2BB**54F9D30624A4B708D310C168894FFEC189C8959526ECBAD46EF1D7FD224B6868FA64F83CD 。

然后我们用python解密一下 。

C++解密Chrome80版本数据库的方法示例代码

可看到了解密成功。下一篇用C++来实现自动化解密 。

几个注意点 。

Cookie位于User Data/Default下的Cookies文件 改名为Cookies.db即可用sqllite进行查询和查看 。

上一篇实现了python的简单解密。这一次我们来用C++实现自动化。在这之前 我们需要用到两个C++库 。

repaidjson cryptopp 。

编译环境为VS2013.这两个库不多做介绍,rapidjson是腾讯的一个开源json解析库。发挥的作用不大,就是解析个json。另外就是cryptopp。嗯。。很牛逼.

解析下大致流程:

1:获取local state文件位置 。

2:获取加密的key(base64编码) 。

3:解析sqllite文件 。

4:DPAPI解密 。

5:ase-gcm解密 。

关于Aes-gcm 需要用到 KEY IV 以及被加密的字符串 梳理下这几个参数的流程:

KEY = local state = > os_crypt => Encrypted_key => Base64Decode(encrypted_key) => 去除首位5个字符 => DPAPI解密IV = 被加密的字符串掐头去尾chiper = 被加密的字符串去头

一般来说 安装的这些配置文件都在LOCAL_APPDATA下。可以使用SHGetSpecialFolderPath(NULL, szBuffer, CSIDL_LOCAL_APPDATA, FALSE),

来获取这个路径。然后starcat组合一下字符串得到路径 部分代码如下:

 char szBuffer[MAX_PATH];	if (EncryptBaseKey == "")	{		string jsonstr;		SHGetSpecialFolderPath(NULL, szBuffer, CSIDL_LOCAL_APPDATA, FALSE);		strcat(szBuffer, "\\Google\\Chrome\\User Data\\Local State");		jsonstr = readfile(szBuffer);		Document root;		root.Parse(jsonstr.c_str());		Value& infoArray = root["os_crypt"];		EncryptBaseKey = infoArray["encrypted_key"].GetString();	}	return EncryptBaseKey;

这里就获取了加密的秘钥。但是有一点。如果是非80版本 是不存在os_crypt的,这里使用的rapidjson就会抛出异常。但不影响。只需要在使用sqllite查询的时候 接管一下字符串,看看是不是包含v10或者v11即可。如果你使用的和我一样代码。请注意大小写V10和v10的区别.

 string e_str = argv[i];			if (strstr(e_str.c_str(), "v10") != NULL || strstr(e_str.c_str(), "v11") != NULL)			{				string DecryptVaule=NewDecrypt(argv[i]);				strcpy(enc_value_a, DecryptVaule.c_str());			}			else{				DecryptPass(argv[i], enc_value, 2048);				_snprintf_s(enc_value_a, sizeof(enc_value_a), _TRUNCATE, "%S", enc_value);			}

紧接着就是对他进行base64解密。这里我用的是cryptopp  先放一下新版解密函数 。

std::string static NewDecrypt(CHAR *cryptData){	string EncryptValue = cryptData;	string Encoded,Decoded;	string key,iv,chiper;	string recovered;//也就是解密的KEY	WCHAR enc_value[2048];	char enc_value_a[2048];	ZeroMemory(enc_value, sizeof(enc_value));	ZeroMemory(enc_value_a, sizeof(enc_value_a));	//-----------------------初始化几个要用到加密字符串的变量----------------------------------//	iv = EncryptValue;	chiper = EncryptValue;	//---------------------------------------------------------//	StringSource((BYTE*)EncryptValue.c_str(), EncryptValue.size(), true,		new HexEncoder(		new StringSink(Encoded)));	EncryptValue = Encoded;	Encoded.clear();	//---------------------------------------------------------//	key = GetEncryptKEY();	StringSource((BYTE*)key.c_str(), key.size(), true,		new Base64Decoder(		new StringSink(Decoded)));	key = Decoded;	key = key.substr(5);//去除首位5个字符	Decoded.clear();	DecryptPass((char*)key.c_str(), enc_value, 2048);	_snprintf_s(enc_value_a, sizeof(enc_value_a), _TRUNCATE, "%S", enc_value);	key = enc_value_a;	StringSource((BYTE*)key.c_str(),key.size(), true,		new HexEncoder(		new StringSink(Encoded)));	key = Encoded;	Encoded.clear();	//KEY解密完毕 开始处理Nonce 也就是IV	iv =iv.substr(3,12);	StringSource((BYTE*)iv.c_str(), iv.size(), true,		new HexEncoder(		new StringSink(Encoded)));	iv = Encoded;	Encoded.clear();	//---------------------------------------------------------//	//开始处理chiper	if (chiper.size() < 30){ return "wu xiao zi fu chuan....."; }	StringSource((BYTE*)chiper.c_str(), chiper.size(), true,		new HexEncoder(		new StringSink(Encoded)));	chiper = Encoded;	Encoded.clear();	chiper = chiper.substr(30);//因为是HEX 占了2个字节	//---------------------------------------------------------//	//进行AES_GCM	try	{		StringSource((BYTE*)iv.c_str(), iv.size(), true,			new HexDecoder(			new StringSink(Decoded)			) // HexEncoder			); // StringSource		iv = Decoded;		Decoded.clear();		StringSource((BYTE*)key.c_str(), key.size(), true,			new HexDecoder(			new StringSink(Decoded)			) // HexEncoder			); // StringSource		key = Decoded;		Decoded.clear();		StringSource((BYTE*)chiper.c_str(), chiper.size(), true,			new HexDecoder(			new StringSink(Decoded)			) // HexEncoder			); // StringSource		chiper = Decoded;		Decoded.clear();		cout << chiper << endl;		GCM< AES >::Decryption d;		d.SetKeyWithIV((BYTE*)key.c_str(), key.size(), (BYTE*)iv.c_str(), iv.size());		StringSource s(chiper, true,			new AuthenticatedDecryptionFilter(d,			new StringSink(recovered)			) // StreamTransformationFilter			); // StringSource		cout << "recovered text: " << recovered << endl;	}	catch (const CryptoPP::Exception& e)	{		cerr << e.what() << endl;		//exit(1);	}	return recovered;}

先base64解码一下 。

key = GetEncryptKEY();	StringSource((BYTE*)key.c_str(), key.size(), true,		new Base64Decoder(		new StringSink(Decoded)));	key = Decoded;	key = key.substr(5);//去除首位5个字符	Decoded.clear();

如此可以得到这一样一个字符串 。

C++解密Chrome80版本数据库的方法示例代码

这是没有去除字符的情况下,这个时候去除之后 即祛除了首位的DPAPI 如此便获得了一个初步解密的KEY。但在这之后,我们还需要对这个KEY做一次解密,因为这个时候的KEY还不能真正算是解密的KEY 他还需要进行一次DPAPI解密 。

DPAPI的解密函数部分代码如下:

DATA_BLOB input; input.pbData = (BYTE*)(cryptData);	DATA_BLOB output;	DWORD blen;	for(blen=128; blen<=2048; blen+=16) { input.cbData = blen;		if (CryptUnprotectData(&input, NULL, NULL, NULL, NULL, 0, &output))			break;	}	if (blen>=2048)		return 0;	CHAR *decrypted = (CHAR *)malloc(clearSize);	if (!decrypted) {		LocalFree(output.pbData);		return 0;	}	memset(decrypted, 0, clearSize);	memcpy(decrypted, output.pbData, (clearSize < output.cbData) ? clearSize - 1 : output.cbData);	_snwprintf_s(clearData, clearSize, _TRUNCATE, L"%S", decrypted);	free(decrypted);	LocalFree(output.pbData);	return 1;

在解密之后我们可以得到:

C++解密Chrome80版本数据库的方法示例代码

然后我们对加密字符串进行处理,取出iv和chiper。再使用aes-gcm解密即可.

iv =iv.substr(3,12);	StringSource((BYTE*)iv.c_str(), iv.size(), true,		new HexEncoder(		new StringSink(Encoded)));	iv = Encoded;	Encoded.clear();	//---------------------------------------------------------//	//开始处理chiper	if (chiper.size() < 30){ return "wu xiao zi fu chuan....."; }	StringSource((BYTE*)chiper.c_str(), chiper.size(), true,		new HexEncoder(		new StringSink(Encoded)));	chiper = Encoded;	Encoded.clear();

解密 。

try	{		StringSource((BYTE*)iv.c_str(), iv.size(), true,			new HexDecoder(			new StringSink(Decoded)			) // HexEncoder			); // StringSource		iv = Decoded;		Decoded.clear();		StringSource((BYTE*)key.c_str(), key.size(), true,			new HexDecoder(			new StringSink(Decoded)			) // HexEncoder			); // StringSource		key = Decoded;		Decoded.clear();		StringSource((BYTE*)chiper.c_str(), chiper.size(), true,			new HexDecoder(			new StringSink(Decoded)			) // HexEncoder			); // StringSource		chiper = Decoded;		Decoded.clear();		cout << chiper << endl;		GCM< AES >::Decryption d;		d.SetKeyWithIV((BYTE*)key.c_str(), key.size(), (BYTE*)iv.c_str(), iv.size());		StringSource s(chiper, true,			new AuthenticatedDecryptionFilter(d,			new StringSink(recovered)			) // StreamTransformationFilter			); // StringSource		cout << "recovered text: " << recovered << endl;	}	catch (const CryptoPP::Exception& e)	{		cerr << e.what() << endl;		//exit(1);	}	return recovered;

最终献上Demo源码 。

// Chrome80解密Demo.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <string>#include <fstream>#include <iostream>/*********************************\加密库头存放在这\*********************************/#include "cryptopp\base64.h"using CryptoPP::Base64Decoder;using CryptoPP::Base64Encoder;#include "cryptopp/hex.h"using CryptoPP::HexEncoder;using CryptoPP::HexDecoder;#include "cryptopp/filters.h"using CryptoPP::StringSink;using CryptoPP::StringSource;using CryptoPP::AuthenticatedEncryptionFilter;using CryptoPP::AuthenticatedDecryptionFilter;#include "cryptopp/aes.h"using CryptoPP::AES;#include "cryptopp/gcm.h"using CryptoPP::GCM;#include "cryptopp/secblock.h"using CryptoPP::SecByteBlock;/*********************************\加密库头加载完毕\*********************************/using namespace std;#pragma comment(lib,"userenv.lib")#pragma comment(lib,"cryptlib.lib")#pragma comment(lib,"Crypt32.lib")//RFBBUEkBAAAA0Iyd3wEV0RGMegDAT8KX6wEAAAAFBcVfgeqrR6TWICu+11nQAAAAAAIAAAAAABBmAAAAAQAAIAAAAJxLse8lqGAP4o493iTyljEUUF9y76AAoprRgHJwesCyAAAAAA6AAAAAAgAAIAAAAFtTd4B22Ky/x2LVgQUSaKku2rCvsv+FiMFj+lGN8LmZMAAAANBlkfPhV/zVaMALHr0gK6dM7nFsfNTv6bfFKCyKbIorgbBnjfKp+K5MVz9iizYVs0AAAACihmRGBIQ6oDkgjzCk+9AhePof4eUhB98pb7UlbGgssV2fnGRrBYQHW8Gyyp9W4pojyn9J7GQixtdCIPBwEW92//763130954DBA6D89BBAB2FF4A4460AEA7B823BA5BAF01B2B5E2CECDED5855F6E1E7B57946599C6ACD7D60F4B03FC11D5F7C6A39FA59FBF33D7int DecryptPass(CHAR *cryptData, WCHAR *clearData, UINT clearSize){	DATA_BLOB input;	input.pbData = (BYTE*)(cryptData);	DATA_BLOB output;	DWORD blen;	for (blen = 128; blen <= 2048; blen += 16) {		input.cbData = blen;		if (CryptUnprotectData(&input, NULL, NULL, NULL, NULL, 0, &output))			break;	}	if (blen >= 2048)		return 0;	CHAR *decrypted = (CHAR *)malloc(clearSize);	if (!decrypted) {		LocalFree(output.pbData);		return 0;	}	memset(decrypted, 0, clearSize);	memcpy(decrypted, output.pbData, (clearSize < output.cbData) ? clearSize - 1 : output.cbData);	_snwprintf_s(clearData, clearSize, _TRUNCATE, L"%S", decrypted);	free(decrypted);	LocalFree(output.pbData);	return 1;}int _tmain(int argc, _TCHAR* argv[]){	string EncryptValue;	string key, iv, chiper, recovered;	string Decoded, Encoded;	WCHAR enc_value[2048];	char enc_value_a[2048];	ZeroMemory(enc_value, sizeof(enc_value));	ZeroMemory(enc_value_a, sizeof(enc_value_a));	cout << "请输入EncryptKEY[BASE64]:" << endl;	cin >> key;	cout << "请输入EncryptValue[HEX]:" << endl;	cin >> EncryptValue;	cout << "<---------------开始解密流程--------------->\r\n" << endl;	//开始赋值	iv = EncryptValue;	chiper = EncryptValue;	StringSource((BYTE*)key.c_str(), key.size(), true,		new Base64Decoder(		new StringSink(Decoded)));	key = Decoded;	Decoded.clear();	cout << "1:EncryptKEY 进行Base64解密:\r\n" << key << "\r\n" << endl;	key = key.substr(5);	cout << "2:EncryptKEY 去除首5个字符:\r\n" << key << "\r\n" << endl;	DecryptPass((char*)key.c_str(), enc_value, 2048);	_snprintf_s(enc_value_a, sizeof(enc_value_a), _TRUNCATE, "%S", enc_value);	key = enc_value_a;	cout << "3:EncryptKEY 进行DPAPI解密:\r\n" << key << "\r\n" << endl;	StringSource((BYTE*)key.c_str(), key.size(), true,		new HexEncoder(		new StringSink(Encoded)));	key = Encoded;	Encoded.clear();	cout << "4:对已经通过DPAPI的EncryptKEY 进行HEX编码:\r\n" << key << "\r\n" << endl;	StringSource((BYTE*)iv.c_str(), iv.size(), true,		new HexDecoder(		new StringSink(Decoded)));	iv = Decoded;	Decoded.clear();	iv=iv.substr(3, 15);	StringSource((BYTE*)iv.c_str(), iv.size(), true,		new HexEncoder(		new StringSink(Encoded)));	iv = Encoded;	Encoded.clear();	iv = iv.substr(0,iv.size()-6);	cout << "5:对要解密的字符串进行反HEX编码 也就是解码 并且截取之后再次 进行HEX编码 赋值给iv:\r\n" << iv << "\r\n" << endl;	chiper = chiper.substr(30);	cout << "6:对要解密的字符串进行截取末尾15:\r\n" << chiper << "\r\n" << endl;	try	{		StringSource((BYTE*)iv.c_str(), iv.size(), true,			new HexDecoder(			new StringSink(Decoded)			) // HexEncoder			); // StringSource		iv = Decoded;		Decoded.clear();		StringSource((BYTE*)key.c_str(), key.size(), true,			new HexDecoder(			new StringSink(Decoded)			) // HexEncoder			); // StringSource		key = Decoded;		Decoded.clear();		StringSource((BYTE*)chiper.c_str(), chiper.size(), true,			new HexDecoder(			new StringSink(Decoded)			) // HexEncoder			); // StringSource		chiper = Decoded;		Decoded.clear();		cout << chiper << endl;		GCM< AES >::Decryption d;		d.SetKeyWithIV((BYTE*)key.c_str(), key.size(), (BYTE*)iv.c_str(), iv.size());		StringSource s(chiper, true,			new AuthenticatedDecryptionFilter(d,			new StringSink(recovered)			) // StreamTransformationFilter			); // StringSource		cout << "7:最终解密文本为:\r\n" << recovered << "\r\n" << endl;	}	catch (const CryptoPP::Exception& e)	{		cerr << e.what() << endl;		//exit(1);	}	system("pause");	return 0;}

附上一张解密靓照 。

C++解密Chrome80版本数据库的方法示例代码

核对下解密的密文是否正确 。

C++解密Chrome80版本数据库的方法示例代码

到此这篇关于C++解密Chrome80版本数据库的方法示例代码的文章就介绍到这了,更多相关c++ 解密Chrome80数据库内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。

原文链接:https://www.freebuf.com/sectool/232490.html 。

最后此篇关于C++解密Chrome80版本数据库的方法示例代码的文章就讲到这里了,如果你想了解更多关于C++解密Chrome80版本数据库的方法示例代码的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com