This commit is contained in:
Vladislav Rastoropov 2023-03-05 20:00:06 +03:00
parent e3fa582d60
commit ad0109d8f5
45 changed files with 232544 additions and 0 deletions

View File

@ -0,0 +1,49 @@
class DeviceMotionEvent extends Event {
constructor(type, ...args) {
this.isTrusted = true;
this.bubbles = false;
this.cancelBubble = false;
this.cancelable = false;
this.composed = false;
this.defaultPrevented = false;
this.eventPhase = 0;
this.interval = 0;
this.returnValue = true;
this.type = type;
}
static requestPermission() {
console.log('request permission DeviceMotionEvent')
}
get acceleration() {
return null;
}
get rotationRate() {
return null;
}
get accelerationIncludingGravity() {
return null;
}
get currentTarget() {
return null;
}
get srcElement() {
return null;
}
get target() {
return null;
}
get timeStamp() {
return new Date.getTime().now();
}
}
module.exports = DeviceMotionEvent;

15
browser-env/File.js Normal file
View File

@ -0,0 +1,15 @@
const defineFile = (window) => {
class File {
constructor() {
}
get path() {
}
}
window.File = File;
}
module.exports = defineFile;

20
browser-env/MemoryInfo.js Normal file
View File

@ -0,0 +1,20 @@
class MemoryInfo {
constructor() {
}
get jsHeapSizeLimit() {
return 2172649472;
}
get totalJSHeapSize() {
return 9653617;
}
get usedJSHeapSize() {
return 7970197;
}
}
module.exports = MemoryInfo;

View File

@ -0,0 +1,24 @@
class NetworkInformation {
constructor() {
}
get downlink() {
return 4.6
}
get effectiveType() {
return '4g';
}
get rtt() {
return 150;
}
get saveData() {
return false
}
}
module.exports = NetworkInformation;

View File

@ -0,0 +1,89 @@
const defineSpeechSynthesisVoice = (window) => {
class SpeechSynthesisVoice extends Object {}
window.SpeechSynthesisVoice = SpeechSynthesisVoice;
window.Object.defineProperty(
window.SpeechSynthesisVoice.prototype,
Symbol.toStringTag,
{
configurable: true,
enumerable: false,
writable: false,
value: "SpeechSynthesisVoice",
}
);
window.Object.defineProperty(
window.SpeechSynthesisVoice.prototype,
"constructor",
{
value: Object,
}
);
// hook
const props = ["default", "lang", "localService", "name", "voiceURI"];
const voiceObjs = [];
for (const voice of fakeVoices) {
const voiceObj = new SpeechSynthesisVoice();
voiceObjs.push(voiceObj);
window.Object.setPrototypeOf(
voiceObj,
new Proxy(window.SpeechSynthesisVoice.prototype, {
ownKeys(target) {
// 'constructor' not in the prototype of SpeechSynthesisVoice
return window.Reflect.ownKeys(target).filter(
(e) => e !== "constructor"
);
},
get: (target, property, receiver) => {
//
if (property === "__proto__") {
return window.Object.getPrototypeOf(voiceObj);
}
return window.Reflect.get(target, property, receiver);
},
})
);
}
for (const prop of props) {
Object.defineProperty(SpeechSynthesisVoice.prototype, prop, {
});
utils.mockGetterWithProxy(
SpeechSynthesisVoice.prototype,
prop,
_Object.create,
{
configurable: true,
enumerable: true,
},
{
apply: (target, thisArg, args) => {
if (
voiceObjs.map((e) => _Object.getPrototypeOf(e)).includes(thisArg)
) {
// window.speechSynthesis.getVoices()[0].__proto__.default
// throw TypeError
if (props.includes(prop)) {
throw utils.patchError(new TypeError("Illegal invocation"), prop);
} else {
return undefined;
}
}
return fakeVoices[voiceObjs.indexOf(thisArg)][prop];
},
}
);
}
};
module.exports = defineSpeechSynthesisVoice;

View File

@ -0,0 +1,16 @@
const defineXMLHttpRequest = window => {
const XMLHttpRequestSend = window.XMLHttpRequest.prototype.send;
window.XMLHttpRequest.prototype.send = function send(...args) {
console.log(...args);
return XMLHttpRequestSend.call(this, ...args);
}
const XMLHttpRequestOpen = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function open(...args) {
args[1] = 'http://127.0.0.1:3000/send'; // {"success": true}
console.log('OPEN: ', ...args);
return XMLHttpRequestOpen.call(this, ...args);
}
}
module.exports = defineXMLHttpRequest;

6
browser-env/canvas.js Normal file
View File

@ -0,0 +1,6 @@
const defineCanvas = window => {
window.CanvasRenderingContext2D = window.document.createElement('canvas').getContext('2d');
window.CanvasRenderingContext = window.document.createElement('canvas').getContext('2d');
}
module.exports = defineCanvas;

136
browser-env/chrome.js Normal file
View File

@ -0,0 +1,136 @@
chrome = {};
chrome.app = {
InstallState: {
DISABLED: "disabled",
INSTALLED: "installed",
NOT_INSTALLED: "not_installed",
},
RunningState: {
CANNOT_RUN: "cannot_run",
READY_TO_RUN: "ready_to_run",
RUNNING: "running",
},
getDetails: () => {
"[native code]";
},
getIsInstalled: () => {
"[native code]";
},
installState: () => {
"[native code]";
},
get isInstalled() {
return false;
},
runningState: () => {
"[native code]";
},
};
chrome.runtime = {
OnInstalledReason: {
CHROME_UPDATE: "chrome_update",
INSTALL: "install",
SHARED_MODULE_UPDATE: "shared_module_update",
UPDATE: "update",
},
OnRestartRequiredReason: {
APP_UPDATE: "app_update",
OS_UPDATE: "os_update",
PERIODIC: "periodic",
},
PlatformArch: {
ARM: "arm",
ARM64: "arm64",
MIPS: "mips",
MIPS64: "mips64",
X86_32: "x86-32",
X86_64: "x86-64",
},
PlatformNaclArch: {
ARM: "arm",
MIPS: "mips",
MIPS64: "mips64",
X86_32: "x86-32",
X86_64: "x86-64",
},
PlatformOs: {
ANDROID: "android",
CROS: "cros",
FUCHSIA: "fuchsia",
LINUX: "linux",
MAC: "mac",
OPENBSD: "openbsd",
WIN: "win",
},
RequestUpdateCheckStatus: {
NO_UPDATE: "no_update",
THROTTLED: "throttled",
UPDATE_AVAILABLE: "update_available",
},
connect: function() {
"[native code]";
},
sendMessage: function() {
"[native code]";
},
id: undefined,
};
let startE = Date.now();
chrome.csi = function () {
"[native code]";
return {
startE: startE,
onloadT: startE + 281,
pageT: 3947.235,
tran: 15,
};
};
chrome.loadTimes = function () {
"[native code]";
return {
get requestTime() {
return startE / 1000;
},
get startLoadTime() {
return startE / 1000;
},
get commitLoadTime() {
return startE / 1000 + 0.324;
},
get finishDocumentLoadTime() {
return startE / 1000 + 0.498;
},
get finishLoadTime() {
return startE / 1000 + 0.534;
},
get firstPaintTime() {
return startE / 1000 + 0.437;
},
get firstPaintAfterLoadTime() {
return 0;
},
get navigationType() {
return "Other";
},
get wasFetchedViaSpdy() {
return true;
},
get wasNpnNegotiated() {
return true;
},
get npnNegotiatedProtocol() {
return "h3";
},
get wasAlternateProtocolAvailable() {
return false;
},
get connectionInfo() {
return "h3";
},
};
};
module.exports = chrome;

16
browser-env/cookies.js Normal file
View File

@ -0,0 +1,16 @@
const defineCookies = window => {
window.document.cookie = 'asos-ts121=4dcff988a4964c0f88ce3f2cabcb73c5'
window.document.cookie = 'asos-cou998=GB';
window.document.cookie = 'asos-sto997=COM';
window.document.cookie = 'asos-du123=https%3A%2F%2Fmy.asos.com%2Fmy-account%3Fcountry%3DRU';
window.document.cookie = 'bm_sz=45808E5A1C2FD5A58D9E4A87E76B0E7E~YAAQV8ETAsGheniGAQAAO3vYlBLSV+0AeZYf1zB+Q0zAcggi2hr8Uxl7mELucFYoSPonr4560l04xqqCcAPlaF+yQkUFt5FofLzQ6EXMJu0RAhxFSkjmo7FRITzCTF5yoZkmV3G7qGveNe6mRoFKJ8Kqf0TC/pTLW69maYyGWtP5C+avmIgwK14YpjaIj3LGagkQZhqEui/7LxSUzh9ERUdo5EHu5Mxv9Wi7S/4942O4SFmtNEZnczTm6334SvcNaqlwE4gYnuumNvnFmAfCJECOwcOVAZGj59Kc43Z+TU2v~3290948~3486519';
window.document.cookie = 'asos-lan999=en-GB';
window.document.cookie = 'keyStoreDataversion=ornjx7v-36';
window.document.cookie = '_abck=56B5FC2147EF5451923462E585D1D380~-1~YAAQV8ETAvyheniGAQAAq3/YlAkcP9LCIlKSlbRIAX2wYf2okcbcgujT0ZEHDBr2mQtYNjSaXrrFEKDLPB72zQr5afIAaxxCBF172bSQtrFtSCkkt3hh2Vc7Jp0inhDDF7IQGx0zD7S8EDsHNdz1F/H9hoIsiKNpvSdNuVVUWDvjgq1DpML4xFq8HhCbu9fxA8FDY/MX39klZLT1Ya+E0qO/rEKqe9pSkmaMeDE393VQwVDBCLOamgp5RBVOMH5j6iHZgP4qFLGloxS7SmFgiKXv3dYc+HKxeB6LuXul+NcZLI7mRM2qdI2sAQycHkfyW8e68eD6s54GLfycYy2jqLnXqhLwaiyL/vyaxDUhocdVqV3z+bgirfs1FMv+F5X3hgIE1XEIv/M=~-1~-1~1677538026';
window.document.cookie = 'AMCV_C0137F6A52DEAFCC0A490D4C%40AdobeOrg=T';
window.document.cookie = 'bm_mi=78BF595C0DA24635CEBFC9ECAABBBE39~YAAQNsETAtZb8YeGAQAAcInzlBIWkOLtWn49Zg59FkXKxI690dyepamF97fTp19PGBI33i2ZwCfXI1cWCoEqx8OyjvgzzEMgGdqbwmfO8t+KBLsu8sSYVYgYytWAocoMQaeWDSCnK/Oi3Tx/9/J2VdmtwZieFq5ZzpMceln7uTot1XbjVzX5smy5RxZjWtckZJhv+EdsE2NkoFTR5Wq0TFYSS1bZTqfye3Wl9Nrth1YEey0h52fcG0PjPGPoF4EYNRNRl3AyBwOppHXzkl+4Jbz7TOjKrXf4iYQSYpqxfmDvmrYK585eDqoc4zJhzCZQ10A3RQmDKkRv~1';
window.document.cookie = 'bm_sv=399089C7BA65493EFEE776A634F8EFEB~YAAQNsETAthc8YeGAQAAjbLzlBJlynY4W1K8s12Idon+kJt8nC9ROu8cAW3zvdUhpZqKDGHnwfh4NuLnjobwxwGO7Q53/qj4SQuK3f6VfpzdgSEo+38qBolqVlPCXbAraxjp5OEcnR5Ntf0lTr7FWMeIjMyQX9t4XdeXFdojHFrx9YpXGKiwhEWIZNMunhqU1hD/tP0W2/XNrihbgjQw7CQwRBVaIEKISVr1VJbtdzFjbLG6LxkDsxeAewjNBQ==~1';
}
module.exports = defineCookies;

15
browser-env/document.js Normal file
View File

@ -0,0 +1,15 @@
const defineDocument = window => {
Object.defineProperties(window.Document.prototype, {
URL: {
get: () => {
return 'https://my.asos.com/identity/login?signin=ca270a738a5c227ec615ac4f24216ca7';
}
},
hidden: {
get: () => false,
},
})
}
module.exports = defineDocument;

View File

View File

@ -0,0 +1,15 @@
const defineCurrentScript = window => {
Object.defineProperty(window.Document.prototype, 'currentScript', {
get: () => {
return new Proxy({}, {
get(target, prop, r) {
if (prop === 'src') {
return 'https://my.asos.com/cPYhw7js-taKj/GV/951_KziztRsQ/f5OEkf5rkY5Qit/fSovAg/WXQ/MOWY5XCs'
}
}
})
}
});
}
module.exports = defineCurrentScript;

View File

@ -0,0 +1,65 @@
const defineCanPlayType = window => {
const parseInput = arg => {
const [mime, codecStr] = arg.trim().split(';')
let codecs = []
if (codecStr && codecStr.includes('codecs="')) {
codecs = codecStr
.trim()
.replace(`codecs="`, '')
.replace(`"`, '')
.trim()
.split(',')
.filter(x => !!x)
.map(x => x.trim())
}
return {
mime,
codecStr,
codecs
}
}
const canPlayType = {
// Intercept certain requests
apply: function(target, ctx, args) {
if (!args || !args.length) {
return target.apply(ctx, args)
}
const { mime, codecs } = parseInput(args[0])
// This specific mp4 codec is missing in Chromium
if (mime === 'video/mp4') {
if (codecs.includes('avc1.42E01E')) {
return 'probably'
}
}
// This mimetype is only supported if no codecs are specified
if (mime === 'audio/x-m4a' && !codecs.length) {
return 'maybe'
}
// This mimetype is only supported if no codecs are specified
if (mime === 'audio/aac' && !codecs.length) {
return 'probably'
}
// Everything else as usual
return target.apply(ctx, args)
}
}
window.HTMLMediaElement.canPlayType = function() {
}
window.HTMLMediaElement.canPlayType = new Proxy(
window.HTMLMediaElement.canPlayType,
canPlayType
)
}
const defineHTMLMediaElement = window => {
defineCanPlayType(window);
}
module.exports = defineHTMLMediaElement;

View File

@ -0,0 +1,20 @@
const defineAddEventListener = window => {
// const windowAddEventListener = window.addEventListener;
// window.addEventListener = function(type, listener, opts) {
// setTimeout(() => {
// listener();
// }, 1000);
// }
// const documentAddEventListener = document.addEventListener;
const addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function(type, listener, opts) {
setTimeout(() => {
listener(new window.UniversalEvent(type));
}, 1000);
}
}
module.exports = defineAddEventListener;

75
browser-env/events.js Normal file
View File

@ -0,0 +1,75 @@
const defineEvents = window => {
class PointerEvent extends window.Event {
constructor() {
super()
}
}
class DeviceOrientationEvent extends window.Event {
constructor() {
super()
}
}
class DeviceMotionEvent extends window.Event {
constructor() {
super()
}
}
class TouchEvent extends window.Event {
constructor() {
super()
}
}
window.DeviceOrientationEvent = DeviceOrientationEvent;
window.PointerEvent = PointerEvent;
window.DeviceMotionEvent = DeviceMotionEvent;
// window.TouchEvent = TouchEvent;
class UniversalEvent extends window.Event {
constructor (type) {
super(type);
}
get target() {
return window.document.createElement('input');
}
get currentTarget() {
return window.document.createElement('input');
}
get altKey() { return 1; }
get ctrlKey() {}
get shiftKey() {}
get charCode() {}
get code() {}
get detail() {}
get isComposing() {}
get key() {}
get keyCode() { return 1; }
get location() { return 1; }
get metakey() { return 1; }
get repeat() { return 1; }
get buttun() { return 1; }
get buttons() { return 1; }
get clientX() { return 1; }
get clientY() { return 0; }
get layerX() { return 1; }
get layerY() { return 1; }
get offsetX() {return 1; }
get offsetY() { return 1; }
get pageX() { return 1; }
get pageY() { return 0; }
get screenX() { return 1; }
get screenY() { return 1; }
get x() { return 1; }
get y() { return 1;}
get changedTouches() { return {} }
get touches() {}
}
window.UniversalEvent = UniversalEvent;
}
module.exports = defineEvents;

5
browser-env/indexedDB.js Normal file
View File

@ -0,0 +1,5 @@
const defineIndexedDB = (window) => {
window.indexedDB = {}
}
module.exports = defineIndexedDB;

16
browser-env/location.js Normal file
View File

@ -0,0 +1,16 @@
const defineLocation = window => {
Object.defineProperties(window.Location, {
'protocol': {
get() {
return 'https:'
}
},
'hostname': {
get() {
return 'www.zalando.co.uk'
}
},
});
}
module.exports = defineLocation;

278
browser-env/navigator.js Normal file
View File

@ -0,0 +1,278 @@
const NetworkInformation = require('./NetworkInformation');
const definePermissions = window => {
class PermissionStatus {
constructor(name) {
this.name_ = name;
this.onchangeCallBack = null;
}
get name() {
return this.name_
}
get onchange() {
return this.onchangeCallBack;
}
set onchange(value) {
this.onchangeCallBack = value;
this.onchangeCallBack();
}
get state() {
return 'denied'
}
}
window.PermissionStatus = PermissionStatus;
window.Permissions = function() {}
window.Permissions.prototype.query = async function(permission) {
const { name } = permission;
return Promise.resolve(new window.PermissionStatus(name));
}
}
class Brave {
constructor() {}
async isBrave() {
return new Promise.resolve(true);
}
}
const defineNavigator = (window) => {
definePermissions(window);
Object.defineProperties(Object.getPrototypeOf(window.navigator), {
brave: {
get() {
return new Brave();
}
},
bluetooth: {
get: () => {
return {};
},
},
clipboard: {
get: () => {
return {};
},
},
connection: {
get: () => {
return new NetworkInformation();
},
},
cookieEnabled: {
get: () => {
return true;
},
},
credentials: {
get: () => {
return {};
},
},
deviceMemory: {
get: () => 8,
},
bluetooth: {
get: () => {
return {};
},
},
doNotTrack: {
get: () => null,
},
geolocation: {
get: () => {
return {};
},
},
hid: {
get: () => {
return {};
},
},
ink: {
get: () => {
return {};
},
},
keyboard: {
get: () => {
return {};
},
},
locks: {
get: () => {
return {};
},
},
managed: {
get: () => {
return {};
},
},
maxTouchPointsoxjl: {
get: () => 0,
},
mediaCapabilities: {
get: () => {
return {};
},
},
mediaDevices: {
get: () => {
return {};
},
},
mediaSession: {
get: () => {
return {};
},
},
onLine: {
get: () => true,
},
pdfViewerEnabled: {
get: () => {
return {};
},
},
permissions: {
get: () => {
return window.Object.create(window.Permissions.prototype);
},
},
platform: {
get: () => "Win32",
},
product: {
get: () => "Gecko",
},
productSub: {
get: () => "20030107",
},
scheduling: {
get: () => {
return {};
},
},
serial: {
get: () => {
return {};
},
},
serviceWorker: {
get: () => {
return {};
},
},
storage: {
get: () => {
return {};
},
},
usb: {
get: () => {
return {};
},
},
userActivation: {
get: () => {
return {};
},
},
userAgent: {
get: () =>
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
},
userAgentData: {
get: () => {
return {};
},
},
vendor: {
get: () => "Google Inc.",
},
vendorSub: {
get: () => "",
},
vibrate: {
value: function vibrate() {
console.log('VIBRATE!!!')
}
},
getBattery: {
value: async function getBattery() {
return new Promise((rs, rj) => {
setTimeout(() => {
rs({
charging: true
})
}, 100);
})
}
},
virtualKeyboard: {
get: () => {
return {};
},
},
wakeLock: {
get: () => {
return {};
},
},
webdriver: {
get: () => false,
},
webkitPersistentStorage: {
get: () => {
return {};
},
},
webkitTemporaryStorage: {
get: () => {
return {};
},
},
windowControlsOverlay: {
get: () => {
return {};
},
},
xr: {
get: () => {
return {};
},
},
appVersion: {
get: () =>
"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
},
javaEnabled: {
value: function javaEnabled() {
return false;
}
},
requestMediaKeySystemAccess: {
value: async function requestMediaKeySystemAccess(params) {
return new window.Promise((rs, rj) => {
rs(true);
});
}
},
registerProtocolHandler: {
value: function registerProtocolHandler() {
return;
}
}
});
window.clientInformation = window.navigator;
};
module.exports = defineNavigator;

View File

@ -0,0 +1,11 @@
const MemoryInfo = require('./MemoryInfo');
const definePerformance = window => {
Object.defineProperty(window.Performance.prototype, 'memory', {
get() {
return new MemoryInfo();
}
})
}
module.exports = definePerformance;

249
browser-env/plugins.js Normal file
View File

@ -0,0 +1,249 @@
const definePlugins = (window) => {
const plugin0 = Object.create(window.Plugin.prototype);
const mimeType0 = Object.create(window.MimeType.prototype);
const mimeType1 = Object.create(window.MimeType.prototype);
Object.defineProperties(mimeType0, {
type: {
get: () => 'application/pdf',
},
suffixes: {
get: () => 'pdf',
},
enabledPlugin: {
get() {
return plugin0;
}
}
});
Object.defineProperties(mimeType1, {
type: {
get: () => 'text/pdf',
},
suffixes: {
get: () => 'pdf',
},
enabledPlugin: {
get() {
return plugin0
}
}
});
Object.defineProperties(plugin0, {
name: {
get: () => 'Chrome PDF Viewer',
},
description: {
get: () => 'Portable Document Format',
},
0: {
get: () => {
return mimeType0;
},
},
1: {
get: () => {
return mimeType1;
},
},
length: {
get: () => 2,
},
filename: {
get: () => 'internal-pdf-viewer',
},
});
const plugin1 = Object.create(window.Plugin.prototype);
Object.defineProperties(plugin1, {
name: {
get: () => 'Chromium PDF Viewer',
},
description: {
get: () => 'Portable Document Format',
},
0: {
get: () => {
return mimeType0;
},
},
1: {
get: () => {
return mimeType1;
},
},
length: {
get: () => 2,
},
filename: {
get: () => 'internal-pdf-viewer',
},
});
const plugin2 = Object.create(window.Plugin.prototype);
Object.defineProperties(plugin2, {
name: {
get: () => 'Microsoft Edge PDF Viewer',
},
description: {
get: () => 'Portable Document Format',
},
0: {
get: () => {
return mimeType0;
},
},
1: {
get: () => {
return mimeType1;
},
},
length: {
get: () => 2,
},
filename: {
get: () => 'internal-pdf-viewer',
},
});
const plugin3 = Object.create(window.Plugin.prototype);
Object.defineProperties(plugin3, {
name: {
get: () => 'PDF Viewer',
},
description: {
get: () => 'Portable Document Format',
},
0: {
get: () => {
return mimeType0;
},
},
1: {
get: () => {
return mimeType1;
},
},
length: {
get: () => 2,
},
filename: {
get: () => 'internal-pdf-viewer',
},
});
const plugin4 = Object.create(window.Plugin.prototype);
Object.defineProperties(plugin4, {
name: {
get: () => 'WebKit built-in PDF',
},
description: {
get: () => 'Portable Document Format',
},
0: {
get: () => {
return mimeType0;
},
},
1: {
get: () => {
return mimeType1;
},
},
length: {
get: () => 2,
},
filename: {
get: () => 'internal-pdf-viewer',
},
});
const pluginArray = Object.create(window.PluginArray.prototype);
pluginArray['0'] = plugin0;
pluginArray['1'] = plugin1;
pluginArray['2'] = plugin2;
pluginArray['3'] = plugin3;
pluginArray['4'] = plugin4;
pluginArray['Chrome PDF Viewer'] = plugin0;
pluginArray['Chromium PDF Viewer'] = plugin1;
pluginArray['Microsoft Edge PDF Viewer'] = plugin2;
pluginArray['PDF Viewer'] = plugin3;
pluginArray['WebKit built-in PDF'] = plugin4;
let refreshValue;
Object.defineProperties(pluginArray, {
length: {
get: () => 5,
},
item: {
value: (index) => {
if (index > 4294967295) {
index = index % 4294967296;
}
switch (index) {
case 0:
return plugin3;
case 1:
return plugin0;
case 2:
return plugin1;
case 3:
return plugin2;
case 4:
return plugin4;
default:
break;
}
},
},
refresh: {
get: () => {
return refreshValue;
},
set: (value) => {
refreshValue = value;
},
},
namedItem: {
value: function namedItem(name) {
'{ [native code] }';
switch (name) {
case 'PDF Viewer':
return plugin3;
case 'Chrome PDF Viewer':
return plugin0;
case 'Chromium PDF Viewer':
return plugin1;
case 'Microsoft Edge PDF Viewer':
return plugin2;
case 'WebKit built-in PDF':
return plugin4;
default:
return undefined;
}
},
},
});
Object.defineProperty(Object.getPrototypeOf(window.navigator), 'plugins', {
get: () => {
'[native code]';
return pluginArray;
},
});
Object.getOwnPropertyDescriptor(
Object.getPrototypeOf(window.navigator),
'plugins'
).get.toString = function toString() {
return 'function get plugins() { [native code] }';
};
}
module.exports = definePlugins;

188
browser-env/promise.js Normal file
View File

@ -0,0 +1,188 @@
const { _NATIVE_TOSTRING_ } = require('./../utils/constants');
const definePromise = (window) => {
class PromiseNodeJS {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(value) {
if (this.state === "pending") {
debugger;
this.state = "fulfilled";
this.value = value;
this.onFulfilledCallbacks.forEach((callback) => callback(this.value));
}
}
reject(reason) {
if (this.state === "pending") {
this.state = "rejected";
this.reason = reason;
this.onRejectedCallbacks.forEach((callback) => callback(this.reason));
}
}
then(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (error) => {
throw error;
};
const promise = new PromiseNodeJS((resolve, reject) => {
if (this.state === "fulfilled") {
setTimeout(() => {
try {
const result = onFulfilled(window, this.value);
PromiseNodeJS.resolvePromise(promise, result, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === "rejected") {
setTimeout(() => {
try {
const result = onRejected(window, this.reason);
PromiseNodeJS.resolvePromise(promise, result, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === "pending") {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
let result;
if (_NATIVE_TOSTRING_.call(onFulfilled).includes('callContext')) {
result = onFulfilled(window, this.value);
} else {
result = onFulfilled(this.value);
}
PromiseNodeJS.resolvePromise(promise, result, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const result = onRejected(window, this.reason);
PromiseNodeJS.resolvePromise(promise, result, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise;
}
catch(onRejected) {
return this.then(null, onRejected);
}
static resolve(value) {
return new PromiseNodeJS((resolve) => resolve(value));
}
static reject(reason) {
return new PromiseNodeJS((resolve, reject) => reject(reason));
}
static all(promises) {
return new PromiseNodeJS((resolve, reject) => {
debugger;
const results = [];
let count = 0;
for (let i = 0; i < promises.length; i++) {
promises[i].then((value) => {
results[i] = value;
count++;
if (count === promises.length) {
resolve(results);
}
}, reject);
}
});
}
static race(promises) {
return new PromiseNodeJS((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
});
}
static resolvePromise(promise, result, resolve, reject) {
if (promise === result) {
reject(new TypeError("Chaining cycle detected"));
return;
}
if (result instanceof PromiseNodeJS) {
result.then(resolve, reject);
return;
}
if (
result !== null &&
(typeof result === "object" || typeof result === "function")
) {
let called = false;
try {
const then = result.then;
if (typeof then === "function") {
then.call(
result,
(value) => {
if (called) return;
called = true;
PromiseNodeJS.resolvePromise(promise, value, resolve, reject);
},
(error) => {
if (called) return;
called = true;
reject(error);
}
);
return;
}
} catch (error) {
if (called) return;
called = true;
reject(error);
return;
}
}
resolve(result);
}
}
window.Promise = PromiseNodeJS;
};
module.exports = definePromise;

91
browser-env/screen.js Normal file
View File

@ -0,0 +1,91 @@
const defineScreenOrientation = window => {
class ScreenOrientation {
constructor() {
this.onchange = null;
}
get angle() {
return 0;
}
get type() {
return 'landscape-primary';
}
}
window.ScreenOrientation = ScreenOrientation;
}
const defineScreen = (window) => {
defineScreenOrientation(window);
Object.defineProperties(window.Screen.prototype, {
'availHeight': {
get: () => 900
},
'availLeft': {
get: () => 0
},
'availTop': {
get: () => 0
},
'availWidth': {
get: () => 1440
},
'colorDepth': {
get: () => 30
},
'height': {
get: () => 900
},
'isExtended': {
get: () => false
},
'pixelDepth': {
get: () => 30
},
'width': {
get: () => 1440
},
'orientation': {
get() {
return new window.ScreenOrientation();
}
},
'onchange': {
get() {
return null;
}
},
});
Object.defineProperties(window, {
innerHeight: {
get() {
return 821;
}
},
innerWidth: {
get() {
return 1440;
}
},
outerHeight: {
get() {
return 900;
}
},
outerWidth: {
get() {
return 1440;
}
},
devicePixelRatio: {
get() {
return 1;
}
}
});
}
module.exports = defineScreen;

View File

@ -0,0 +1,36 @@
const defineInterval = window => {
const windowInterval = window.setInterval;
const windowTimeout = window.setTimeout;
let timeoutCallCounter = 0;
let intervalCallCounter = 0;
window.setInterval = function setInterval(...args) {
console.log('interval', intervalCallCounter);
++intervalCallCounter;
if (intervalCallCounter > 3) {
return;
}
const intervalId = windowInterval(...args);
var clearAll = function() {
window.clearInterval(intervalId);
}
windowTimeout(clearAll, 5000);
return intervalId;
}
window.setTimeout = function(callBack, time) {
console.log('timeout', timeoutCallCounter);
++timeoutCallCounter;
if (timeoutCallCounter === 5) {
global.allTimeoutsCleaned = true;
return;
}
if (time === 300000) time = 10000;
return windowTimeout(callBack, time)
}
}
module.exports = defineInterval;

View File

@ -0,0 +1,58 @@
const defineSpeechSynthesis = window => {
class SpeechSynthesisVoice {
constructor(def, lang, localService, name) {
this.default_ = def;
this.lang_ = lang;
this.localService_ = localService;
this.name_ = name;
this.voiceURI_ = name;
}
get default() {
return this.default_;
}
get lang() {
return this.lang_;
}
get localService() {
return this.localService_;
}
get name() {
return this.name_;
}
get voiceURI() {
return this.voiceURI_;
}
}
const speech1 = new SpeechSynthesisVoice(true, "ru-RU", true, "Microsoft Irina - Russian (Russia)");
const speech2 = new SpeechSynthesisVoice(false, "en-US", true, "Microsoft Mark - English (United States)");
const speech3 = new SpeechSynthesisVoice(false, "en-US", true, "Microsoft Zira - English (United States)");
class speechSynthesis extends Object {
constructor() {
super();
this._onvoiceschanged = null;
}
getVoices() {
return [
speech1,
speech2,
speech3
]
}
get onvoiceschanged() {
return this._onvoiceschanged ;
}
set onvoiceschanged(value) {
this._onvoiceschanged = value;
this._onvoiceschanged();
}
}
window.speechSynthesis = new speechSynthesis();
}
module.exports = defineSpeechSynthesis;

15
browser-env/toString.js Normal file
View File

@ -0,0 +1,15 @@
const { userFunctionToString } = require('./../utils/constants');
const defineToString = window => {
const orgToString = window.Function.prototype.toString;
window.Function.prototype.toString = function toString() {
if (userFunctionToString.has(this)) {
const result = userFunctionToString.get(this);
return result.replaceAll(/console\.log\([a-zA-Z0-9_\(\)\s,\[\]']*\);/g, '');
}
return orgToString.call(this);
}
}
module.exports = defineToString;

59
browser-env/webgl.js Normal file
View File

@ -0,0 +1,59 @@
const { WEBGLEXTENSIONS } = require('./../utils/constants');
const defineWebGL = window => {
class WebGLDebugRendererInfo {
constructor() {}
get UNMASKED_RENDERER_WEBGL() {
return 37446;
}
get UNMASKED_VENDOR_WEBGL() {
return 37445;
}
}
const glDebugInfo = new WebGLDebugRendererInfo();
class WebGLRenderingContext {
constructor() {
}
getExtension(ex) {
if (ex === 'WEBGL_debug_renderer_info') {
return glDebugInfo;
}
return {}
}
getParameter(param) {
if (param === 37446) {
return 'ANGLE (Intel Inc., Intel(R) Iris(TM) Plus Graphics 640, OpenGL 4.1)';
}
if (param === 37445) {
return 'Google Inc. (Intel Inc.)';
}
return {};
}
getSupportedExtensions() {
return WEBGLEXTENSIONS;
}
}
const getContext = window.HTMLCanvasElement.prototype.getContext;
window.HTMLCanvasElement.prototype.getContext = function (type, ...args) {
if (type === 'webgl' ||
type === 'webgl2' ||
type === 'experimental-webgl'
) {
return new WebGLRenderingContext();
}
return getContext.call(this, type, ...args);
}
window.WebGLRenderingContext = WebGLRenderingContext;
window.WebGL2RenderingContext = WebGLRenderingContext;
}
module.exports = defineWebGL;

7
browser-env/webrtc.js Normal file
View File

@ -0,0 +1,7 @@
const defineWebRTC = window => {
// window.RTCPeerConnection = function RTCPeerConnection() {}
window.webkitRTCPeerConnection = function RTCPeerConnection() {}
}
module.exports = defineWebRTC;

434
browser-env/window.js Normal file
View File

@ -0,0 +1,434 @@
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const chrome = require('./chrome');
const definePlugins = require('./plugins');
const defineNavigator = require('./navigator');
const defineXMLHttpRequest = require('./XMLHttpRequest');
const defineToString = require('./toString');
const defineCurrentScript = require('./document/currentScript');
const defineLocation = require('./location');
const defineHTMLMediaElement = require('./element/HTMLMediaElement');
const defineScreen = require('./screen');
const defineIndexedDB = require('./indexedDB');
const defineCanvas = require('./canvas');
const defineWebGL = require('./webgl');
const definePerformance = require('./performance');
const defineInterval = require('./setInterval');
const defineCookies = require('./cookies');
const defineEvents = require('./events');
const DeviceMotionEvent = require('./DeviceMotionEvent');
const defineWebRTC = require("./webrtc");
const defineSpeechSynthesis = require("./speechSynthesis");
const defineDocument = require("./document");
const defineFile = require("./File");
const defineAddEventListener = require('./eventListener');
const { window } = new JSDOM(`
<!DOCTYPE html>
<html class="layout-v2" lang="en">
<head>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="apple-mobile-web-app-capable" content="yes" />
<title>ASOS | Sign in</title>
<link rel="preload" href="https://assets.asosservices.com/MasterLayout/WebFonts/FTN75__W/FTN75__W.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="https://assets.asosservices.com/MasterLayout/WebFonts/FTN45__W/FTN45__W.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" as="script" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0= sha384-ZvpUoO/+PpLXR1lu4jmpXWu80pZlYUAfxl5NsBMWOEPSjUn/6Z/hRTt8+pR6L4N2 sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous">
<link rel="preload" href="/Content/dist/styles/bundle.5908ce81c95b7a58eeb6.css" as="style">
<link rel="stylesheet" href="/Content/dist/styles/bundle.5908ce81c95b7a58eeb6.css" />
<script>
function onWindowFullyLoaded(callback) {
if (document.readyState === 'complete') {
callback();
} else {
window.addEventListener('load', callback);
}
}
function onDomLoaded(callback) {
if (document.readyState !== 'loading') {
callback();
} else {
document.addEventListener('DOMContentLoaded', callback);
}
}
</script>
<script type="text/javascript">
var isMobile = false;
window.asos = window.asos || {};
window.asos.context = {
isIosOidc: false,
isMobile: false
};
window.asos.addToViewBag = function (val) {
window.asos.viewBag = Object.assign(window.asos.viewBag || {}, val);
}
</script>
<script type="text/javascript">
window.asos.routes = {};
ASOS = typeof (ASOS) == 'undefined' ? {} : ASOS;
ASOS.Identity = typeof (ASOS.Identity) == 'undefined' ? {} : ASOS.Identity;
ASOS.Identity.IsTouchDevice = /MSIE 10.*Touch/.test(navigator.userAgent) || ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
var isMobile = false;
ASOS.Identity.Configuration = function() {
return {
isTouch: false,
isMobileOidcClient: false,
oidcClientPlatform: 'web'
};
}();
ASOS.Identity.Events = function() {
return {
clickEvent: "click"
};
}();
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" crossorigin="anonymous" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0= sha384-ZvpUoO/+PpLXR1lu4jmpXWu80pZlYUAfxl5NsBMWOEPSjUn/6Z/hRTt8+pR6L4N2 sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg=="></script>
<script>
window.jQuery || document.write('<script src="/Content/dist/js/jquery.min.c4dccdd9.js"><\/script>');
</script>
<script>
!function(T,l,y){var S=T.location,k="script",D="connectionString",C="ingestionendpoint",I="disableExceptionTracking",E="ai.device.",b="toLowerCase",w="crossOrigin",N="POST",e="appInsightsSDK",t=y.name||"appInsights";(y.name||T[e])&&(T[e]=t);var n=T[t]||function(d){var g=!1,f=!1,m={initialize:!0,queue:[],sv:"5",version:2,config:d};function v(e,t){var n={},a="Browser";return n[E+"id"]=a[b](),n[E+"type"]=a,n["ai.operation.name"]=S&&S.pathname||"_unknown_",n["ai.internal.sdkVersion"]="javascript:snippet_"+(m.sv||m.version),{time:function(){var e=new Date;function t(e){var t=""+e;return 1===t.length&&(t="0"+t),t}return e.getUTCFullYear()+"-"+t(1+e.getUTCMonth())+"-"+t(e.getUTCDate())+"T"+t(e.getUTCHours())+":"+t(e.getUTCMinutes())+":"+t(e.getUTCSeconds())+"."+((e.getUTCMilliseconds()/1e3).toFixed(3)+"").slice(2,5)+"Z"}(),name:"Microsoft.ApplicationInsights."+e.replace(/-/g,"")+"."+t,sampleRate:100,tags:n,data:{baseData:{ver:2}}}}var h=d.url||y.src;if(h){function a(e){var t,n,a,i,r,o,s,c,u,p,l;g=!0,m.queue=[],f||(f=!0,t=h,s=function(){var e={},t=d.connectionString;if(t)for(var n=t.split(";"),a=0;a<n.length;a++){var i=n[a].split("=");2===i.length&&(e[i[0][b]()]=i[1])}if(!e[C]){var r=e.endpointsuffix,o=r?e.location:null;e[C]="https://"+(o?o+".":"")+"dc."+(r||"services.visualstudio.com")}return e}(),c=s[D]||d[D]||"",u=s[C],p=u?u+"/v2/track":d.endpointUrl,(l=[]).push((n="SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details)",a=t,i=p,(o=(r=v(c,"Exception")).data).baseType="ExceptionData",o.baseData.exceptions=[{typeName:"SDKLoadFailed",message:n.replace(/\./g,"-"),hasFullStack:!1,stack:n+"\nSnippet failed to load ["+a+"] -- Telemetry is disabled\nHelp Link: https://go.microsoft.com/fwlink/?linkid=2128109\nHost: "+(S&&S.pathname||"_unknown_")+"\nEndpoint: "+i,parsedStack:[]}],r)),l.push(function(e,t,n,a){var i=v(c,"Message"),r=i.data;r.baseType="MessageData";var o=r.baseData;return o.message='AI (Internal): 99 message:"'+("SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details) ("+n+")").replace(/\"/g,"")+'"',o.properties={endpoint:a},i}(0,0,t,p)),function(e,t){if(JSON){var n=T.fetch;if(n&&!y.useXhr)n(t,{method:N,body:JSON.stringify(e),mode:"cors"});else if(XMLHttpRequest){var a=new XMLHttpRequest;a.open(N,t),a.setRequestHeader("Content-type","application/json"),a.send(JSON.stringify(e))}}}(l,p))}function i(e,t){f||setTimeout(function(){!t&&m.core||a()},500)}var e=function(){var n=l.createElement(k);n.src=h;var e=y[w];return!e&&""!==e||"undefined"==n[w]||(n[w]=e),n.onload=i,n.onerror=a,n.onreadystatechange=function(e,t){"loaded"!==n.readyState&&"complete"!==n.readyState||i(0,t)},n}();y.ld<0?l.getElementsByTagName("head")[0].appendChild(e):setTimeout(function(){l.getElementsByTagName(k)[0].parentNode.appendChild(e)},y.ld||0)}try{m.cookie=l.cookie}catch(p){}function t(e){for(;e.length;)!function(t){m[t]=function(){var e=arguments;g||m.queue.push(function(){m[t].apply(m,e)})}}(e.pop())}var n="track",r="TrackPage",o="TrackEvent";t([n+"Event",n+"PageView",n+"Exception",n+"Trace",n+"DependencyData",n+"Metric",n+"PageViewPerformance","start"+r,"stop"+r,"start"+o,"stop"+o,"addTelemetryInitializer","setAuthenticatedUserContext","clearAuthenticatedUserContext","flush"]),m.SeverityLevel={Verbose:0,Information:1,Warning:2,Error:3,Critical:4};var s=(d.extensionConfig||{}).ApplicationInsightsAnalytics||{};if(!0!==d[I]&&!0!==s[I]){var c="onerror";t(["_"+c]);var u=T[c];T[c]=function(e,t,n,a,i){var r=u&&u(e,t,n,a,i);return!0!==r&&m["_"+c]({message:e,url:t,lineNumber:n,columnNumber:a,error:i}),r},d.autoExceptionInstrumented=!0}return m}(y.cfg);function a(){y.onInit&&y.onInit(n)}(T[t]=n).queue&&0===n.queue.length?(n.queue.push(a),n.trackPageView({})):a()}(window,document,{
src: "https://js.monitor.azure.com/scripts/b/ai.2.min.js", // The SDK URL Source
crossOrigin: "anonymous", // When supplied this will add the provided value as the cross origin attribute on the script tag
onInit: function(appInsights) {
var serverId = "b4f008c799e4e9720a092b50d3b4cd45";
if (serverId) {
appInsights.context.telemetryTrace.parentID = serverId;
}
appInsights.addTelemetryInitializer((envelope) => {
if (envelope.data.url && envelope.data.url.includes("/Content/")) {
return false;
}
return true;
});
},
cfg: {
connectionString: "InstrumentationKey=cef16d31-8194-4d9a-bdfd-3de8a10903c5;IngestionEndpoint=https://westeurope-3.in.applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/",
loggingLevelTelemetry: 0
}});
</script>
<script src="//ci.asosservices.com/core/shared-libs-2.0.4.min.js"></script>
<script src="/Content/dist/js/jquery.validate.min.4c0cc637.js" defer></script>
<script src="/Content/dist/js/jquery.modal.min.970d08b0.js" defer></script>
<script src="/Content/dist/js/jquery.unobtrusive-ajax.min.3c00b4d3.js" defer></script>
<script src="/Content/dist/js/jquery.validate.unobtrusive.min.1fc39d86.js" defer></script>
<script src="/Content/dist/js/sha256.min.71575116.js" defer></script>
<script src="/Content/dist/js/global.init.877afe7cf8e36c60fd54.js" defer></script>
<script src="/Content/dist/js/Asos.Identity.Analytics.Account.8878f13b40b7bd1ca76d.js" defer></script>
<script src="/Content/dist/js/Asos.Identity.Analytics.Ids.12285accf7757b8ce00d.js" defer></script>
<script src="/Content/dist/js/Asos.Identity.Form.Submission.e6762cd5741353850512.js" defer></script>
<script src="/Content/dist/js/Asos.Identity.Helpers.38adf00d310357c6987d.js" defer></script>
<script src="/Content/dist/js/Asos.Identity.RecaptchaCallbacks.f0b84a8f695088abde35.js" defer></script>
<script src="/Content/dist/js/Asos.Identity.RecaptchaTracker.4fc5715b8ba0325a303e.js" defer></script>
<script src="/Content/dist/js/jquery.email-autocomplete.331e11f11061270ef52d.js" defer></script>
<script src="https://resources.asosservices.com/res/analytics/identity.js" defer></script><script src="/Content/dist/js/adobeTracking.56c3fcf0373322466895.js" defer></script>
<script type="text/javascript">
window.AdobeGlobalTrackingData = {
platform: "desktop",
domainSuffix: "com",
pageType: "secure",
breadCrumbs: "sign in",
dateTime: "",
currentPageUrl: "",
visitNumber: "",
newRepeat: "",
windowInnerHeight: "",
windowInnerWidth: "",
responseStart: "",
domContentLoadedEvent: "",
previousSitContent: "",
countryIsoCode: "ru",
isCheckout: "False",
clientPlatform: "desktop web"
}
onDomLoaded(function() {
window.adobeTrackingFile.RaiseEventForLoginError();
window.adobeTrackingFile.RaiseEventForLinkAccountError();
onWindowFullyLoaded(function () {
window.AdobeGlobalTrackingData.isLoginErrorPresent = window.isLoginErrorPresent;
window.AdobeGlobalTrackingData.isLinkAccountErrorPresent = window.isLinkAccountErrorPresent;
window.adobeTrackingFile.raiseEvent("signInPageLoaded", window.AdobeGlobalTrackingData);
});
});
</script>
<script type="text/javascript">
window.asos.optimizely = window.asos.optimizely || {};
window.asos.optimizely.viewBag = {"sdkKey":"ShK2dzd7JQhz8jETx1Fkb","optimizelyLocation":"https://www.asos.com/assets/optimizely/datafiles/%s.json","browseCountry":"GB","language":"en-GB","browseStore":"COM","platform":"desktop","loggedIn":"true","recognised":"false","geoCountry":null,"identityAppClient":false,"identityRequestOrigin":"self","xSiteOrigin":""};
if ('False'.toLowerCase() == 'true') {
window.asos.optimizely.viewBag.forceDisable = 1;
}
const safetyNetToAvoidHiddenMvtContainers = function () {
document.querySelectorAll('.mvt-container').forEach(el => {
el.style.visibility = "visible";
});
}
setTimeout(safetyNetToAvoidHiddenMvtContainers, 1500);
</script>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-NK4DFXV');</script>
<!-- End Google Tag Manager -->
</head>
<body class="full sign-in-page lang-en region-gb" data-state="isExpanded">
<div id="content" class="">
<div id="header">
<h1>
<a href="http://www.asos.com" class="home" id="asos-logo">
<img src="/Content/images/asos-logo-2022-93x28.png" height="28" width="93" alt="ASOS Logo" loading="lazy" />
</a>
</h1>
</div> <main id="main">
<div class="container signin-container">
<div class="signin-options">
<div class="title qa-title with-link">
<div class="qa-header"><a class="qa-join-asos" href="/identity/register?signin=519ed2f4fc21e4de23335b05a4c9c130&amp;forceAuthentication=True" id="new-to-asos-tab">Join</a></div>
</div>
<div class="title qa-title active">
<div class="qa-header" aria-current="page">Sign in</div>
</div>
<div class="clear"></div>
</div>
<div class="form form-login">
<form action="https://my.asos.com/identity/login?signin=519ed2f4fc21e4de23335b05a4c9c130&amp;showAllOptions=False" data-analytics="signInUsingEmail" id="signInForm" method="post"><input id="idsrv_xsrf" name="idsrv.xsrf" type="hidden" value="c9VUP5VyUeKetobneEINUutR1ocDlm95pR3VZg3s0mo8BwacStZOgONuy4otdV6o9SOa0iUFbd79S9tGXqoawDYnAdg" /> <fieldset>
<legend class="screenreader">Sign in with email</legend>
<div class="mobile-spacer">
<div>
</div>
</div>
<div>
<div class="field">
<label class="qa-email-label" for="EmailAddress" id="EmailLabel">Email address</label>
<div class="input-wrapper" aria-labelledby="EmailLabel">
<input Name="Username" class="qa-email-textbox" data-val="true" data-val-email="Email fail! Please type in your correct email address" data-val-length="Oops, that email address is too long - try again, please" data-val-length-max="255" data-val-required="Oops! You need to type your email here" id="EmailAddress" maxlength="255" name="EmailAddress" type="email" value="" />
<span class="field-validation-valid qa-email-validation" data-valmsg-for="Username" data-valmsg-replace="true"></span>
</div>
<div class="clear"></div>
</div>
<div class="field">
<label class="qa-password-label" for="Password" id="PasswordLabel">Password</label>
<div class="input-wrapper" aria-labelledby="PasswordLabel">
<input autocomplete="off" class="qa-password-textbox" data-val="true" data-val-length="Hold up, that&#39;s too long. Less than 100 characters please" data-val-length-max="100" data-val-required="Hey, we need a password here" id="Password" name="Password" type="password" value="" />
<button id="signin-show-me" class="reveal hidden qa-reveal" type="button" role="button">Show</button>
<button id="signin-hide-me" class="hide hidden qa-hide" type="button" role="button">Hide</button>
<span class="field-validation-valid qa-password-validation" data-valmsg-for="Password" data-valmsg-replace="true"></span>
</div>
<div class="clear"></div>
</div>
</div>
<div class="submit">
<input data-sitekey=""
data-callback=""
type="submit"
value="Sign in"
id="signin"
class="g-recaptcha qa-submit adobeTrackedButton"
return="false"
data-adobe='{"event": "tracking.identity.signIn" ,"data" :{"action":"Sign In","context":"Sign In" ,"signupmethod":"Email","recognised":"","socialPlatform": ""}}' />
<div class="clear"></div>
</div>
<input id="submitting" name="submitting" type="hidden" value="Submitting..." />
<div class="forgotten-password">
<a class="qa-forgot-password adobeTrackedButton" data-analytics="alreadyRegisteredForgotPassword" href="/identity/password/reset?signin=519ed2f4fc21e4de23335b05a4c9c130" id="forgot-password-link">Forgot password?</a>
</div>
</fieldset>
</form> </div>
<div class="info info-centre ">
<h2 id="sign-in-header" class="qa-subtitle">Or sign in with...</h2>
<div class="clear"></div>
<div class="options three-buttons ">
<p class="banner">
We are aware that you may not be able to log in to your ASOS account using Facebook. We're working on getting it back up and running as soon as possible, in the meantime please use one of the other available login methods.
</p>
<div id="social-links-container" class="social-links-container social-buttons-icon-with-text">
<ul id="social-signin-list" style="list-style-type: none">
<li class="social-register">
<a href="https://my.asos.com/identity/external?provider=Google&amp;signin=519ed2f4fc21e4de23335b05a4c9c130" id="signup-google" data-analytics="signInUsingSocial" data-analytics-social="google" class="social-link gplus">
<div class="connect google qa-sign-up-with-google">
<div class="icon qa-sign-up-with-google" role="img" aria-label="google"></div>
<div class="text"><span>Google</span></div>
</div>
</a>
</li>
<li class="social-register">
<a href="https://my.asos.com/identity/external?provider=Apple&amp;signin=519ed2f4fc21e4de23335b05a4c9c130" id="signup-apple" data-analytics="signInUsingSocial" data-analytics-social="apple" class="social-link apple">
<div class="connect apple qa-sign-up-with-apple">
<div class="icon qa-sign-up-with-apple" role="img" aria-label="apple"></div>
<div class="text"><span>Apple</span></div>
</div>
</a>
</li>
<li class="social-register">
<a href="#" id="signup-facebook" data-analytics="signInUsingSocial" data-analytics-social="facebook" class="social-link facebook disabled">
<div class="connect facebook qa-sign-up-with-facebook">
<div class="icon qa-sign-up-with-facebook" role="img" aria-label="facebook"></div>
<div class="text"><span>Facebook</span></div>
</div>
</a>
</li>
</ul>
</div>
<div class="twitter-gone">
<a href="https://www.asos.com/customer-care/technical/im-having-trouble-signing-into-my-account/">Where has Twitter Gone?</a>
</div>
</div>
<div class="clear"></div>
</div>
</div>
<script>
window.asos.addToViewBag({"IsAllowedBrowser":true,"ForceAuthentication":false,"IsCheckout":false});
</script>
<script src="/Content/dist/js/views/signin/index.ebd8d5d18b50c212a2ca.js" defer></script>
</main>
</div>
<div class="terms">
<label>
<a target="_blank" href="http://www.asos.com/privacy-policy/" id="privacy-policy" class="qa-privacypolicy-link" rel="noopener">Privacy Policy</a> | <a href="http://www.asos.com/terms-and-conditions/" id="terms-and-conditions" class="qa-tandc-link" target="_blank" rel="noopener">Terms and Conditions</a>
</label>
</div>
<script type="text/javascript" nonce="57f3824f30c8eedcd701b0e0f61a8374" src="/cPYhw7js-taKj/GV/951_KziztRsQ/f5OEkf5rkY5Qit/fSovAg/WXQ/MOWY5XCs"></script></body>
</html>
`, {
url: 'http://127.0.0.1:3000',
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36',
contentType: 'text/html',
});
window.chrome = chrome;
window.DeviceMotionEvent = DeviceMotionEvent;
definePlugins(window);
defineNavigator(window);
defineXMLHttpRequest(window);
defineToString(window);
defineCurrentScript(window);
defineLocation(window);
defineHTMLMediaElement(window);
defineScreen(window);
defineIndexedDB(window);
defineWebGL(window);
definePerformance(window);
defineInterval(window);
defineCookies(window);
defineEvents(window);
defineWebRTC(window);
defineSpeechSynthesis(window);
defineDocument(window);
defineFile(window);
defineAddEventListener(window);
// Object.defineProperty(window.HTMLIFrameElement.prototype, 'loading', {
// get() {
// },
// set() {
// }
// })
// delete window.SharedArrayBuffer;
// Object.defineProperties(window, {
// 'isSecureContext': {
// get: () => true
// },
// 'crossOriginIsolated': {
// get: () => false
// },
// });
// global.Function.prototype.toString = window.Function.prototype.toString;
module.exports = window;

26
index.js Normal file
View File

@ -0,0 +1,26 @@
const { parse } = require('@babel/parser');
const fs = require('fs');
const Interpreter = require('./libs/Interpreter');
const Deobfuscator = require('./libs/Deobfuscator');
const srcCode = fs.readFileSync('./input/src.js', { encoding: 'utf-8' });
const ast = parse(srcCode);
function deobfucateCode(ctx) {
const { env } = ctx;
const deobfuscator = new Deobfuscator(ast, env);
deobfuscator.deobfuscate();
const code = deobfuscator.getCode();
fs.writeFileSync('./output/deobfuscated.js', code);
}
const interval = setInterval(() => {
console.log('cheking...');
if (global.interpreterState) {
clearInterval(interval);
deobfucateCode(global.interpreterState)
}
}, 3000);
console.log(new Interpreter(srcCode).eval(ast.program))

1
input/src.js Normal file

File diff suppressed because one or more lines are too long

35317
interpreter-logs/callsLog.txt Normal file

File diff suppressed because it is too large Load Diff

57
libs/Deobfuscator.js Normal file
View File

@ -0,0 +1,57 @@
const traverse = require('@babel/traverse').default;
const generate = require('@babel/generator').default;
const t = require('@babel/types');
const ExecutionContext = require('./ExecutionContext');
const window = require('./../browser-env/window');
const Interpreter = require('./Interpreter');
class Deobfuscator {
constructor(ast, env) {
this.ast = ast;
this.env = env;
this.exec = new ExecutionContext(window, env);
this.interpreter = new Interpreter();
}
getCode() {
return generate(this.ast).code;
}
deobfuscate() {
this._replaceStrings();
}
_replaceStrings() {
const self = this;
traverse(this.ast, {
CallExpression: path => {
const { node } = path;
if (
t.isMemberExpression(node.callee) &&
(
(t.isIdentifier(node.callee.object) &&
node.callee.object.name === 'EE') ||
(t.isMemberExpression(node.callee.object) &&
t.isIdentifier(node.callee.object.object) &&
node.callee.object.object.name === 'EE')
) &&
t.isIdentifier(node.callee.property)
) {
try {
let result = self.interpreter.eval(node, self.exec);
if (typeof result === 'string') {
path.replaceWith(t.stringLiteral(result));
} else if (typeof result === 'number') {
path.replaceWith(t.numericLiteral(result));
}
} catch(err) { console.log(err) }
}
}
});
}
}
module.exports = Deobfuscator;

35
libs/Environment.js Normal file
View File

@ -0,0 +1,35 @@
class Environment {
constructor(record = {}, parent = null) {
this.record = record;
this.parent = parent;
}
define(name, value = undefined) {
this.record[name] = value;
return value;
}
lookup(name) {
return this.resolve(name).record[name];
}
resolve(name) {
if (this.record.hasOwnProperty(name)) {
return this;
}
if (this.parent === null) {
throw new ReferenceError(`Variable "${name}" is not defined`);
}
return this.parent.resolve(name);
}
assign(name, value) {
this.resolve(name).record[name] = value;
return value;
}
}
module.exports = Environment;

8
libs/ExecutionContext.js Normal file
View File

@ -0,0 +1,8 @@
class ExecutionContext {
constructor(thisValue, env) {
this.thisValue = thisValue;
this.env = env;
}
}
module.exports = ExecutionContext;

View File

@ -0,0 +1,4 @@
const Environment = require("./Environment")
const window = require('./../browser-env/window');
module.exports = new Environment(window);

View File

@ -0,0 +1,6 @@
const ExecutionContext = require("./ExecutionContext");
const GlobalEnvironment = require("./GlobalEnvironment");
const window = require('./../browser-env/window');
module.exports = new ExecutionContext(window, GlobalEnvironment);

630
libs/Interpreter.js Normal file
View File

@ -0,0 +1,630 @@
const t = require('@babel/types');
const generate = require("@babel/generator").default;
const Environment = require('./Environment');
const ExecutionContext = require('./ExecutionContext');
const GlobalExecutionContext = require('./GlobalExecutionContext');
const { userFunctionToString } = require('./../utils/constants');
const fs = require('fs');
class Interpreter {
constructor(code, execCtx = GlobalExecutionContext) {
this.scriptCode = code;
this.callStack = [execCtx];
this.flags = {
continue: false,
break: false
}
}
eval(node, ctx = this.callStack[this.callStack.length - 1]) {
if (global.allTimeoutsCleaned) {
console.log('SetContext!');
global.interpreterState = ctx;
global.allTimeoutsCleaned = false;
return;
}
if (t.isProgram(node)) {
this._hoistVariables(node, ctx);
let result;
node.body.forEach((node) => {
result = this.eval(node, ctx);
});
return result;
}
if (t.isExpressionStatement(node)) {
return this.eval(node.expression, ctx);
}
if (t.isLiteral(node)) {
// if (t.isNullLiteral(node)) {
// return null;
// }
// return node.value;
return global.eval(generate(node).code)
}
if (t.isBinaryExpression(node)) {
const left = this.eval(node.left, ctx);
const right = this.eval(node.right, ctx);
switch (node.operator) {
case '+':
return left + right;
case '-':
return left - right;
case '*':
return left * right;
case '/':
return left / right;
case '%':
return left % right;
case '**':
return left ** right;
case '==':
return left == right;
case '===':
return left === right;
case '!=':
return left != right;
case '!==':
return left !== right;
case '<':
return left < right;
case '<=':
return left <= right;
case '>':
return left > right;
case '>=':
return left >= right;
case '|':
return left | right;
case '&':
return left & right;
case '^':
return left ^ right;
case '<<':
return left << right;
case '>>':
return left >> right;
case '>>>':
return left >>> right;
case 'in':
return left in right;
case 'instanceof':
return left instanceof right;
default:
throw `Unknown operator ${node.operator}`;
}
}
if (t.isUnaryExpression(node)) {
const arg = this.eval(node.argument, ctx);
switch (node.operator) {
case '+':
return +arg;
case '-':
return -arg;
case '!':
return !arg;
case '~':
return ~arg;
case 'typeof':
return typeof arg;
case 'void':
return void arg;
default:
throw new Error(`Unknown unary operator ${node.operator}`);
}
}
if (t.isLogicalExpression(node)) {
switch (node.operator) {
case '||':
return this.eval(node.left, ctx) || this.eval(node.right, ctx);
case '&&':
return this.eval(node.left, ctx) && this.eval(node.right, ctx);
case '??':
return this.eval(node.left, ctx) ?? this.eval(node.right, ctx);
default:
throw new Error(`Unknown operator ${node.operator}`);
}
}
if (t.isVariableDeclaration(node)) {
let result;
node.declarations.forEach(variableDeclarator => {
result = this.eval(variableDeclarator, ctx);
});
return result;
}
if (t.isVariableDeclarator(node)) {
const name = node.id.name;
if (!node.init) { // Переменная уже определена из-за hoisting
return;
}
const value = this.eval(node.init, ctx);
return ctx.env.define(name, value);
}
if (t.isIdentifier(node)) {
return ctx.env.lookup(node.name)
}
if (t.isAssignmentExpression(node)) {
if (t.isIdentifier(node.left)) {
const left = node.left.name;
const right = this.eval(node.right, ctx);
// if (left === 'wPE') {
// console.log(`CODE: ${generate(node).code} | RESULT: ${right}`);
// }
let prevValue = this.eval(node.left, ctx);
switch(node.operator) {
case '=':
return ctx.env.assign(left, right);
case '+=':
return ctx.env.assign(left, prevValue + right);
case '-=':
return ctx.env.assign(left, prevValue - right);
case '*=':
return ctx.env.assign(left, prevValue * right);
case '/=':
return ctx.env.assign(left, prevValue / right);
case '^=':
return ctx.env.assign(left, prevValue ^ right);
case '&=':
return ctx.env.assign(left, prevValue & right);
case '|=':
return ctx.env.assign(left, prevValue | right);
case '%=':
return ctx.env.assign(left, prevValue % right);
default:
throw `Unimplement operator assignment ${node.operator}`
}
}
if (t.isMemberExpression(node.left)) {
let objectName = node.left.object.name;
let object;
if (objectName === undefined) {
object = this.eval(node.left.object, ctx);
} else {
object = ctx.env.lookup(objectName);
}
if (!object) {
throw `Undefined object in assignment... ${generate(node).code}`;
}
let prop;
if (node.left.computed) {
prop = this.eval(node.left.property, ctx);
} else {
prop = node.left.property.name;
}
if (prop == undefined) {
throw `Undefined property in assignment... ${generate(node).code}`
}
const propValue = this.eval(node.right, ctx);
const prevValue = object[prop];
switch(node.operator) {
case '=':
return object[prop] = propValue;
case '+=':
return object[prop] = prevValue + propValue;
case '-=':
return object[prop] = prevValue + propValue;
case '*=':
return object[prop] = prevValue * propValue;
case '/=':
return object[prop] = prevValue / propValue;
case '^=':
return object[prop] = prevValue ^ propValue;
case '&=':
return object[prop] = prevValue & propValue;
case '|=':
return object[prop] = prevValue | propValue;
case '%=':
return object[prop] = prevValue % propValue;
default:
throw `Unimplement operator assignment ${node.operator}`
}
}
throw `Unimplement assignment for node type ${node.left.type}`;
}
if (t.isUpdateExpression(node)) {
if (t.isIdentifier(node.argument)) {
const varName = node.argument.name;
const varValue = this.eval(node.argument, ctx);
const newValue = node.operator === '++' ? varValue + 1 : varValue - 1;
if (node.prefix) {
return ctx.env.assign(varName, newValue);
}
ctx.env.assign(varName, newValue);
return varValue;
}
if (t.isMemberExpression(node.argument)) {
const objectEnv = this.eval(node.argument.object, ctx);
const prop = node.argument.computed ? this.eval(node.argument.property, ctx) : node.argument.property.name;
const propValue = objectEnv[prop];
const newValue = node.operator === '++' ? propValue + 1 : propValue - 1;
if (node.prefix) {
return objectEnv[prop] = newValue;
}
objectEnv[prop] = newValue;
return propValue;
}
}
if (t.isEmptyStatement(node)) {
return;
}
if (t.isSequenceExpression(node)) {
let result;
const { expressions } = node;
expressions.forEach(expr => {
result = this.eval(expr, ctx);
});
return result;
}
if (t.isThisExpression(node)) {
return ctx.thisValue;
}
if (t.isObjectExpression(node)) {
const object = {};
node.properties.forEach(prop => {
const key = prop.key.name || prop.key.value;
const value = this.eval(prop.value, ctx);
object[key] = value;
})
return object;
}
if (t.isArrayExpression(node)) {
const elements = node.elements.map(el => this.eval(el, ctx));
const array = [...elements];
return array;
}
if (t.isConditionalExpression(node)) {
if (this.eval(node.test, ctx)) {
return this.eval(node.consequent, ctx)
} else {
return this.eval(node.alternate, ctx);
}
}
if (t.isIfStatement(node)) {
const test = this.eval(node.test, ctx);
if (test) {
return this.eval(node.consequent, ctx)
} else if (node.alternate !== null) {
return this.eval(node.alternate, ctx)
} else {
return undefined;
}
}
if (t.isBlockStatement(node)) {
this._hoistVariables(node, ctx);
let result;
for (let i = 0; i < node.body.length; ++i) {
const stmt = node.body[i];
result = this.eval(stmt, ctx);
if (this.callStack[this.callStack.length - 1] !== ctx) {
return result;
}
if (this.flags.continue || this.flags.break) {
break;
}
}
return result;
}
if (t.isFunctionDeclaration(node)) {
const self = this;
const parentEnv = ctx.env;
const func = function(...args) {
const activationRecord = {};
for (let i = 0; i < node.params.length; ++i) {
activationRecord[node.params[i].name] = args[i];
}
activationRecord['arguments'] = [...args];
const execCtx = new ExecutionContext(
this,
new Environment(activationRecord, parentEnv)
);
self.callStack.push(execCtx);
if (new.target) {
self._evalFunctionBlock(node.body, execCtx);
return this;
}
let result = self._evalFunctionBlock(node.body, execCtx);
return result;
}
const funcString = this.scriptCode.substring(node.loc.start.column, node.loc.end.column);
userFunctionToString.set(func, funcString);
ctx.env.define(node.id.name, func);
return;
}
if (t.isFunctionExpression(node)) {
const name = node.id ? node.id.name : undefined;
const self = this;
const parentEnv = ctx.env;
const func = function(...args) {
const activationRecord = {};
if (name) {
activationRecord[name] = func;
}
for (let i = 0; i < node.params.length; ++i) {
activationRecord[node.params[i].name] = args[i];
}
activationRecord['arguments'] = [...args];
const execCtx = new ExecutionContext(
this,
new Environment(activationRecord, parentEnv)
);
self.callStack.push(execCtx);
if (new.target) {
self._evalFunctionBlock(node.body, execCtx);
return this;
}
let result = self._evalFunctionBlock(node.body, execCtx);
return result;
}
const funcString = this.scriptCode.substring(node.loc.start.column, node.loc.end.column);
userFunctionToString.set(func, funcString);
return func;
}
if (t.isReturnStatement(node)) {
let functionResult;
if (node.argument !== null) {
functionResult = this.eval(node.argument, ctx);
}
this.callStack.pop();
return functionResult;
}
if (t.isCallExpression(node)) {
let thisCtx;
let fn;
if (t.isMemberExpression(node.callee)) {
thisCtx = this.eval(node.callee.object, ctx);
const prop = node.callee.computed
? this.eval(node.callee.property, ctx)
: node.callee.property.name;
fn = thisCtx[prop];
} else {
fn = this.eval(node.callee, ctx);
thisCtx = ctx.thisValue;
}
if (fn === undefined) {
throw `function is not defined ${generate(node).code}`;
}
const args = node.arguments.map(arg => this.eval(arg, ctx));
if (args[1] && args[1] === 493711) {
// console.log('here')
return 3031957943;
}
const result = fn.call(thisCtx, ...args);
const resultBlackList = ['length', 'push', 'pop', 'charCodeAt', 'charAt', toString];
// if (
// typeof result === 'string' &&
// !resultBlackList.includes(result) &&
// result.length > 1 && result.length < 100
// ) {
// fs.appendFileSync('./interpreter-logs/callsLog.txt', result + '\n');
// }
return result;
return fn.call(thisCtx, ...args)
}
if (t.isMemberExpression(node)) {
const object = this.eval(node.object, ctx);
let prop;
if (node.computed) {
prop = this.eval(node.property, ctx);
} else {
prop = node.property.name;
}
return object[prop];
}
if (t.isNewExpression(node)) {
const callee = this.eval(node.callee, ctx);
const args = node.arguments.map(arg => this.eval(arg, ctx));
const result = new callee(...args);
return result
}
if (t.isWhileStatement(node)) {
const { test, body } = node;
let result;
while(this.callStack[this.callStack.length - 1] === ctx && this.eval(test, ctx)) {
result = this.eval(body, ctx);
if (this.flags.continue) {
this.flags.continue = false;
}
if (this.flags.break) {
this.flags.break = false;
break;
}
}
return result;
}
if (t.isForStatement(node)) {
const { init, test, body } = node;
let result;
if (node.init) this.eval(init, ctx);
while(this.callStack[this.callStack.length - 1] === ctx && (test ? this.eval(test, ctx) : 1)) {
result = this.eval(body, ctx);
if (this.flags.continue) {
this.flags.continue = false;
}
if (this.flags.break) {
this.flags.break = false;
break;
}
if (node.update) {
this.eval(node.update, ctx);
}
}
return result;
}
if (t.isDoWhileStatement(node)) {
const { test, body } = node;
let result;
do {
result = this.eval(body, ctx);
if (this.flags.continue) {
this.flags.continue = false;
}
if (this.flags.break) {
this.flags.break = false;
break;
}
} while(this.callStack[this.callStack.length - 1] === ctx && this.eval(test, ctx));
return result;
}
if (t.isContinueStatement(node)) {
this.flags.continue = true;
return;
}
if (t.isBreakStatement(node)) {
this.flags.break = true;
return;
}
if (t.isThrowStatement(node)) {
throw this.eval(node.argument, ctx);
}
if (t.isTryStatement(node)) {
let result;
try {
result = this.eval(node.block, ctx);
} catch(e) {
console.debug('debug:', e);
const paramName = node.handler.param.name;
ctx.env.define(paramName, e);
result = this.eval(node.handler.body, ctx);
}
if (node.finalizer) {
return this.eval(node.finalizer, ctx)
}
return result;
}
if (t.isForInStatement(node)) {
const object = this.eval(node.right, ctx);
const varName = node.left.declarations[0].id.name;
for (var key in object) {
ctx.env.define(varName, key);
this.eval(node.body, ctx);
}
return;
}
if (t.isSwitchStatement(node)) {
const test = this.eval(node.discriminant, ctx);
let result;
for (let i = 0; i < node.cases.length; ++i) {
const caseClause = node.cases[i];
if (
caseClause.test !== null &&
this.eval(caseClause.test, ctx) === test
) {
result = this._evalCaseClause(caseClause, ctx);
if (this.flags.break === true) {
this.flags.break = false;
}
break; // break из текущего цикла for
} else if (caseClause.test === null) { // ветка default
result = this._evalCaseClause(caseClause, ctx);
if (this.flags.break === true) {
this.flags.break = false;
}
}
}
return result;
}
throw `Unimplemented ${node.type} node`;
}
_hoistVariables(block, ctx) {
block.body.forEach(stmt => {
if (t.isFunctionDeclaration(stmt)) {
this.eval(stmt, ctx)
}
if (t.isVariableDeclaration(stmt)) {
for (const variableDeclarator of stmt.declarations) {
const name = variableDeclarator.id.name;
ctx.env.define(name, undefined);
}
}
});
}
_evalFunctionBlock(block, ctx) {
this._hoistVariables(block, ctx);
let result;
for (let s = 0; s < block.body.length; ++s) {
const stmt = block.body[s];
result = this.eval(stmt, ctx);
if (this.callStack[this.callStack.length - 1] !== ctx) {
return result;
}
}
this.callStack.pop();
return result;
}
_evalCaseClause(caseClause, ctx) {
let result;
for (let i = 0; i < caseClause.consequent.length; ++i) {
const stmt = caseClause.consequent[i];
result = this.eval(stmt, ctx);
// switch-case мог быть внутри функции,
// поэтому мог наткнуться на return
if (this.callStack[this.callStack.length - 1] !== ctx) {
if (this.flags.break === true) {
this.flags.break = false;
}
return result;
}
}
return result;
}
}
module.exports = Interpreter;

12774
output/deob.js Normal file

File diff suppressed because it is too large Load Diff

12781
output/deobfuscate.io.js Normal file

File diff suppressed because it is too large Load Diff

6970
output/deobfuscated.js Normal file

File diff suppressed because one or more lines are too long

160660
output/logger.txt Normal file

File diff suppressed because it is too large Load Diff

1194
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

24
package.json Normal file
View File

@ -0,0 +1,24 @@
{
"name": "akamai-deobfuscator-2.0",
"version": "1.0.0",
"description": "Akamai Bot Manager 2.0 dynamic script deobfuscator from asos",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/rastvl/akamai-deobfuscator-2.0.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/rastvl/akamai-deobfuscator-2.0/issues"
},
"homepage": "https://github.com/rastvl/akamai-deobfuscator-2.0#readme",
"dependencies": {
"canvas": "^2.11.0",
"jsdom": "^21.1.0"
}
}

39
utils/constants.js Normal file
View File

@ -0,0 +1,39 @@
const userFunctionToString = new Map();
const _NATIVE_TOSTRING_ = global.Function.prototype.toString;
const WEBGLEXTENSIONS = [
'ANGLE_instanced_arrays',
'EXT_blend_minmax',
'EXT_color_buffer_half_float',
'EXT_disjoint_timer_query',
'EXT_float_blend',
'EXT_frag_depth',
'EXT_shader_texture_lod',
'EXT_texture_compression_bptc',
'EXT_texture_compression_rgtc',
'EXT_texture_filter_anisotropic',
'EXT_sRGB',
'KHR_parallel_shader_compile',
'OES_element_index_uint',
'OES_fbo_render_mipmap',
'OES_standard_derivatives',
'OES_texture_float',
'OES_texture_float_linear',
'OES_texture_half_float',
'OES_texture_half_float_linear',
'OES_vertex_array_object',
'WEBGL_color_buffer_float',
'WEBGL_compressed_texture_s3tc',
'WEBGL_compressed_texture_s3tc_srgb',
'WEBGL_debug_renderer_info',
'WEBGL_debug_shaders',
'WEBGL_depth_texture',
'WEBGL_draw_buffers',
'WEBGL_lose_context',
'WEBGL_multi_draw',
];
module.exports = {
userFunctionToString,
_NATIVE_TOSTRING_,
WEBGLEXTENSIONS
}

10
utils/server.js Normal file
View File

@ -0,0 +1,10 @@
const express = require('express');
const app = express();
app.post('/send', (req, res) => {
console.log(req);
res.send('{"success": true}');
});
app.listen(3000, () => console.log('Server started at 3000'));