-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 6ee36af
Showing
13 changed files
with
322 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/target | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
[package] | ||
name = "chrome_cookie_decryptor" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[profile.release] | ||
opt-level = 'z' | ||
lto = true | ||
codegen-units = 1 | ||
panic = 'abort' | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
whoami = "1.4.0" | ||
rusqlite = { version = "0.29.0", features = ["bundled"] } | ||
serde_json = "1.0.96" | ||
base64 = "0.21.2" | ||
winapi = { version = "0.3.6", features = ["wingdi", "winnt", "winuser", "libloaderapi", "combaseapi", "objbase", "shobjidl", "winerror", "dpapi", "winbase"] } | ||
aes-gcm = "0.10.2" | ||
tokio = { version = "1.28.2", features = ["full"] } | ||
|
||
#[target.'cfg(target_os = "windows")'.features] | ||
#default = ["windows"] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
use aes_gcm::{ | ||
aead::{generic_array::GenericArray, Aead}, | ||
Aes256Gcm, KeyInit, | ||
}; | ||
|
||
// #[cfg(windows)] | ||
pub async fn decrypt_cookie(key: Vec<u8>, encrypted_value: Vec<u8>) -> String { | ||
let iv = &encrypted_value[3..15]; | ||
let encrypted_value = &encrypted_value[15..]; | ||
|
||
let cipher = Aes256Gcm::new(&GenericArray::from_slice(&key)); | ||
|
||
if let Ok(decrypted) = cipher.decrypt(GenericArray::from_slice(iv), encrypted_value) { | ||
if let Ok(decoded) = String::from_utf8(decrypted) { | ||
return decoded; | ||
} | ||
} | ||
|
||
return String::new(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
pub struct UserCookie { | ||
pub host_key: String, | ||
pub name: String, | ||
pub value: String, | ||
pub expires_utc: i64, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
use rusqlite::Connection; | ||
|
||
#[cfg(windows)] | ||
pub async fn take_cookies_from_db( | ||
username: String, | ||
) -> Result<Vec<(String, String, String, i64, Vec<u8>)>, rusqlite::Error> { | ||
let conn = match Connection::open(format!( | ||
r"C:\Users\{}\AppData\Local\Google\Chrome\User Data\Default\Network\Cookies", | ||
username | ||
)) { | ||
Ok(conn) => conn, | ||
Err(e) => return Err(e), | ||
}; | ||
|
||
let query = "SELECT host_key, name, value, expires_utc, encrypted_value FROM cookies"; | ||
|
||
let mut stmt = conn.prepare(&query).unwrap(); | ||
|
||
let cookie_iter = stmt | ||
.query_map([], |row| { | ||
Ok(( | ||
row.get::<_, String>(0)?, | ||
row.get::<_, String>(1)?, | ||
row.get::<_, String>(2)?, | ||
row.get::<_, i64>(3)?, | ||
row.get::<_, Vec<u8>>(4)?, | ||
)) | ||
})? | ||
.collect(); | ||
|
||
cookie_iter | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
use crate::async_writeln; | ||
#[cfg(windows)] | ||
use crate::encrypted_key::key::get_encryption_key; | ||
|
||
use std::{io::ErrorKind, sync::Arc}; | ||
use tokio::io::Error; | ||
use tokio::{fs::File, sync::Mutex}; | ||
|
||
use super::cookie_decryption::decrypt_cookie; | ||
use super::cookie_form::UserCookie; | ||
|
||
#[cfg(windows)] | ||
pub async fn handle_chrome_cookies( | ||
username: String, | ||
cookies: Vec<(String, String, String, i64, Vec<u8>)>, | ||
filepath: &str, | ||
) -> Result<(), Error> { | ||
let filepath = if filepath.is_empty() { "." } else { filepath }; | ||
let mut file = match File::create(format!("{}\\cookies.txt", filepath)).await { | ||
Ok(file) => file, | ||
Err(_e) => { | ||
return Err(tokio::io::Error::new( | ||
ErrorKind::Other, | ||
"Create folder failure", | ||
)); | ||
} | ||
}; | ||
async_writeln!(file, "# Netscape HTTP Cookie File").unwrap(); | ||
async_writeln!(file, "# http://curl.haxx.se/rfc/cookie_spec.html").unwrap(); | ||
async_writeln!(file, "# This is a generated file! Do not edit.").unwrap(); | ||
|
||
let cookie_iter = cookies; | ||
|
||
let key = tokio::task::spawn(async move { | ||
if let Ok(key) = get_encryption_key(username.clone()).await { | ||
key | ||
} else { | ||
vec![] | ||
} | ||
}) | ||
.await | ||
.unwrap(); | ||
|
||
if key.is_empty() { | ||
return Err(tokio::io::Error::new( | ||
ErrorKind::Other, | ||
"Key decryption error", | ||
)); | ||
} | ||
|
||
let shared_key = Arc::new(Mutex::new(key)); | ||
|
||
for cookie in cookie_iter { | ||
let shared_key_clone = Arc::clone(&shared_key); | ||
let decrypt_val = tokio::task::spawn(async move { | ||
let decrypt_val = | ||
decrypt_cookie(shared_key_clone.lock().await.to_vec(), cookie.4).await; | ||
decrypt_val | ||
}) | ||
.await | ||
.unwrap(); | ||
|
||
let cookie_val = if decrypt_val.is_empty() { | ||
cookie.2 | ||
} else { | ||
decrypt_val | ||
}; | ||
|
||
let cookies = UserCookie { | ||
host_key: cookie.0, | ||
name: cookie.1, | ||
value: cookie_val, | ||
expires_utc: (cookie.3 / 1_000_000) - 11644473600, | ||
}; | ||
|
||
async_writeln!( | ||
file, | ||
"{}\tTRUE\t/\tFALSE\t{}\t{}\t{}", | ||
cookies.host_key, | ||
cookies.expires_utc, | ||
cookies.name, | ||
cookies.value | ||
) | ||
.unwrap(); | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
pub mod cookie_decryption; | ||
pub mod cookie_form; | ||
pub mod get_raw_cookies; | ||
pub mod handle_raw_cookie; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
use std::ptr::null_mut; | ||
|
||
#[cfg(windows)] | ||
use winapi::um::{ | ||
dpapi::CryptUnprotectData, winbase::LocalFree, wincrypt::CRYPTOAPI_BLOB, winnt::HANDLE, | ||
}; | ||
|
||
#[cfg(windows)] | ||
pub async fn decrypt_data_key(mut unencoded_key: Vec<u8>) -> Result<Vec<u8>, String> { | ||
let mut data_in = CRYPTOAPI_BLOB { | ||
cbData: unencoded_key.len() as u32, | ||
pbData: unencoded_key.as_mut_ptr(), | ||
}; | ||
let mut data_out = CRYPTOAPI_BLOB { | ||
cbData: 0, | ||
pbData: null_mut(), | ||
}; | ||
unsafe { | ||
CryptUnprotectData( | ||
&mut data_in, | ||
null_mut(), | ||
null_mut(), | ||
null_mut(), | ||
null_mut(), | ||
0, | ||
&mut data_out, | ||
); | ||
|
||
let bytes = Vec::from_raw_parts( | ||
data_out.pbData, | ||
data_out.cbData as usize, | ||
data_out.cbData as usize, | ||
); | ||
LocalFree(data_out.pbData as HANDLE); | ||
Ok(bytes) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
use base64::engine::general_purpose; | ||
use base64::Engine; | ||
use serde_json::Value; | ||
use std::io::ErrorKind; | ||
use tokio::io::Error; | ||
use tokio::{fs::File, io::AsyncReadExt}; | ||
|
||
#[cfg(windows)] | ||
use super::decrypt_key::decrypt_data_key; | ||
|
||
#[cfg(windows)] | ||
pub async fn get_encryption_key(username: String) -> Result<Vec<u8>, Error> { | ||
let local_state_path = format!( | ||
r"C:\Users\{}\AppData\Local\Google\Chrome\User Data\Local State", | ||
username | ||
); | ||
let mut local_state_file = match File::open(local_state_path).await { | ||
Ok(file) => file, | ||
Err(e) => return Err(e), | ||
}; | ||
let mut local_state = String::new(); | ||
local_state_file.read_to_string(&mut local_state).await?; | ||
|
||
let local_state: Value = match serde_json::from_str(&local_state) { | ||
Ok(val) => val, | ||
Err(e) => return Err(e.into()), | ||
}; | ||
|
||
let encrypted_key = local_state["os_crypt"]["encrypted_key"].as_str().unwrap(); | ||
let encrypted_key = general_purpose::STANDARD.decode(encrypted_key).unwrap(); | ||
let unencoded_key = encrypted_key[5..].to_vec(); | ||
|
||
match decrypt_data_key(unencoded_key).await { | ||
Ok(key) => Ok(key), | ||
Err(e) => Err(tokio::io::Error::new(ErrorKind::Other, format!("{}", e))), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod decrypt_key; | ||
pub mod key; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
use std::{env::args, io::ErrorKind, path::Path}; | ||
|
||
#[cfg(windows)] | ||
use cookie::{get_raw_cookies::take_cookies_from_db, handle_raw_cookie::handle_chrome_cookies}; | ||
|
||
use tokio::io; | ||
|
||
mod cookie; | ||
mod encrypted_key; | ||
mod marco; | ||
|
||
#[cfg(not(windows))] | ||
fn main() { | ||
//* Only windows supported */ | ||
} | ||
|
||
#[cfg(windows)] | ||
#[tokio::main] | ||
async fn main() -> io::Result<()> { | ||
let args: Vec<String> = args().collect(); | ||
|
||
let mut path_to_folder: String = String::from(""); | ||
if let Some(path) = args.iter().nth(1) { | ||
if Path::is_dir(Path::new(path)) { | ||
path_to_folder = path.to_string() | ||
} | ||
} | ||
|
||
let os_username = whoami::username(); | ||
let chrome_cookies = match take_cookies_from_db(os_username.clone()).await { | ||
Ok(cookies) => cookies, | ||
Err(e) => { | ||
println!("HELP:\nTo solve this problem, you need to close your chrome browser\n"); | ||
return Err(tokio::io::Error::new(ErrorKind::Other, format!("{}", e))); | ||
} | ||
}; | ||
|
||
match handle_chrome_cookies(os_username.clone(), chrome_cookies, path_to_folder.as_str()).await | ||
{ | ||
Ok(()) => return Ok(()), | ||
Err(e) => { | ||
println!("{}", e); | ||
return Err(tokio::io::Error::new(ErrorKind::Other, format!("{}", e))); | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#[macro_export] | ||
macro_rules! async_writeln { | ||
($dst: expr) => { | ||
{ | ||
tokio::io::AsyncWriteExt::write_all(&mut $dst, b"\n").await | ||
} | ||
}; | ||
($dst: expr, $fmt: expr) => { | ||
{ | ||
use std::io::Write; | ||
let mut buf = Vec::<u8>::new(); | ||
writeln!(buf, $fmt).unwrap(); | ||
tokio::io::AsyncWriteExt::write_all(&mut $dst, &buf).await | ||
} | ||
}; | ||
($dst: expr, $fmt: expr, $($arg: tt)*) => { | ||
{ | ||
use std::io::Write; | ||
let mut buf = Vec::<u8>::new(); | ||
writeln!(buf, $fmt, $( $arg )*).unwrap(); | ||
tokio::io::AsyncWriteExt::write_all(&mut $dst, &buf).await | ||
} | ||
}; | ||
} |