Skip to content

Instantly share code, notes, and snippets.

@senior-sigan
Last active April 22, 2023 02:56
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save senior-sigan/4dfe9008dddd8bb65d8f to your computer and use it in GitHub Desktop.
Save senior-sigan/4dfe9008dddd8bb65d8f to your computer and use it in GitHub Desktop.
Decrypt Chrome Login Data file that contains user's passwords.
require 'sqlite3'
require 'ffi' # extension for programmatically loading dynamic libraries
# Based on https://code.google.com/p/chromium/codesearch#chromium/src/components/os_crypt/os_crypt_win.cc
# Decrypt Chrome Login Data file that contains user passwords
module DPAPI
extend FFI::Library
ffi_lib 'crypt32' # import crypt32 to use winapi function CryptUnprotectData
class DecryptError < StandardError; end
=begin
typedef struct _CRYPTOAPI_BLOB {
DWORD cbData;
BYTE *pbData;
} DATA_BLOB;
=end
class DataBlob < FFI::Struct
layout :cbData, :uint32,
:pbData, :pointer
end
=begin
BOOL WINAPI CryptUnprotectData(
_In_ DATA_BLOB *pDataIn,
_Out_opt_ LPWSTR *ppszDataDescr,
_In_opt_ DATA_BLOB *pOptionalEntropy,
_Reserved_ PVOID pvReserved,
_In_opt_ CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct,
_In_ DWORD dwFlags,
_Out_ DATA_BLOB *pDataOut
);
=end
attach_function :CryptUnprotectData,
[:pointer, :pointer, :pointer, :pointer, :pointer, :uint32, :pointer],
:int32
def self.decrypt(ciphertext)
plaintext_blob = DataBlob.new
ciphertext_blob = DataBlob.new
ciphertext_blob[:cbData] = ciphertext.bytesize
ciphertext_blob[:pbData] = FFI::MemoryPointer.from_string(ciphertext)
#Contains a password or other additional entropy
#used when the data was encrypted. This parameter can be set to NULL
entropy = DataBlob.new
pwd = ''
entropy[:cbData] = pwd.bytesize
entropy[:pbData] = FFI::MemoryPointer.from_string(pwd)
raise DecryptError if CryptUnprotectData(
ciphertext_blob, nil, entropy, nil, nil, 0, plaintext_blob).zero?
plaintext_blob[:pbData].get_bytes(0, plaintext_blob[:cbData])
end
end
db = SQLite3::Database.new 'Login Data' # Load sqlite file
rows = db.execute('SELECT username_value, password_value FROM logins')
pwd=rows.map do |enc_pwd|
{enc_pwd.first => DPAPI::decrypt(enc_pwd.last)}
end
puts pwd # Show all decrypted login/password pairs
@Hatsouky
Copy link

and how to use this ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment