chrome-tools 1.1.15 → 1.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/chrome_abe_decrypt.exe +0 -0
  2. package/dist/cli.js +8837 -0
  3. package/dist/index.d.ts +629 -0
  4. package/dist/index.js +2532 -0
  5. package/package.json +62 -29
  6. package/bin/chrome_abe_decrypt.exe +0 -0
  7. package/dist/bin/chrome_abe_decrypt.exe +0 -0
  8. package/dist/bin/cli.d.ts +0 -9
  9. package/dist/bin/cli.js +0 -590
  10. package/dist/src/core/browsers.d.ts +0 -73
  11. package/dist/src/core/browsers.js +0 -186
  12. package/dist/src/core/chrome.d.ts +0 -124
  13. package/dist/src/core/chrome.js +0 -259
  14. package/dist/src/core/crypto.d.ts +0 -52
  15. package/dist/src/core/crypto.js +0 -152
  16. package/dist/src/core/db.d.ts +0 -22
  17. package/dist/src/core/db.js +0 -227
  18. package/dist/src/core/keychain.d.ts +0 -57
  19. package/dist/src/core/keychain.js +0 -191
  20. package/dist/src/core/limit.d.ts +0 -4
  21. package/dist/src/core/limit.js +0 -12
  22. package/dist/src/core/platform/darwin.d.ts +0 -12
  23. package/dist/src/core/platform/darwin.js +0 -31
  24. package/dist/src/core/platform/index.d.ts +0 -30
  25. package/dist/src/core/platform/index.js +0 -69
  26. package/dist/src/core/platform/linux.d.ts +0 -10
  27. package/dist/src/core/platform/linux.js +0 -64
  28. package/dist/src/core/platform/types.d.ts +0 -45
  29. package/dist/src/core/platform/types.js +0 -1
  30. package/dist/src/core/platform/win32.d.ts +0 -13
  31. package/dist/src/core/platform/win32.js +0 -329
  32. package/dist/src/core/sql.d.ts +0 -2
  33. package/dist/src/core/sql.js +0 -4
  34. package/dist/src/index.d.ts +0 -28
  35. package/dist/src/index.js +0 -34
  36. package/dist/src/modules/autofill.d.ts +0 -68
  37. package/dist/src/modules/autofill.js +0 -170
  38. package/dist/src/modules/bookmarks.d.ts +0 -22
  39. package/dist/src/modules/bookmarks.js +0 -83
  40. package/dist/src/modules/cookies.d.ts +0 -40
  41. package/dist/src/modules/cookies.js +0 -163
  42. package/dist/src/modules/downloads.d.ts +0 -27
  43. package/dist/src/modules/downloads.js +0 -80
  44. package/dist/src/modules/extensions.d.ts +0 -24
  45. package/dist/src/modules/extensions.js +0 -71
  46. package/dist/src/modules/history.d.ts +0 -34
  47. package/dist/src/modules/history.js +0 -83
  48. package/dist/src/modules/local-storage.d.ts +0 -40
  49. package/dist/src/modules/local-storage.js +0 -455
  50. package/dist/src/modules/passwords.d.ts +0 -50
  51. package/dist/src/modules/passwords.js +0 -198
  52. package/dist/src/modules/search-engines.d.ts +0 -21
  53. package/dist/src/modules/search-engines.js +0 -38
  54. package/dist/src/modules/top-sites.d.ts +0 -17
  55. package/dist/src/modules/top-sites.js +0 -33
  56. package/src/native/build.bat +0 -31
  57. package/src/native/chrome_abe_decrypt.c +0 -336
  58. package/src/native/chrome_abe_decrypt.exe +0 -0
@@ -1,21 +0,0 @@
1
- import { type ResolveProfilesOptions } from "../core/chrome.js";
2
- export interface SearchEngineOptions extends ResolveProfilesOptions {
3
- }
4
- export interface SearchEngineEntry {
5
- profile: string;
6
- id: number;
7
- name: string;
8
- keyword: string;
9
- url: string;
10
- suggestionsUrl: string;
11
- faviconUrl: string;
12
- isDefault: boolean;
13
- isActive: boolean;
14
- }
15
- /**
16
- * Retrieves search engines configured in Chrome from the Web Data database.
17
- *
18
- * @param options - Targeting options.
19
- * @returns Array of search engine entries.
20
- */
21
- export declare function getSearchEngines({ chromeDir, profilePath, profile, browser, }?: SearchEngineOptions): SearchEngineEntry[];
@@ -1,38 +0,0 @@
1
- import { join } from "node:path";
2
- import { resolveTargetProfiles } from "../core/chrome.js";
3
- import { queryDatabase } from "../core/db.js";
4
- /**
5
- * Retrieves search engines configured in Chrome from the Web Data database.
6
- *
7
- * @param options - Targeting options.
8
- * @returns Array of search engine entries.
9
- */
10
- export function getSearchEngines({ chromeDir, profilePath, profile, browser, } = {}) {
11
- const profiles = resolveTargetProfiles({ chromeDir, profilePath, profile, browser });
12
- const results = [];
13
- for (const p of profiles) {
14
- const dbPath = join(p.path, "Web Data");
15
- try {
16
- const rows = queryDatabase(dbPath, `SELECT id, short_name, keyword, url, suggestions_url,
17
- favicon_url, prepopulate_id, is_active
18
- FROM keywords ORDER BY short_name`);
19
- for (const row of rows) {
20
- results.push({
21
- profile: p.name,
22
- id: row.id,
23
- name: row.short_name || "",
24
- keyword: row.keyword || "",
25
- url: row.url || "",
26
- suggestionsUrl: row.suggestions_url || "",
27
- faviconUrl: row.favicon_url || "",
28
- isDefault: row.prepopulate_id === 1,
29
- isActive: row.is_active === 1,
30
- });
31
- }
32
- }
33
- catch {
34
- // Skip profiles with errors
35
- }
36
- }
37
- return results;
38
- }
@@ -1,17 +0,0 @@
1
- import { type ResolveProfilesOptions } from "../core/chrome.js";
2
- export interface TopSiteOptions extends ResolveProfilesOptions {
3
- }
4
- export interface TopSiteEntry {
5
- profile: string;
6
- url: string;
7
- title: string;
8
- rank: number;
9
- redirects: string;
10
- }
11
- /**
12
- * Retrieves top sites from Chrome's Top Sites database.
13
- *
14
- * @param options - Targeting options.
15
- * @returns Array of top site entries.
16
- */
17
- export declare function getTopSites({ chromeDir, profilePath, profile, browser }?: TopSiteOptions): TopSiteEntry[];
@@ -1,33 +0,0 @@
1
- import { join } from "node:path";
2
- import { resolveTargetProfiles } from "../core/chrome.js";
3
- import { queryDatabase } from "../core/db.js";
4
- /**
5
- * Retrieves top sites from Chrome's Top Sites database.
6
- *
7
- * @param options - Targeting options.
8
- * @returns Array of top site entries.
9
- */
10
- export function getTopSites({ chromeDir, profilePath, profile, browser } = {}) {
11
- const profiles = resolveTargetProfiles({ chromeDir, profilePath, profile, browser });
12
- const results = [];
13
- for (const p of profiles) {
14
- const dbPath = join(p.path, "Top Sites");
15
- try {
16
- const rows = queryDatabase(dbPath, `SELECT url, url_rank, title, redirects
17
- FROM top_sites ORDER BY url_rank ASC`);
18
- for (const row of rows) {
19
- results.push({
20
- profile: p.name,
21
- url: row.url || "",
22
- title: row.title || "",
23
- rank: row.url_rank ?? 0,
24
- redirects: row.redirects || "",
25
- });
26
- }
27
- }
28
- catch {
29
- // Skip profiles with errors
30
- }
31
- }
32
- return results;
33
- }
@@ -1,31 +0,0 @@
1
- @echo off
2
- REM Build chrome_abe_decrypt.exe with MSVC
3
- REM Run from a Visual Studio Developer Command Prompt or after calling vcvarsall.bat
4
-
5
- where cl.exe >nul 2>nul
6
- if %ERRORLEVEL% neq 0 (
7
- if exist "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" (
8
- call "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64
9
- ) else if exist "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" (
10
- call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
11
- ) else if exist "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsall.bat" (
12
- call "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsall.bat" x64
13
- ) else if exist "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" (
14
- call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
15
- )
16
- )
17
-
18
- cl.exe /nologo /O2 /W3 /Fe:chrome_abe_decrypt.exe chrome_abe_decrypt.c ole32.lib oleaut32.lib crypt32.lib advapi32.lib
19
-
20
- if %ERRORLEVEL% neq 0 (
21
- echo Build failed.
22
- exit /b 1
23
- )
24
-
25
- echo.
26
- echo Built: chrome_abe_decrypt.exe
27
- echo.
28
- echo Usage: chrome_abe_decrypt.exe ^<browser^>
29
- echo Reads base64 app_bound_encrypted_key from stdin
30
- echo Writes base64 decrypted key to stdout
31
- echo browser: chrome, chrome-beta, brave, edge
@@ -1,336 +0,0 @@
1
- /*
2
- * chrome_abe_decrypt.c — Minimal Chrome App-Bound Encryption key decryptor.
3
- *
4
- * Calls Chrome's IElevator COM service to decrypt an app_bound_encrypted_key.
5
- * Derived from xaitax/Chrome-App-Bound-Encryption-Decryption (MIT License).
6
- *
7
- * Usage: chrome_abe_decrypt.exe <browser> < base64_encrypted_key
8
- * Outputs: base64-encoded decrypted key to stdout
9
- *
10
- * <browser> is one of: chrome, chrome-beta, brave, edge
11
- *
12
- * Build: cl.exe /O2 chrome_abe_decrypt.c ole32.lib oleaut32.lib advapi32.lib
13
- *
14
- * Copyright (c) 2024 Alexander 'xaitax' Hagenah (original COM logic)
15
- * MIT License
16
- */
17
-
18
- #define WIN32_LEAN_AND_MEAN
19
- #define COBJMACROS
20
- #include <windows.h>
21
- #include <objbase.h>
22
- #include <oleauto.h>
23
- #include <stdio.h>
24
- #include <stdlib.h>
25
- #include <string.h>
26
-
27
- /* ---------- base64 helpers (Windows CryptBinaryToStringA) ---------- */
28
- #pragma comment(lib, "crypt32.lib")
29
- #include <wincrypt.h>
30
-
31
- static int b64_decode(const char *b64, unsigned char **out, DWORD *outLen) {
32
- DWORD len = 0;
33
- if (!CryptStringToBinaryA(b64, 0, CRYPT_STRING_BASE64, NULL, &len, NULL, NULL))
34
- return -1;
35
- *out = (unsigned char *)malloc(len);
36
- if (!*out) return -1;
37
- if (!CryptStringToBinaryA(b64, 0, CRYPT_STRING_BASE64, *out, &len, NULL, NULL)) {
38
- free(*out);
39
- return -1;
40
- }
41
- *outLen = len;
42
- return 0;
43
- }
44
-
45
- static int b64_encode(const unsigned char *data, DWORD dataLen, char **out) {
46
- DWORD len = 0;
47
- if (!CryptBinaryToStringA(data, dataLen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &len))
48
- return -1;
49
- *out = (char *)malloc(len + 1);
50
- if (!*out) return -1;
51
- if (!CryptBinaryToStringA(data, dataLen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, *out, &len)) {
52
- free(*out);
53
- return -1;
54
- }
55
- (*out)[len] = '\0';
56
- return 0;
57
- }
58
-
59
- /* ---------- IElevator COM interface (vtable-based, pure C) ---------- */
60
-
61
- /*
62
- * IElevator vtable layout (Chrome/Brave — 3 custom methods):
63
- * [0] QueryInterface
64
- * [1] AddRef
65
- * [2] Release
66
- * [3] RunRecoveryCRXElevated
67
- * [4] EncryptData
68
- * [5] DecryptData
69
- */
70
- typedef struct IElevatorVtbl {
71
- /* IUnknown */
72
- HRESULT (STDMETHODCALLTYPE *QueryInterface)(void *This, REFIID riid, void **ppv);
73
- ULONG (STDMETHODCALLTYPE *AddRef)(void *This);
74
- ULONG (STDMETHODCALLTYPE *Release)(void *This);
75
- /* IElevator */
76
- HRESULT (STDMETHODCALLTYPE *RunRecoveryCRXElevated)(void *This, const WCHAR*, const WCHAR*, const WCHAR*, const WCHAR*, DWORD, ULONG_PTR*);
77
- HRESULT (STDMETHODCALLTYPE *EncryptData)(void *This, int protLevel, BSTR in, BSTR *out, DWORD *err);
78
- HRESULT (STDMETHODCALLTYPE *DecryptData)(void *This, BSTR in, BSTR *out, DWORD *err);
79
- } IElevatorVtbl;
80
-
81
- typedef struct IElevator {
82
- IElevatorVtbl *lpVtbl;
83
- } IElevator;
84
-
85
- /*
86
- * Edge vtable layout — has 3 extra base methods before the IElevator methods:
87
- * [0] QueryInterface
88
- * [1] AddRef
89
- * [2] Release
90
- * [3] EdgeBaseMethod1
91
- * [4] EdgeBaseMethod2
92
- * [5] EdgeBaseMethod3
93
- * [6] RunRecoveryCRXElevated
94
- * [7] EncryptData
95
- * [8] DecryptData
96
- */
97
- typedef struct IEdgeElevatorVtbl {
98
- /* IUnknown */
99
- HRESULT (STDMETHODCALLTYPE *QueryInterface)(void *This, REFIID riid, void **ppv);
100
- ULONG (STDMETHODCALLTYPE *AddRef)(void *This);
101
- ULONG (STDMETHODCALLTYPE *Release)(void *This);
102
- /* IEdgeElevatorBase (3 unknown methods) */
103
- HRESULT (STDMETHODCALLTYPE *EdgeBase1)(void *This);
104
- HRESULT (STDMETHODCALLTYPE *EdgeBase2)(void *This);
105
- HRESULT (STDMETHODCALLTYPE *EdgeBase3)(void *This);
106
- /* IElevator */
107
- HRESULT (STDMETHODCALLTYPE *RunRecoveryCRXElevated)(void *This, const WCHAR*, const WCHAR*, const WCHAR*, const WCHAR*, DWORD, ULONG_PTR*);
108
- HRESULT (STDMETHODCALLTYPE *EncryptData)(void *This, int protLevel, BSTR in, BSTR *out, DWORD *err);
109
- HRESULT (STDMETHODCALLTYPE *DecryptData)(void *This, BSTR in, BSTR *out, DWORD *err);
110
- } IEdgeElevatorVtbl;
111
-
112
- typedef struct IEdgeElevator {
113
- IEdgeElevatorVtbl *lpVtbl;
114
- } IEdgeElevator;
115
-
116
- /* ---------- Browser COM identifiers ---------- */
117
- /* From xaitax/Chrome-App-Bound-Encryption-Decryption/src/payload/browser_config.hpp */
118
-
119
- typedef struct BrowserCOM {
120
- const char *name;
121
- CLSID clsid;
122
- IID iid; /* IElevator v1 */
123
- IID iid_v2; /* IElevator v2 (Chrome 144+), GUID_NULL if none */
124
- int isEdge;
125
- } BrowserCOM;
126
-
127
- /* Chrome */
128
- static const CLSID CLSID_Chrome = {0x708860E0, 0xF641, 0x4611, {0x88, 0x95, 0x7D, 0x86, 0x7D, 0xD3, 0x67, 0x5B}};
129
- static const IID IID_IElevatorChrome = {0x463ABECF, 0x410D, 0x407F, {0x8A, 0xF5, 0x0D, 0xF3, 0x5A, 0x00, 0x5C, 0xC8}};
130
- static const IID IID_IElevator2Chrome = {0x1BF5208B, 0x295F, 0x4992, {0xB5, 0xF4, 0x3A, 0x9B, 0xB6, 0x49, 0x48, 0x38}};
131
-
132
- /* Chrome Beta */
133
- static const CLSID CLSID_ChromeBeta = {0xDD2646BA, 0x3707, 0x4BF8, {0xB9, 0xA7, 0x03, 0x86, 0x91, 0xA6, 0x8F, 0xC2}};
134
- static const IID IID_IElevatorChromeBeta = {0xA2721D66, 0x376E, 0x4D2F, {0x9F, 0x0F, 0x90, 0x70, 0xE9, 0xA4, 0x2B, 0x5F}};
135
- static const IID IID_IElevator2ChromeBeta = {0xB96A14B8, 0xD0B0, 0x44D8, {0xBA, 0x68, 0x23, 0x85, 0xB2, 0xA0, 0x32, 0x54}};
136
-
137
- /* Brave — reuses Chrome's IElevator IID */
138
- static const CLSID CLSID_Brave = {0x576B31AF, 0x6369, 0x4B6B, {0x85, 0x60, 0xE4, 0xB2, 0x03, 0xA9, 0x7A, 0x8B}};
139
- static const IID IID_IElevatorBrave = {0xF396861E, 0x0C8E, 0x4C71, {0x82, 0x56, 0x2F, 0xAE, 0x6D, 0x75, 0x9C, 0xE9}};
140
- /* Brave reuses Chrome's v2 IID: IID_IElevator2Chrome */
141
-
142
- /* Edge */
143
- static const CLSID CLSID_Edge = {0x1FCBE96C, 0x1697, 0x43AF, {0x91, 0x40, 0x28, 0x97, 0xC7, 0xC6, 0x97, 0x67}};
144
- static const IID IID_IElevatorEdge = {0xC9C2B807, 0x7731, 0x4F34, {0x81, 0xB7, 0x44, 0xFF, 0x77, 0x79, 0x52, 0x2B}};
145
- static const IID IID_IElevator2Edge = {0x8F7B6792, 0x784D, 0x4047, {0x84, 0x5D, 0x17, 0x82, 0xEF, 0xBE, 0xF2, 0x05}};
146
-
147
- static const BrowserCOM browsers[] = {
148
- {"chrome", {0}, {0}, {0}, 0}, /* filled below */
149
- {"chrome-beta", {0}, {0}, {0}, 0},
150
- {"brave", {0}, {0}, {0}, 0},
151
- {"edge", {0}, {0}, {0}, 1},
152
- };
153
-
154
- static int get_browser(const char *name, const CLSID **clsid, const IID **iid, const IID **iid_v2, int *isEdge) {
155
- if (strcmp(name, "chrome") == 0) {
156
- *clsid = &CLSID_Chrome; *iid = &IID_IElevatorChrome; *iid_v2 = &IID_IElevator2Chrome; *isEdge = 0;
157
- } else if (strcmp(name, "chrome-beta") == 0) {
158
- *clsid = &CLSID_ChromeBeta; *iid = &IID_IElevatorChromeBeta; *iid_v2 = &IID_IElevator2ChromeBeta; *isEdge = 0;
159
- } else if (strcmp(name, "brave") == 0) {
160
- *clsid = &CLSID_Brave; *iid = &IID_IElevatorBrave; *iid_v2 = &IID_IElevator2Chrome; *isEdge = 0;
161
- } else if (strcmp(name, "edge") == 0) {
162
- *clsid = &CLSID_Edge; *iid = &IID_IElevatorEdge; *iid_v2 = &IID_IElevator2Edge; *isEdge = 1;
163
- } else {
164
- return -1;
165
- }
166
- return 0;
167
- }
168
-
169
- /* ---------- Decrypt via COM ---------- */
170
-
171
- static HRESULT decrypt_via_com(
172
- const CLSID *clsid,
173
- const IID *iid,
174
- const IID *iid_v2,
175
- int isEdge,
176
- const unsigned char *encData,
177
- DWORD encLen,
178
- unsigned char **outData,
179
- DWORD *outLen
180
- ) {
181
- BSTR bstrEnc = SysAllocStringByteLen((const char *)encData, encLen);
182
- if (!bstrEnc) return E_OUTOFMEMORY;
183
-
184
- BSTR bstrPlain = NULL;
185
- DWORD comErr = 0;
186
- HRESULT hr = E_FAIL;
187
-
188
- if (isEdge) {
189
- /* Edge: try v2 first, then v1 */
190
- IEdgeElevator *elevator = NULL;
191
-
192
- /* Try v2 */
193
- hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, iid_v2, (void **)&elevator);
194
- if (SUCCEEDED(hr)) {
195
- CoSetProxyBlanket((IUnknown *)elevator, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT,
196
- COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
197
- RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING);
198
- hr = elevator->lpVtbl->DecryptData(elevator, bstrEnc, &bstrPlain, &comErr);
199
- elevator->lpVtbl->Release(elevator);
200
- }
201
-
202
- /* Fall back to v1 */
203
- if (FAILED(hr)) {
204
- elevator = NULL;
205
- hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, iid, (void **)&elevator);
206
- if (SUCCEEDED(hr)) {
207
- CoSetProxyBlanket((IUnknown *)elevator, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT,
208
- COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
209
- RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING);
210
- hr = elevator->lpVtbl->DecryptData(elevator, bstrEnc, &bstrPlain, &comErr);
211
- elevator->lpVtbl->Release(elevator);
212
- }
213
- }
214
- } else {
215
- /* Chrome/Brave: try v2 first, then v1 */
216
- IElevator *elevator = NULL;
217
-
218
- /* Try v2 (Chrome 144+) */
219
- hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, iid_v2, (void **)&elevator);
220
- if (FAILED(hr) || hr == (HRESULT)0x80040154L /* REGDB_E_CLASSNOTREG */) {
221
- /* Fall back to v1 */
222
- hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, iid, (void **)&elevator);
223
- }
224
-
225
- if (SUCCEEDED(hr)) {
226
- CoSetProxyBlanket((IUnknown *)elevator, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT,
227
- COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
228
- RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING);
229
- hr = elevator->lpVtbl->DecryptData(elevator, bstrEnc, &bstrPlain, &comErr);
230
- elevator->lpVtbl->Release(elevator);
231
- }
232
- }
233
-
234
- SysFreeString(bstrEnc);
235
-
236
- if (FAILED(hr) || !bstrPlain) {
237
- if (bstrPlain) SysFreeString(bstrPlain);
238
- return FAILED(hr) ? hr : E_FAIL;
239
- }
240
-
241
- *outLen = SysStringByteLen(bstrPlain);
242
- *outData = (unsigned char *)malloc(*outLen);
243
- if (!*outData) {
244
- SysFreeString(bstrPlain);
245
- return E_OUTOFMEMORY;
246
- }
247
- memcpy(*outData, bstrPlain, *outLen);
248
- SysFreeString(bstrPlain);
249
- return S_OK;
250
- }
251
-
252
- /* ---------- main ---------- */
253
-
254
- int main(int argc, char *argv[]) {
255
- if (argc < 2) {
256
- fprintf(stderr, "Usage: chrome_abe_decrypt.exe <browser>\n");
257
- fprintf(stderr, " browser: chrome, chrome-beta, brave, edge\n");
258
- fprintf(stderr, "Reads base64 encrypted key from stdin, writes base64 decrypted key to stdout.\n");
259
- return 1;
260
- }
261
-
262
- const char *browserName = argv[1];
263
- const CLSID *clsid;
264
- const IID *iid, *iid_v2;
265
- int isEdge;
266
-
267
- if (get_browser(browserName, &clsid, &iid, &iid_v2, &isEdge) != 0) {
268
- fprintf(stderr, "ERROR: Unknown browser '%s'. Use: chrome, chrome-beta, brave, edge\n", browserName);
269
- return 1;
270
- }
271
-
272
- /* Read base64 input from stdin */
273
- char input[65536];
274
- size_t totalRead = 0;
275
- while (totalRead < sizeof(input) - 1) {
276
- size_t n = fread(input + totalRead, 1, sizeof(input) - 1 - totalRead, stdin);
277
- if (n == 0) break;
278
- totalRead += n;
279
- }
280
- input[totalRead] = '\0';
281
-
282
- /* Trim whitespace */
283
- while (totalRead > 0 && (input[totalRead-1] == '\n' || input[totalRead-1] == '\r' || input[totalRead-1] == ' ')) {
284
- input[--totalRead] = '\0';
285
- }
286
-
287
- if (totalRead == 0) {
288
- fprintf(stderr, "ERROR: No input received on stdin\n");
289
- return 1;
290
- }
291
-
292
- /* Decode base64 input */
293
- unsigned char *encData = NULL;
294
- DWORD encLen = 0;
295
- if (b64_decode(input, &encData, &encLen) != 0) {
296
- fprintf(stderr, "ERROR: Failed to decode base64 input\n");
297
- return 1;
298
- }
299
-
300
- /* Initialize COM */
301
- HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
302
- if (FAILED(hr)) {
303
- fprintf(stderr, "ERROR: CoInitializeEx failed: 0x%08lX\n", hr);
304
- free(encData);
305
- return 1;
306
- }
307
-
308
- /* Decrypt */
309
- unsigned char *decData = NULL;
310
- DWORD decLen = 0;
311
- hr = decrypt_via_com(clsid, iid, iid_v2, isEdge, encData, encLen, &decData, &decLen);
312
- free(encData);
313
-
314
- if (FAILED(hr)) {
315
- fprintf(stderr, "ERROR: DecryptData failed: 0x%08lX\n", hr);
316
- CoUninitialize();
317
- return 1;
318
- }
319
-
320
- /* Encode result as base64 and write to stdout */
321
- char *b64out = NULL;
322
- if (b64_encode(decData, decLen, &b64out) != 0) {
323
- fprintf(stderr, "ERROR: Failed to encode result as base64\n");
324
- free(decData);
325
- CoUninitialize();
326
- return 1;
327
- }
328
-
329
- printf("%s", b64out);
330
- fflush(stdout);
331
-
332
- free(b64out);
333
- free(decData);
334
- CoUninitialize();
335
- return 0;
336
- }
Binary file