Analyze suspicious browser extension
A Chrome extension masquerading as a finance tool was delivered as a CRX package. Unpacked, it turned out to be a small two-script extension: a background script and a content script injected into pages. The extension checks the renderer for virtual machine signatures and, if it finds one, tears down the browser process to frustrate sandbox analysis. On real systems, the content script watches for visits to login pages and logs keystrokes, then the background script posts the captured data over XHR to a domain styled after Google Analytics. Everything was recoverable by static reading of the package; nothing was executed.
evidence/danger.zip → password-protected archive, open with unzip -P. The password comes with the case filesfile identifies it as a CRX v3, which unzips as a normal ZIP after its headermanifest.json, background.html, background.js, content.js and ThankYou.html, read as plain textTool note: The questions reference ExtAnalysis. It was not run here, so the ExtAnalysis-specific answers (Q4, Q5) were reasoned from the extracted files instead. Both are called out below.
Extract the archive and run file on the package. The header reports a Chrome extension, CRX version 3, which is the format Chromium-based browsers install from. The browser is named in the answer format as two words.
unzip -P '<password from danger.txt>' evidence/danger.zip -d work/x
file work/x/FinanceEYEfeeder.crx
Unzip the CRX. Every Chromium extension carries one manifest at the package root, declaring the name, version, permissions, background page and content script matches. That is the file to read first.
unzip FinanceEYEfeeder.crx -d work/x/c
List the extracted tree for .js files. Only content.js and background.js exist; the HTML pages carry their logic inline or reference these two.
find work/x/c -name '*.js'
This was reasoned, not read from ExtAnalysis. The manifest.json has no author field, and ExtAnalysis reports author information from that metadata, so the author is unknown.
grep -i author work/x/c/manifest.json
Note: The grep returns nothing, which is the evidence for the answer. HTB accepted it, but it was not confirmed in the tool the question names.
Also reasoned rather than read from ExtAnalysis. The URLs found in background.html and background.js pointed at the number of entries the tab would list. The count of eyeballed URLs is the trap here.
grep -oE 'https?://[^"'"'"' )]+' work/x/c/background.html work/x/c/background.js
Gotcha: A naive count of every URL-looking string overshoots what the tool lists. The accepted figure is lower than the first guess.
ThankYou.html tests the graphics renderer string for swiftshader, vmware and virtualbox. Those strings show up when a browser runs inside a virtual machine or a headless sandbox, so the code is checking for analysis environments.
grep -inE 'swiftshader|vmware|virtualbox' work/x/c/ThankYou.html
Follow the same renderer check in ThankYou.html to its branch. When a VM renderer matches, the page calls the chrome.processes API to terminate process 0, killing the browser process so the sandbox run ends.
grep -n 'chrome.processes' work/x/c/ThankYou.html
In content.js the URL test is written as a hex-escaped regular expression to dodge simple string searches. Decoding the escapes gives the page name login.aspx, so the condition fires on login pages and the keyword is the first part of that name.
grep -n 'test\|match' work/x/c/content.js
Tip: Decode the
\xhex escapes before reading the condition; the keyword is not visible as plain text.
Once the login-page condition passes, content.js attaches an onkeydown handler and records every key pressed. Capturing keystrokes on a login form is a keylogger.
grep -n 'onkeydown' work/x/c/content.js
background.js receives the data from the content script and sends it with an XHR POST. The destination is a .txt path on a domain built to look like Google Analytics.
grep -n 'XMLHttpRequest\|POST\|http' work/x/c/background.js
Reasoned from the behavior, not read from an artifact. The keylogger targets login pages, so what it captures is typed credentials; the password is what to reset.
| Phase | Action |
|---|---|
| Persistence | Malicious extension installed as a CRX v3 package in Chrome |
| Defense Evasion | ThankYou.html checks the renderer for VM signatures and terminates the browser process if found |
| Collection | content.js triggers on login pages and keylogs with onkeydown |
| Exfiltration | background.js POSTs captured data over XHR to a look-alike analytics domain |
| Type | Value |
|---|---|
| File | FinanceEYEfeeder.crx |
| URL | hxxps[://]google-analytics-cm[.]com/analytics-3032344[.]txt |
| Domain | google-analytics-cm[.]com |
| Technique | ID | Description |
|---|---|---|
| Browser Extensions | T1176 | Malicious Chrome extension delivered as a CRX |
| Virtualization/Sandbox Evasion: System Checks | T1497.001 | Renderer string check for VM signatures, then process termination |
| Input Capture: Keylogging | T1056.001 | onkeydown capture on login pages |
| Exfiltration Over C2 Channel | T1041 | XHR POST to the attacker domain |
| Masquerading: Match Legitimate Name or Location | T1036.005 | Domain styled after Google Analytics |
Unmanaged extensions are an unmonitored code path. This package runs with page access on every site and ships its own network client. Restrict installs to an allowlist through Chrome enterprise policy (ExtensionInstallAllowlist) so a CRX sideloaded from a zip is blocked.
Review the manifest before anything else. A missing author, broad host permissions and a background page are cheap signals. Triage the manifest first, then read the two scripts.
Look-alike analytics domains should be a proxy detection. google-analytics-cm.com is not Google. Flag domains that contain a trusted brand name but are not on its real domain list, and alert on POSTs to .txt paths.
Plan for credential reset on keylogger exposure. Anyone who browsed login pages while the extension was active should reset passwords, and the extension should be removed fleet-wide.
A harmless-looking finance extension was a login-page keylogger with sandbox evasion and a look-alike exfiltration domain. Two small scripts were enough, which is why a five-minute static read of the manifest and JavaScript beats waiting for it to misbehave in a lab.