Malicious Browser Extension Analysis: MSI installer -> malicious extension -> C2 domain hidden in crypto transactions
Overview
While randomly navigating, I found a very interesting malware, that while analyzing it didn’t create a traditional persistence on the machine via the registry, services, scheduled tasks, etc. Instead, it created a malicious extension on all of the user’s browsers. Additionally, the initial stage used a very interesting feature of the MSI file to execute a CustomAction from a DLL. This is a very in-depth analysis, so I hope you enjoy it!
Analysis
How It Started…Of course, with a fake captcha, but not the typical “WIN + R, then CTRL + V and Enter” kind. This one used an image captcha where each wrong selection redirected to a random site. However, selecting the correct image it redirects to the malmware:
The domain contains a password and a link to a MEGA file. (Interestingly, the MEGA link changed daily but always led to the same malware on diferent files.)
Extracting the ZIP file revealed another compressed file and an image with the password “2025”:
Extracting again, we found the MSI file setup.msi and a file named ._ with an unusually large size, likely to evade analysis in sandboxes with file size limits. Soon, we discovered that it initially installs “Task Coach” but bundles some suspicious additions.
MSI file
So lets start using orca to analyse the MSI file!
In MSI file it is possible to set custom actions, like execute binarys, scripts, call DLL functions, modify registry keys and etc. In our sample, we found a call to the function SendCollectedData from DataUploader.dll;
Here a example of DLL that permits MSI custom actions call its functions:
|
|
Even more suspicious with this CustomActionDatas:
Lets dump all files from the MSI and inspected DataUploader.dll. Other DLLs, like sqlite3.dll, also stood out, commonly used by stealers.
The custom action names were self-explanatory. Analyzing the DLL, we saw it used MsiSetPropertyW to set results in variables like HttpPostServerResponse and MsiGetPropertyW to retrieve values from custom action data (e.g., HttpPostUrl). (The DLL’s logic is complex, so this is a simplified summary.)
We can see that some arguments are being defined by the response of the uploded data to kantorpusatsbl[.]com[/]diagnostics[.]php,
Interestingly verif.bat and tpm2emu.exe use the same argument that is defined by the response of attacker server.
Taking a look at the verif.bat was a script using 7z to extract topic.dat, protected by a password passed as the second command-line argument. The connection to the malicious domain was likely to retrieve this password for the next malware stages.
Executing the MSI and monitoring with ProcMon, we observed a successful connection to kantorpusatsbl[.]com/diagnostics.php and the execution of 7z. We copied the password:
And in the topic.dat we have 4 DLLs, some legit and others pretty suspicious with invalid signatures, but soon we will take a closer look
Continuing we can see something very strange, explorer.exe executed powershell, 100% a process injection, but lets keep looking.
And without a doubt, this is a stealer. It searched for: the “local state” of a lot different browsers (It first do that and the ones he actully find the file, then it searchs for the cookies), crypto extensions, .kbdx files (KeePass databases), crypto wallets and the list go on.
PowerShell also created files resembling a browser extension’s structure:
Since tpm2emu.exe used the password from the malicious domain, we suspected it was responsible for injecting into explorer.exe. Running it without arguments revealed a bad chess game:
The malware relied entirely on the password passed to 7z and tpm2emu.exe. The latter required the extracted DLLs, particularly libcrypto-1_1-x64.dll, which had suspicious exports among legitimate ones:
Debugging with breakpoints on injection-related functions (e.g., VirtualAlloc), we spotted the injection into explorer.exe and a malicious executable:
Dumping and debugging this executable revealed the stealer and the PowerShell executor:
Its even possible to spot the download of the stealer settings
|
|
There are a lot of interesting functions in this malware, but to make this simpler, I’m only highlighting the principal ones.
Now lets analyse the encoded powershell command now. Decoding the command we have a decoding routine and a XOR execution on the result, then again another decoding routine and execution of a remote downloaded script using iex
|
|
Using Python, lets decoded the domain hosting the next script:
|
|
And we have the URL:

This URL contained a massive Base64 string that, when decoded, revealed another decoding and decryption routine using AES.
|
|
Lets again create another python script to do this for us:
|
|
Finnaly, the last script:
It’s a very big script. What it mostly does is decode each Base64 string (which represents the content of the extension’s files) and add it to its respective file. But the question is: How does it add the extension to the browser?
The following deobfuscated function reveals that the extension was installed by modifying the ‘Secure Preferences’ file while enforcing Developer Mode in the browser:
Note that MAC (Mandatory Access Control) is recalculated to trick the browser into accepting malicious changes. Without this step, the browser’s integrity check would fail!
|
|
Malicious Browser Extension
Lets execute Microsoft Edge and take a look. The extension tries to masqueraded as a Google Drive extension:
Lets take a look on the manifest.json that contains the settings of this extension:
The SubscribeUninstallSimulate.js is the main function of this malware and (as expected) is heavily obfuscated. However, we can identify some very interesting imports and modules:
The C2 Domain on a Crypto transaction
Let’s examine the updateDomain function. It begins very strangely with a cryptocurrency wallet address:
And start checking the transactions made from that wallet in different well know domains.
Let’s take a closer look. We can see that it is checking the output of the transaction and appears to decode every scriptPubKey it can find. However, one in particular caught my attention:
Coping the suspicious value and decoding from hex, we have the domain ngc246[.]com. A very interesting method to retrieve a C2 domain address! (This probably exploits Bitcoin’s flexibility in script content while bypassing typical validation. The domain persists forever on-chain.)
Let’s jump to another core module that is Animate.js and Report.js it seens that it handles all commands sended by the attacker c2
And that’s exactly it! We can find numerous functions designed to enumerate and fetch commands, then post their outputs to an API hosted on ngc246[.]com
A summary of its functionalities:
1. Configuration & Initialization
| Method | Purpose |
|---|---|
setDomain(domain) |
Sets the C2 server domain |
getUUID() |
Retrieves the machine’s unique identifier |
init() |
Loads the C2 domain from browser storage |
getDomain() |
Returns the current C2 domain |
2. Core Communication function
| Method | Purpose |
|---|---|
fetch(endpoint, params, method, headers) |
Generic HTTP request handler (used by all other methods) |
3. Machine Control & Data Exfiltration
| Method | Purpose |
|---|---|
initMachine(data) |
Initializes malware with device info |
newGrabberInfo(data) |
Sends stolen data (e.g., credentials, cookies) to C2 |
setScreenshotResult(ruleId, screenshot) |
Uploads screenshots of victim’s active tab |
getInjections() |
Fetches malicious scripts to inject into web pages |
setFiles(data) |
Exfiltrates stolen files to C2 |
4. Remote Command Execution
| Method | Purpose |
|---|---|
getCommands() |
Fetches commands from C2 |
updateCommand(id, answer) |
Sends command results back to C2 |
5. Cryptocurrency Theft (Exchange Targeting)
| Method | Purpose |
|---|---|
getExchangeSettings() |
Get the config of the withdrawals (Like minimum amount) |
createAccount(data) |
Steals exchange account credentials on the creation of a account |
setBalance(data) |
Reports balance of user account to C2 |
setWithdraw(data) |
Report withdrawals to C2 |
getAddress(data) |
Fetches attacker-controlled crypto addresses |
6. Persistence & Evasion
| Method | Purpose |
|---|---|
setStealerData(data) |
Exfiltrate to C2 all stolen data |
setChecker(data) |
Verifies malware is still active |
Report.js creates the handles for each command:
Command Handlers: handleStealer: Processes stealing-related commands (Search and exfiltrate files with seed phrases) handleExtension: Manages browser extensions (enable/disable) handleInfo: Retrieves system information handlePush: Creates browser notifications handleCookies: get all browser cookies handleScreenshot: Takes screenshots handleUrl: Opens URLs handleCurrentUrl: Gets current tab URL handleHistory: Retrieves browser history handleInjects: Manages script injections handleSettings: Handles settings handleProxy: Get proxy settings handleScreenshotRules: Manages screenshot rules
This malware still has one aspect that makes me curious: what are the injected scripts doing on the pages? Using Developer Tools, we can extract some very interesting data from the malware’s configuration - including the C2 domain, reverse proxy address, and each injection script
First, we have the pattern that the malware searches for in the user’s accessed pages - targeting financial sites like PayPal, US Bank, Navy Federal, and others
Now lets take a look in the script injected in paypal page:
It first captures the email/password during login and stores them in a custom cookie.
Then extracts PayPal balance, card details, and bank account info.
After that it sents: Balance, cards, banks, credentials and device info to poribax[.]com[/]logs.php
For some injected scripts it was observed sending the exfiltred information to a telegram BOT
Concluding Thoughts
Creating persistence using a browser extension is very uncommon, but it shows how powerful extensions can be. Using crypto transactions to retrieve the C2 domain was also very creative (and involves a lot of money! =O).
This analysis was very fun and involved some pretty interesting techniques, highlighting the importance of “Stop, Question, Verify, and Repeat.”
Thank you for taking the time to read this analysis! If you have any questions, insights, or suggestions, feel free to reach out.
IOCs
- an[.]disdarrummers[.]shop
- roggiafarm[.]com
- thecsilv[.]com
- rainhadasnoivas[.]com
- hizliadak[.]com
- poribax[.]com
- ngc246[.]com
- 95[.]217[.]142[.]33