From 27d2b556110c4ea98931706a1f6ba8560ce4d819 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 1 Sep 2022 14:55:45 -0500 Subject: [PATCH 01/78] Return a failure shell code when analyzing a single sample fails. --- _run.js | 17 ++++++++++++++--- analyze.js | 8 +++++++- package-lock.json | 2 +- package.json | 2 +- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/_run.js b/_run.js index b6a73c9..8a36042 100644 --- a/_run.js +++ b/_run.js @@ -4,6 +4,9 @@ const path = require("path"); const walk = require("walk-sync"); const argv = require("./argv.js").run; +// Track whether we should return an error shell code or not. +var single_sample = false; + // Read and format JSON flag documentation if (argv.help || process.argv.length === 2) { const columnify = require("columnify"); @@ -108,9 +111,10 @@ else q.concurrency = require("os").cpus().length; if (tasks.length > 1) // If batch mode if (argv.threads) console.log(`Analyzing ${tasks.length} items with ${q.concurrency} threads`) -else +else { console.log(`Analyzing ${tasks.length} items with ${q.concurrency} threads (use --threads to change this value)`) - +} + // queue the input files for analysis const outputDir = argv["output-dir"] || "./"; tasks.forEach(({filepath, filename}) => q.push(cb => analyze(filepath, filename, cb))); @@ -123,6 +127,10 @@ q.on("success", () => { console.log(`Progress: ${completed}/${tasks.length} (${(100 * completed/tasks.length).toFixed(2)}%)`); }); +// Exit with a meaningful return code if we are only analyzing 1 sample. +single_sample = (q.length == 1); + +// Start analyzing samples. q.start(); function analyze(filepath, filename, cb) { @@ -169,9 +177,12 @@ function analyze(filepath, filename, cb) { * If the error is about a weird \"Unknown ActiveXObject\", try --no-kill. * Otherwise, report a bug at https://github.com/CapacitorSet/box-js/issues/ .`); } + if (code != 0) { + final_code = code; + } clearTimeout(killTimeout); worker.kill(); - if (argv.debug) process.exit(code); + if (argv.debug || single_sample) process.exit(code); cb(); }); diff --git a/analyze.js b/analyze.js index 58620aa..96ab993 100644 --- a/analyze.js +++ b/analyze.js @@ -539,7 +539,13 @@ if (argv["dangerous-vm"]) { // Fake up Object.toString not being defined in cscript.exe. //code = "Object.prototype.toString = undefined;\n\n" + code; - vm.run(code); + try{ + vm.run(code); + } catch (e) { + lib.error("Sandbox execution failed:"); + lib.error(e); + process.exit(1); + } } function ActiveXObject(name) { diff --git a/package-lock.json b/package-lock.json index fb3ef7e..eb9fefa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "box-js", - "version": "1.9.16", + "version": "1.9.18", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 63277f8..7263138 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "box-js", - "version": "1.9.16", + "version": "1.9.18", "description": "A tool for studying JavaScript malware.", "dependencies": { "acorn": "^5.6.2", From d60d733164c8a0f790793144d702f48f07ab4f40 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Mon, 5 Sep 2022 14:52:00 -0500 Subject: [PATCH 02/78] Use correct implementation of atob(). --- boilerplate.js | 113 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 6 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index d3ed61a..a64e4a5 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -1,5 +1,111 @@ const parse = require("node-html-parser").parse; +// atob() taken from abab.atob.js . + +/** + * Implementation of atob() according to the HTML and Infra specs, except that + * instead of throwing INVALID_CHARACTER_ERR we return null. + */ +function atob(data) { + // Web IDL requires DOMStrings to just be converted using ECMAScript + // ToString, which in our case amounts to using a template literal. + data = `${data}`; + // "Remove all ASCII whitespace from data." + data = data.replace(/[ \t\n\f\r]/g, ""); + // "If data's length divides by 4 leaving no remainder, then: if data ends + // with one or two U+003D (=) code points, then remove them from data." + if (data.length % 4 === 0) { + data = data.replace(/==?$/, ""); + } + // "If data's length divides by 4 leaving a remainder of 1, then return + // failure." + // + // "If data contains a code point that is not one of + // + // U+002B (+) + // U+002F (/) + // ASCII alphanumeric + // + // then return failure." + if (data.length % 4 === 1 || /[^+/0-9A-Za-z]/.test(data)) { + return null; + } + // "Let output be an empty byte sequence." + let output = ""; + // "Let buffer be an empty buffer that can have bits appended to it." + // + // We append bits via left-shift and or. accumulatedBits is used to track + // when we've gotten to 24 bits. + let buffer = 0; + let accumulatedBits = 0; + // "Let position be a position variable for data, initially pointing at the + // start of data." + // + // "While position does not point past the end of data:" + for (let i = 0; i < data.length; i++) { + // "Find the code point pointed to by position in the second column of + // Table 1: The Base 64 Alphabet of RFC 4648. Let n be the number given in + // the first cell of the same row. + // + // "Append to buffer the six bits corresponding to n, most significant bit + // first." + // + // atobLookup() implements the table from RFC 4648. + buffer <<= 6; + buffer |= atobLookup(data[i]); + accumulatedBits += 6; + // "If buffer has accumulated 24 bits, interpret them as three 8-bit + // big-endian numbers. Append three bytes with values equal to those + // numbers to output, in the same order, and then empty buffer." + if (accumulatedBits === 24) { + output += String.fromCharCode((buffer & 0xff0000) >> 16); + output += String.fromCharCode((buffer & 0xff00) >> 8); + output += String.fromCharCode(buffer & 0xff); + buffer = accumulatedBits = 0; + } + // "Advance position by 1." + } + // "If buffer is not empty, it contains either 12 or 18 bits. If it contains + // 12 bits, then discard the last four and interpret the remaining eight as + // an 8-bit big-endian number. If it contains 18 bits, then discard the last + // two and interpret the remaining 16 as two 8-bit big-endian numbers. Append + // the one or two bytes with values equal to those one or two numbers to + // output, in the same order." + if (accumulatedBits === 12) { + buffer >>= 4; + output += String.fromCharCode(buffer); + } else if (accumulatedBits === 18) { + buffer >>= 2; + output += String.fromCharCode((buffer & 0xff00) >> 8); + output += String.fromCharCode(buffer & 0xff); + } + // "Return output." + return output; +} +/** + * A lookup table for atob(), which converts an ASCII character to the + * corresponding six-bit number. + */ +function atobLookup(chr) { + if (/[A-Z]/.test(chr)) { + return chr.charCodeAt(0) - "A".charCodeAt(0); + } + if (/[a-z]/.test(chr)) { + return chr.charCodeAt(0) - "a".charCodeAt(0) + 26; + } + if (/[0-9]/.test(chr)) { + return chr.charCodeAt(0) - "0".charCodeAt(0) + 52; + } + if (chr === "+") { + return 62; + } + if (chr === "/") { + return 63; + } + // Throw exception; should not be hit in tests + return undefined; +} + function extractJSFromHTA(s) { const root = parse("" + s); items = root.querySelectorAll('script'); @@ -108,7 +214,7 @@ var window = { moveTo: function(a,b){}, close: function(){}, atob: function(s){ - return new Buffer(s, 'base64').toString('ascii'); + return atob(s); }, setTimeout: function(f, i) {}, location: location, @@ -210,11 +316,6 @@ var document = { addEventListener: function(tag, func) {} }; -function atob(s) { - var b = new Buffer(s, 'base64'); - return b.toString(); -}; - class _WidgetInfo { constructor(a1, a2, a3, a4, a5) {} } From 363b7cd8c8df87db3c5bab782265cf51b5e685fd Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Sun, 2 Oct 2022 17:59:10 -0500 Subject: [PATCH 03/78] Return rc 0 when timeing out (could have analysis results). --- _run.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_run.js b/_run.js index 8a36042..368d5ee 100644 --- a/_run.js +++ b/_run.js @@ -150,7 +150,8 @@ function analyze(filepath, filename, cb) { if (!argv.preprocess) console.log("Hint: if the script is heavily obfuscated, --preprocess --unsafe-preprocess can speed up the emulation."); worker.kill(); - if (argv.debug) process.exit(2); + // Useful analysis may have occurred. + if (argv.debug) process.exit(0); cb(); }, timeout * 1000); From 702442d8c2901d8023b4ef6d11bc951234e7f4cd Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 4 Oct 2022 15:38:12 -0500 Subject: [PATCH 04/78] Some obfuscator handling. --- boilerplate.js | 6 ++++++ patch.js | 22 ++++++++++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index a64e4a5..52b3deb 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -335,3 +335,9 @@ var navigator = { Array.prototype.reduce = function(a, b) { throw "CScript JScript has no Array.reduce() method." }; + +Function.prototype.__toString = Function.prototype.toString; +Function.prototype.toString = function(){ + console.log("TOSTRING!!"); + return (this.__toString().replace(/\n/g, "")); +}; diff --git a/patch.js b/patch.js index d01dc9b..4cf22db 100644 --- a/patch.js +++ b/patch.js @@ -73,16 +73,18 @@ let _OriginalFnToString = Function.prototype.toString; Function.prototype.toString = function() { - /** - * WSH's toString() looks a bit different for built-in functions - * than result generated by Node.js (tabbed and wrapped with newlines) - * which is sometimes checked by malicious scripts. - */ - let source = _OriginalFnToString.call(this); - return source.replace( - /^function (\S+) { \[native code\] }$/, - ((m, fnName) => `\nfunction ${fnName} {\n [native code]\n}\n`) - ) + /** + * WSH's toString() looks a bit different for built-in functions + * than result generated by Node.js (tabbed and wrapped with newlines) + * which is sometimes checked by malicious scripts. + */ + let source = _OriginalFnToString.call(this); + let r = source.replace( + /^function (\S+) { \[native code\] }$/, + ((m, fnName) => `\nfunction ${fnName} {\n [native code]\n}\n`) + ) + // Some obfuscators flag funcs with newlines. + return r.replace(/\n/g, ""); } let _OriginalFunction = Function; From 09ff99f0307b359e891fbfb1b72e949d24367c4a Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 4 Oct 2022 15:58:30 -0500 Subject: [PATCH 05/78] More obfuscator handling. --- patch.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/patch.js b/patch.js index 4cf22db..c266765 100644 --- a/patch.js +++ b/patch.js @@ -84,7 +84,8 @@ ((m, fnName) => `\nfunction ${fnName} {\n [native code]\n}\n`) ) // Some obfuscators flag funcs with newlines. - return r.replace(/\n/g, ""); + r = r.replace(/\n/g, "").replace(/{ +/g, "{").replace(/ +}/g, "}"); + return r; } let _OriginalFunction = Function; From 6f09603414b0b5c269ff717ce6bd0a6cbe3a3a10 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 4 Oct 2022 16:24:31 -0500 Subject: [PATCH 06/78] Better exception reporting. --- analyze.js | 2 +- boilerplate.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/analyze.js b/analyze.js index 96ab993..8c9d3ff 100644 --- a/analyze.js +++ b/analyze.js @@ -543,7 +543,7 @@ if (argv["dangerous-vm"]) { vm.run(code); } catch (e) { lib.error("Sandbox execution failed:"); - lib.error(e); + lib.error(e.message); process.exit(1); } } diff --git a/boilerplate.js b/boilerplate.js index 52b3deb..bd95e5a 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -336,8 +336,8 @@ Array.prototype.reduce = function(a, b) { throw "CScript JScript has no Array.reduce() method." }; -Function.prototype.__toString = Function.prototype.toString; -Function.prototype.toString = function(){ - console.log("TOSTRING!!"); - return (this.__toString().replace(/\n/g, "")); -}; +// Stubbed out for now. +function setTimeout() {}; +function clearTimeout() {}; +function setInterval() {}; +function clearInterval() {}; From 8a1bc852e1986e4887ea72212f9e9e74452cbbe2 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 6 Oct 2022 13:34:36 -0500 Subject: [PATCH 07/78] Handle getting title of the result of getElementsByTagName(). --- boilerplate.js | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index bd95e5a..dc861d9 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -236,6 +236,31 @@ var window = { }, }; +function __getElementsByTagName(tag) { + var func = function(item) { + logIOC('DOM Append', {item}, "The script added a HTML node to the DOM"); + return ""; + }; + + // Return a dict that maps every tag name to the same fake element. + fake_dict = {}; + fake_dict = new Proxy(fake_dict, { + get(target, phrase) { // intercept reading a property from dictionary + return { + "appendChild" : func, + "insertBefore" : func, + "parentNode" : { + "appendChild" : func, + "insertBefore" : func, + }, + "getElementsByTagName" : __getElementsByTagName, + "title" : "My Fake Title", + }; + } + }); + return fake_dict; + } + var document = { documentMode: 8, // Fake running in IE8 referrer: 'https://bing.com/', @@ -278,28 +303,7 @@ var document = { logIOC('DOM Insert', {node}, "The script inserted an HTML node on the DOM") eval(extractJSFromHTA(node)); }, - getElementsByTagName: function(tag) { - var func = function(item) { - logIOC('DOM Append', {item}, "The script added a HTML node to the DOM"); - return ""; - }; - - // Return a dict that maps every tag name to the same fake element. - fake_dict = {}; - fake_dict = new Proxy(fake_dict, { - get(target, phrase) { // intercept reading a property from dictionary - return { - "appendChild" : func, - "insertBefore" : func, - "parentNode" : { - "appendChild" : func, - "insertBefore" : func, - }, - }; - } - }); - return fake_dict; - }, + getElementsByTagName: __getElementsByTagName, createElement: function(tag) { var fake_elem = { set src(url) { From d34815ff890b94ad951064e571d6df878f9b2c25 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 6 Oct 2022 15:08:18 -0500 Subject: [PATCH 08/78] Partial emulation of InternetExplorer.Application. --- analyze.js | 2 ++ emulator/InternetExplorerApplication.js | 16 ++++++++++++++++ emulator/WMI.js | 1 + 3 files changed, 19 insertions(+) create mode 100644 emulator/InternetExplorerApplication.js diff --git a/analyze.js b/analyze.js index 8c9d3ff..59c6dcc 100644 --- a/analyze.js +++ b/analyze.js @@ -580,6 +580,8 @@ function ActiveXObject(name) { return require("./emulator/Dictionary"); case "shell.application": return require("./emulator/ShellApplication"); + case "internetexplorer.application": + return require("./emulator/InternetExplorerApplication"); case "wscript.network": return require("./emulator/WScriptNetwork"); case "wscript.shell": diff --git a/emulator/InternetExplorerApplication.js b/emulator/InternetExplorerApplication.js new file mode 100644 index 0000000..dc73a4d --- /dev/null +++ b/emulator/InternetExplorerApplication.js @@ -0,0 +1,16 @@ +const lib = require("../lib"); + +function InternetExplorerApplication() { + this.navigate = function(url) { + lib.logUrl('IE URL Navigation', url); + } + this.busy = false; + this.readystate = 4; + this.document = { + "documentElement" : { + "outerText" : "_Loaded_IE_Doc_outerText_" + } + }; +} + +module.exports = lib.proxify(InternetExplorerApplication, "InternetExplorerApplication"); diff --git a/emulator/WMI.js b/emulator/WMI.js index 0df2c5b..231e448 100644 --- a/emulator/WMI.js +++ b/emulator/WMI.js @@ -333,6 +333,7 @@ module.exports.GetObject = function(name) { } */ return new Proxy({ + UserName: "_Fake_Box-JS_User_", InstancesOf: getTable, ExecQuery: query => { // TODO: implement actual SQL From d7fadecb84771f5ab8bc069765c13c30a1c040b8 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 11 Oct 2022 18:12:42 -0500 Subject: [PATCH 09/78] Initial checkin of loop rewriting functionality. --- analyze.js | 15 ++- flags.json | 7 +- loop_rewriter.js | 100 ++++++++++++++++++ patches/counter_while_loop.js | 189 ++++++++++++++++++++++++++++++++++ patches/except_while_loop.js | 62 +++++++++++ patches/typeof.js | 2 +- 6 files changed, 371 insertions(+), 4 deletions(-) create mode 100644 loop_rewriter.js create mode 100644 patches/counter_while_loop.js create mode 100644 patches/except_while_loop.js diff --git a/analyze.js b/analyze.js index 59c6dcc..f422a32 100644 --- a/analyze.js +++ b/analyze.js @@ -1,5 +1,6 @@ //const Blob = require("cross-blob"); const lib = require("./lib"); +const loop_rewriter = require("./loop_rewriter"); const escodegen = require("escodegen"); const acorn = require("acorn"); const fs = require("fs"); @@ -238,15 +239,24 @@ cc decoder.c -o decoder return; } + if (argv["rewrite-loops"]) { + lib.verbose(" Rewriting loops...", false); + traverse(tree, loop_rewriter.rewriteSimpleWaitLoop); + traverse(tree, loop_rewriter.rewriteSimpleControlLoop); + } + if (!argv["no-rewrite-prototype"]) { lib.verbose(" Replacing `function A.prototype.B()` (use --no-rewrite-prototype to skip)...", false); traverse(tree, function(key, val) { if (!val) return; + //console.log("----"); + //console.log(JSON.stringify(val, null, 2)); if (val.type !== "FunctionDeclaration" && val.type !== "FunctionExpression") return; if (!val.id) return; if (val.id.type !== "MemberExpression") return; - return require("./patches/prototype.js")(val); + r = require("./patches/prototype.js")(val); + return r; }); } @@ -302,8 +312,9 @@ cc decoder.c -o decoder }); } - // console.log(JSON.stringify(tree, null, "\t")); code = escodegen.generate(tree); + //console.log("!!!! CODE !!!!"); + //console.log(code); // The modifications may have resulted in more concatenations, eg. "a" + ("foo", "b") + "c" -> "a" + "b" + "c" if (argv["dumb-concat-simplify"]) { diff --git a/flags.json b/flags.json index 6ca70cf..0a1888b 100644 --- a/flags.json +++ b/flags.json @@ -146,6 +146,11 @@ "name": "dangerous-vm", "type": "Boolean", "description": "Use the `vm` module, rather than `vm2`. This sandbox can be broken, so **don't use this** unless you're 100% sure of what you're doing. Helps with debugging by giving correct stack traces." + }, + { + "name": "rewrite-loops", + "type": "Boolean", + "description": "Rewrite some types of loops to make analysis faster" } ], "export": [ @@ -237,4 +242,4 @@ "description": "Submit URLs to VirusTotal" } ] -} \ No newline at end of file +} diff --git a/loop_rewriter.js b/loop_rewriter.js new file mode 100644 index 0000000..d36e6d4 --- /dev/null +++ b/loop_rewriter.js @@ -0,0 +1,100 @@ +const escodegen = require("escodegen"); + +function rewriteSimpleWaitLoop(key, val) { + if (!val) return; + + // TODO: Currently only rewriting while() loops like + // 'while(x < y) { x = x + 1 }'. + + // While loop? + if (val.type != "WhileStatement") return; + // Simple loop guard? + if (val.test.type != "BinaryExpression") return; + if (val.test.left.type != "Identifier") return; + // Only handling "<" and "<=" for now. + if ((val.test.operator != "<") && (val.test.operator != "<=")) return; + // Single statement in the loop body? + if (val.body.type != "BlockStatement") return; + if (val.body.body.length != 1) return; + // Loop body statement is update to loop variable? + line = val.body.body[0]; + if (line.type != "ExpressionStatement") return; + line = line.expression; + if ((line.type != "AssignmentExpression") && (line.type != "UpdateExpression")) return; + if (line.type == "AssignmentExpression") { + if (line.left.type != "Identifier") return; + if (line.left.name != val.test.left.name) return; + if ((line.operator != "=") && (line.operator != "+=")) return; + }; + if (line.type == "UpdateExpression") { + if (line.argument.type != "Identifier") return; + if (line.operator != "++") return; + }; + + //console.log("----"); + //console.log(JSON.stringify(val, null, 2)); + r = require("./patches/counter_while_loop.js")(val); + //console.log("REWRITE!!"); + //console.log(JSON.stringify(r, null, 2)); + //console.log(escodegen.generate(r)); + return r; +} + +function rewriteSimpleControlLoop(key, val) { + if (!val) return; + + // While loop? + if (val.type != "WhileStatement") return; + + // 2 statements in the loop body? + if (val.body.type != "BlockStatement") return; + if (val.body.body.length != 2) return; + + // 1st loop body statement is a try/catch? + var line1 = val.body.body[0]; + if (line1.type != "TryStatement") return; + + // 1 statement in try block? + if (line1.block.type != "BlockStatement") return; + if (line1.block.body.length != 1) return; + line1 = line1.block.body[0]; + + // Possible calling funtion from array in try block? + if (line1.type != "ExpressionStatement") return; + line1 = line1.expression; + if (line1.type != "CallExpression") return; + if (line1.callee.type != "MemberExpression") return; + + // 1 statement in catch block. + var catch_line = val.body.body[0].handler; + if ((catch_line == undefined) || (catch_line.type != "CatchClause")) return; + var catch_body = catch_line.body; + if (catch_body.type != "BlockStatement") return; + if (catch_body.body.length != 1) return; + catch_body = catch_body.body[0]; + + // Catch statement should be an assignment. + if (catch_body.type != "ExpressionStatement") return; + if (catch_body.expression.type != "AssignmentExpression") return; + + // 2nd loop body statement an assignment? + var line2 = val.body.body[1]; + if (line2.type != "ExpressionStatement") return; + line2 = line2.expression; + if ((line2.type != "AssignmentExpression") && (line2.type != "UpdateExpression")) return; + + // We have a certain type of control flow loop. Rewrite it so that exceptions are not + // repeatedly thrown. + //console.log("----"); + //console.log(JSON.stringify(val, null, 2)); + r = require("./patches/except_while_loop.js")(val); + //console.log("REWRITE!!"); + //console.log(JSON.stringify(r, null, 2)); + //console.log(escodegen.generate(r)); + return r; +}; + +module.exports = { + rewriteSimpleWaitLoop, + rewriteSimpleControlLoop, +}; diff --git a/patches/counter_while_loop.js b/patches/counter_while_loop.js new file mode 100644 index 0000000..2b07623 --- /dev/null +++ b/patches/counter_while_loop.js @@ -0,0 +1,189 @@ +/* +'while (x < y) { x = x + z; }' becomes 'x = x + y * z;' + +Additionally marked as a candidate to hoist. +Needs prototype-plugin enabled. +*/ + +/* + For < loops, positive increment: + final_loop_counter = upper_bound + Math.sign((upper_bound-initial_loop_counter)%increment)*(increment-1) + + For <= loops, positive increment: + final_loop_counter = upper_bound + Math.sign((upper_bound-initial_loop_counter)%increment)*(increment-1) + Math.sign(!Math.sign((upper_bound-initial_loop_counter)%increment)); +*/ + +function MakeNot(expr) { + // {"type":"UnaryExpression","start":30,"end":32,"operator":"!","prefix":true,"argument":{"type":"Literal","start":31,"end":32,"value":1,"raw":"1"}} + return { + type: "UnaryExpression", + operator: "!", + argument: expr + }; +}; + +function MakeLiteral(value) { + return { + type: "Literal", + value: value + }; +}; + +function MakeBinaryExpression(lhs, rhs, op) { + // {"type":"BinaryExpression","start":30,"end":35,"left":{"type":"Identifier","start":30,"end":31,"name":"a"},"operator":"+","right":{"type":"Literal","start":34,"end":35,"value":1,"raw":"1"}} + return { + type: "BinaryExpression", + left: lhs, + right: rhs, + operator: op + }; +}; + +function MakeMemberExpression(object, property, args) { + /* + { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Math" + }, + "property": { + "type": "Identifier", + "name": "sign" + }, + "computed": false + }, + "arguments": [{ + "type": "Literal", + "value": 12, + }] + } + */ + return { + type: "CallExpression", + callee:{ + type: "MemberExpression", + object: {type: "Identifier", name: object}, + property: {type: "Identifier", name: property}, + }, + arguments: args + }; +}; + +function MakeMathSign(upperBound, initialCounter, increment) { + // Make Math.sign((upper_bound-initial_loop_counter)%increment) + return { + type: "CallExpression", + callee: { + type: "MemberExpression", + object: { + type: "Identifier", + name: "Math" + }, + property: { + type: "Identifier", + name: "sign" + }, + computed: false + }, + arguments: [{ + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: upperBound, + operator: "-", + right: initialCounter + }, + operator: "%", + right: increment + }] + }; +}; + +function PullIncrement(fexpr) { + + // Figure out if we have "x = x + z" or "x++". + line = fexpr.body.body[0].expression; + + // Pull loop counter increment value from expression in loop body. + var r; + if (line.type == "AssignmentExpression") { + var line = fexpr.body.body[0].expression; + var baseExpr; + var r; + if (line.operator == "="){ + var rhs = line.right; + if (rhs.left.name != fexpr.test.left.name) { + baseExpr = rhs.left; + } + else { + baseExpr = rhs.right; + } + r = baseExpr; + } + if (line.operator == "+="){ + r = line.right; + }; + }; + + if (line.type == "UpdateExpression") { + r = MakeLiteral(1); + }; + + // Done. + return r; +} + +function PullLoopUpperBound(fexpr) { + // Pull the upper bound from the while test. + return fexpr.test.right; +} + +function PullLoopCounter(fexpr) { + + // Pull the loop counter from the while test. + return fexpr.test.left; +} + +function GenFinalLoopVal(fexpr) { + /* + For < loops, positive increment: + upper_bound + Math.sign((upper_bound-initial_loop_counter)%increment)*(increment-1) + + For <= loops, positive increment: + upper_bound + Math.sign((upper_bound-initial_loop_counter)%increment)*(increment-1) + Math.sign(!Math.sign((upper_bound-initial_loop_counter)%increment)); + */ + var upperBound = PullLoopUpperBound(fexpr); + var loopCounter = PullLoopCounter(fexpr); + var increment = PullIncrement(fexpr); + // upper_bound + Math.sign((upper_bound-initial_loop_counter)%increment)*(increment-1) + var modExpr = MakeBinaryExpression( + MakeMathSign(upperBound, loopCounter, increment), + MakeBinaryExpression(increment, MakeLiteral(1), "-"), + "*" + ); + var r = MakeBinaryExpression(upperBound, modExpr, "+"); + if (fexpr.test.operator == "<=") { + // !(Math.sign((y - x) % z) * (z - 1)); + // upper_bound + Math.sign((upper_bound-initial_loop_counter)%increment)*(increment-1) + Math.sign(!Math.sign((upper_bound-initial_loop_counter)%increment)); + var modExpr1 = MakeBinaryExpression(MakeBinaryExpression(upperBound, loopCounter, "-"), increment, "%"); + var p0 = MakeMemberExpression("Math", "sign", [modExpr1]); + var p1 = MakeNot(p0); + var p2 = MakeMemberExpression("Math", "sign", [p1]); + r = MakeBinaryExpression(r, p2, "+"); + }; + return r; +} + +module.exports = (fexpr) => ({ + type: "ExpressionStatement", + "autogenerated": true, + expression: { + type: "AssignmentExpression", + operator: "=", + left: fexpr.test.left, + right: GenFinalLoopVal(fexpr) + } +}); diff --git a/patches/except_while_loop.js b/patches/except_while_loop.js new file mode 100644 index 0000000..ba8b6fe --- /dev/null +++ b/patches/except_while_loop.js @@ -0,0 +1,62 @@ +function MakeBinaryExpression(lhs, rhs, op) { + // {"type":"BinaryExpression","start":30,"end":35,"left":{"type":"Identifier","start":30,"end":31,"name":"a"},"operator":"+","right":{"type":"Literal","start":34,"end":35,"value":1,"raw":"1"}} + return { + type: "BinaryExpression", + left: lhs, + right: rhs, + operator: op + }; +}; + +function MakeLiteral(value) { + return { + type: "Literal", + value: value + }; +}; + +function MakeIfThen(test, body) { + return { + type: "IfStatement", + test: test, + consequent: body + }; +}; + +function GenSimpleLoop(fexpr) { + + // First just run the loop once to trigger the exception. + var oldBody = fexpr.body; + var tryStmt = oldBody.body[0]; + + // Do function calls only for defined entries in an array. + var tryBody = oldBody.body[0].block.body; + var arrayAcc = tryBody[0].expression.callee; + var undef = { + type: "Identifier", + name: "undefined" + }; + var ifTest = MakeBinaryExpression(arrayAcc, undef, "!="); + var funcCall = tryBody[0]; + var newIf = MakeIfThen(ifTest, funcCall); + + // In new loop body do guarded call followed by existing var update. + var loopBody = { + type: "BlockStatement", + body: [newIf, oldBody.body[1]] + }; + var newLoop = { + type: "WhileStatement", + test: fexpr.test, + body: loopBody + }; + + // Put it all together. + var r = { + type: "BlockStatement", + body: [tryStmt, newLoop] + }; + return r; +}; + +module.exports = (fexpr) => (GenSimpleLoop(fexpr)); diff --git a/patches/typeof.js b/patches/typeof.js index a91f1e6..b9faba4 100644 --- a/patches/typeof.js +++ b/patches/typeof.js @@ -110,4 +110,4 @@ module.exports = (foo) => ({ "expression": false, }, "arguments": [], -}); \ No newline at end of file +}); From 7216900fb8f3a89ded79aa360fb75d1c92eaf347 Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 12 Oct 2022 13:02:36 -0400 Subject: [PATCH 10/78] Tighter test on simple count loop check. --- loop_rewriter.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/loop_rewriter.js b/loop_rewriter.js index d36e6d4..ceb6f8b 100644 --- a/loop_rewriter.js +++ b/loop_rewriter.js @@ -28,15 +28,16 @@ function rewriteSimpleWaitLoop(key, val) { }; if (line.type == "UpdateExpression") { if (line.argument.type != "Identifier") return; + if (line.argument.name != val.test.left.name) return; if (line.operator != "++") return; }; - //console.log("----"); + console.log("----"); //console.log(JSON.stringify(val, null, 2)); r = require("./patches/counter_while_loop.js")(val); - //console.log("REWRITE!!"); + console.log("REWRITE WAIT!!"); //console.log(JSON.stringify(r, null, 2)); - //console.log(escodegen.generate(r)); + console.log(escodegen.generate(r)); return r; } @@ -85,12 +86,12 @@ function rewriteSimpleControlLoop(key, val) { // We have a certain type of control flow loop. Rewrite it so that exceptions are not // repeatedly thrown. - //console.log("----"); + console.log("----"); //console.log(JSON.stringify(val, null, 2)); r = require("./patches/except_while_loop.js")(val); - //console.log("REWRITE!!"); + console.log("REWRITE CONTROL!!"); //console.log(JSON.stringify(r, null, 2)); - //console.log(escodegen.generate(r)); + console.log(escodegen.generate(r)); return r; }; From 07ecc07b52147ed088b451b1868e9c07e19149dd Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Wed, 12 Oct 2022 16:16:36 -0500 Subject: [PATCH 11/78] Working loop rewriter. --- loop_rewriter.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/loop_rewriter.js b/loop_rewriter.js index ceb6f8b..aa84c16 100644 --- a/loop_rewriter.js +++ b/loop_rewriter.js @@ -8,14 +8,23 @@ function rewriteSimpleWaitLoop(key, val) { // While loop? if (val.type != "WhileStatement") return; + // Simple loop guard? if (val.test.type != "BinaryExpression") return; if (val.test.left.type != "Identifier") return; + + // Skip some benign loops we have trouble rewriting by checking the + // loop index variable. Specifically skip loops where the loop index is + // cardCountIndexFinal. + if (val.test.left.name == "cardCountIndexFinal") return; + // Only handling "<" and "<=" for now. if ((val.test.operator != "<") && (val.test.operator != "<=")) return; + // Single statement in the loop body? if (val.body.type != "BlockStatement") return; if (val.body.body.length != 1) return; + // Loop body statement is update to loop variable? line = val.body.body[0]; if (line.type != "ExpressionStatement") return; @@ -32,12 +41,12 @@ function rewriteSimpleWaitLoop(key, val) { if (line.operator != "++") return; }; - console.log("----"); + //console.log("----"); //console.log(JSON.stringify(val, null, 2)); r = require("./patches/counter_while_loop.js")(val); - console.log("REWRITE WAIT!!"); + //console.log("REWRITE WAIT!!"); //console.log(JSON.stringify(r, null, 2)); - console.log(escodegen.generate(r)); + //console.log(escodegen.generate(r)); return r; } @@ -86,12 +95,12 @@ function rewriteSimpleControlLoop(key, val) { // We have a certain type of control flow loop. Rewrite it so that exceptions are not // repeatedly thrown. - console.log("----"); + //console.log("----"); //console.log(JSON.stringify(val, null, 2)); r = require("./patches/except_while_loop.js")(val); - console.log("REWRITE CONTROL!!"); + //console.log("REWRITE CONTROL!!"); //console.log(JSON.stringify(r, null, 2)); - console.log(escodegen.generate(r)); + //console.log(escodegen.generate(r)); return r; }; From 75e99ba67388eefcfd48b69425b07c64a0eefea0 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 13 Oct 2022 14:30:13 -0500 Subject: [PATCH 12/78] Do loop rewriting before other code mosifications. --- analyze.js | 97 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/analyze.js b/analyze.js index f422a32..1d2ef4a 100644 --- a/analyze.js +++ b/analyze.js @@ -140,6 +140,56 @@ If you run into unexpected results, try uncommenting lines that look like code = code.replace(/"[ \r\n]*\+[ \r\n]*"/gm, ""); } + let tree; + try { + tree = acorn.parse(code, { + allowReturnOutsideFunction: true, // used when rewriting function bodies + plugins: { + // enables acorn plugin needed by prototype rewrite + JScriptMemberFunctionStatement: !argv["no-rewrite-prototype"], + }, + }); + } catch (e) { + lib.error("Couldn't parse with Acorn:"); + lib.error(e); + lib.error(""); + if (filename.match(/jse$/)) { + lib.error( + `This appears to be a JSE (JScript.Encode) file. +Please compile the decoder and decode it first: + +cc decoder.c -o decoder +./decoder ${filename} ${filename.replace(/jse$/, "js")} + +` + ); + } else { + lib.error( + // @@@ Emacs JS mode does not properly parse this block. + //`This doesn't seem to be a JavaScript/WScript file. + //If this is a JSE file (JScript.Encode), compile + //decoder.c and run it on the file, like this: + // + //cc decoder.c -o decoder + //./decoder ${filename} ${filename}.js + // + //` + "Decode JSE. 'cc decoder.c -o decoder'. './decoder ${filename} ${filename}.js'" + ); + } + process.exit(4); + return; + } + + // Loop rewriting is looking for loops in the original unmodified code so + // do this before any other modifications. + if (argv["rewrite-loops"]) { + lib.verbose(" Rewriting loops...", false); + traverse(tree, loop_rewriter.rewriteSimpleWaitLoop); + traverse(tree, loop_rewriter.rewriteSimpleControlLoop); + } + + if (argv.preprocess) { lib.verbose(` Preprocessing with uglify-es v${require("uglify-es/package.json").version} (remove --preprocess to skip)...`, false); const unsafe = !!argv["unsafe-preprocess"]; @@ -197,53 +247,6 @@ If you run into unexpected results, try uncommenting lines that look like code = result.code; } } - - let tree; - try { - tree = acorn.parse(code, { - allowReturnOutsideFunction: true, // used when rewriting function bodies - plugins: { - // enables acorn plugin needed by prototype rewrite - JScriptMemberFunctionStatement: !argv["no-rewrite-prototype"], - }, - }); - } catch (e) { - lib.error("Couldn't parse with Acorn:"); - lib.error(e); - lib.error(""); - if (filename.match(/jse$/)) { - lib.error( - `This appears to be a JSE (JScript.Encode) file. -Please compile the decoder and decode it first: - -cc decoder.c -o decoder -./decoder ${filename} ${filename.replace(/jse$/, "js")} - -` - ); - } else { - lib.error( - // @@@ Emacs JS mode does not properly parse this block. - //`This doesn't seem to be a JavaScript/WScript file. - //If this is a JSE file (JScript.Encode), compile - //decoder.c and run it on the file, like this: - // - //cc decoder.c -o decoder - //./decoder ${filename} ${filename}.js - // - //` - "Decode JSE. 'cc decoder.c -o decoder'. './decoder ${filename} ${filename}.js'" - ); - } - process.exit(4); - return; - } - - if (argv["rewrite-loops"]) { - lib.verbose(" Rewriting loops...", false); - traverse(tree, loop_rewriter.rewriteSimpleWaitLoop); - traverse(tree, loop_rewriter.rewriteSimpleControlLoop); - } if (!argv["no-rewrite-prototype"]) { lib.verbose(" Replacing `function A.prototype.B()` (use --no-rewrite-prototype to skip)...", false); From 488cbe3aa260344b0364cfb89242210c58a846e5 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Mon, 17 Oct 2022 12:35:25 -0500 Subject: [PATCH 13/78] Properly save base64 decoded samples to disk. --- emulator/DOM.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emulator/DOM.js b/emulator/DOM.js index de93953..d87c6ef 100644 --- a/emulator/DOM.js +++ b/emulator/DOM.js @@ -12,7 +12,7 @@ module.exports = function(name) { switch (name) { case "nodetypedvalue": if (target.dataType !== "bin.base64") return target.text; - return new Buffer(target.text, "base64").toString("utf8"); + return new Buffer(target.text, "base64"); default: if (name in target) return target[name]; lib.kill(`VirtualDOMTag.${name} not implemented!`); From be98d7499a883a16c2732a28d82d772eaf705ff6 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Mon, 17 Oct 2022 16:39:41 -0500 Subject: [PATCH 14/78] Better shortcut handling. --- analyze.js | 2 +- emulator/ADODBStream.js | 1 + emulator/FileSystemObject.js | 2 ++ emulator/WScriptShell.js | 17 +++++++++++++++-- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/analyze.js b/analyze.js index 1d2ef4a..91a357a 100644 --- a/analyze.js +++ b/analyze.js @@ -7,7 +7,6 @@ const fs = require("fs"); const iconv = require("iconv-lite"); const path = require("path"); const {VM} = require("vm2"); -//const {NodeVM} = require('vm2'); const child_process = require("child_process"); const argv = require("./argv.js").run; const jsdom = require("jsdom").JSDOM; @@ -557,6 +556,7 @@ if (argv["dangerous-vm"]) { vm.run(code); } catch (e) { lib.error("Sandbox execution failed:"); + console.log(e.stack); lib.error(e.message); process.exit(1); } diff --git a/emulator/ADODBStream.js b/emulator/ADODBStream.js index 3f277e3..0ef084d 100644 --- a/emulator/ADODBStream.js +++ b/emulator/ADODBStream.js @@ -34,6 +34,7 @@ function ADODBStream() { this.open = () => {}; this.savetofile = function(filename) { this.virtual_filename = filename; + console.log(filename); lib.writeFile(filename, this.buffer); lib.logResource(lib.getUUID(), this.virtual_filename, this.buffer, true); }; diff --git a/emulator/FileSystemObject.js b/emulator/FileSystemObject.js index 3f2bae8..aa3b713 100644 --- a/emulator/FileSystemObject.js +++ b/emulator/FileSystemObject.js @@ -120,6 +120,7 @@ function FileSystemObject() { if (value) { lib.info(`Returning true for FileSystemObject.FileExists(${path}); use --no-file-exists if nothing happens`); } + lib.logIOC("FileExists", path, "The script checked to see if a file exists."); return value; }; this.folderexists = (path) => { @@ -127,6 +128,7 @@ function FileSystemObject() { if (value) { lib.info(`Returning true for FileSystemObject.FolderExists(${path}); use --no-folder-exists if nothing happens`); } + lib.logIOC("FolderExists", path, "The script checked to see if a folder exists."); return value; }; this.getabsolutepathname = (path) => { diff --git a/emulator/WScriptShell.js b/emulator/WScriptShell.js index c98258e..b8e7940 100644 --- a/emulator/WScriptShell.js +++ b/emulator/WScriptShell.js @@ -47,7 +47,20 @@ function WScriptShell() { this.environment1 = undefined; this.specialfolders = (x) => `(Special folder ${x})`; - this.createshortcut = () => ({}); + this.createshortcut = (x) => ({ + name: x, + save: function() { + var name = "???"; + if (typeof(this.name) !== "undefined") { + name = this.name; + }; + var cmd = "???"; + if ((typeof(this.targetPath) !== "undefined") && (typeof(this.arguments) !== "undefined")) { + cmd = "" + this.targetPath + " " + this.arguments; + } + lib.logIOC("CreateShortcut", {name: name, cmd: cmd}, "The script saved a shortcut."); + } + }); this.expandenvironmentstrings = (path) => { Object.keys(vars).forEach(key => { @@ -55,7 +68,7 @@ function WScriptShell() { if (!regex.test(path)) return; - lib.info(`Script read environment variable ${key}`); + lib.logIOC("Environ", key, "The script read an environment variable"); path = path.replace(regex, vars[key]); }); From 05b876d88be6582247b0588ddb9f6c26c19e2cd3 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 18 Oct 2022 09:42:39 -0500 Subject: [PATCH 15/78] Some bug fixes and better IOC reporting. --- analyze.js | 2 +- emulator/ADODBConnection.js | 7 ++----- emulator/ADODBStream.js | 3 +-- emulator/FileSystemObject.js | 2 +- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/analyze.js b/analyze.js index 91a357a..027d8b6 100644 --- a/analyze.js +++ b/analyze.js @@ -64,7 +64,7 @@ function rewrite(code) { // box-js is assuming that the JS will be run on Windows with cscript or wscript. // Neither of these engines supports strict JS mode, so remove those calls from // the code. - code = code.replace(/"use strict"/g, '"STRICT MODE NOT SUPPORTED"'); + code = code.toString().replace(/"use strict"/g, '"STRICT MODE NOT SUPPORTED"'); // Some samples (for example that use JQuery libraries as a basis to which to // add malicious code) won't emulate properly for some reason if there is not diff --git a/emulator/ADODBConnection.js b/emulator/ADODBConnection.js index 765011a..c3ae782 100755 --- a/emulator/ADODBConnection.js +++ b/emulator/ADODBConnection.js @@ -4,14 +4,11 @@ const iconv = require("iconv-lite"); function ADODBConnection() { this.open = function(query, conn) { - console.log("adodb.connection open()"); - console.log(query); - console.log(conn); + log.logIOC("ADODBConnection", {"query": query}, "The script opened an ADODB connection."); }; this.cursorlocation1 = function(arg) { - console.log("adodb.connection cursorlocation()"); - console.log(arg); + log.logIOC("ADODBConnection", {"arg": arg}, "The script called ADODB cursor location."); }; this.close = () => {}; diff --git a/emulator/ADODBStream.js b/emulator/ADODBStream.js index 0ef084d..d091e41 100644 --- a/emulator/ADODBStream.js +++ b/emulator/ADODBStream.js @@ -34,7 +34,7 @@ function ADODBStream() { this.open = () => {}; this.savetofile = function(filename) { this.virtual_filename = filename; - console.log(filename); + lib.logIOC("ADODBStream", {"name": filename}, "The script wrote a file."); lib.writeFile(filename, this.buffer); lib.logResource(lib.getUUID(), this.virtual_filename, this.buffer, true); }; @@ -55,7 +55,6 @@ function ADODBStream() { this.buffer = lib.readFile(filename); }; this.tojson = function(data) { - console.log(data); return "[1]"; }; this.flush = function() {}; diff --git a/emulator/FileSystemObject.js b/emulator/FileSystemObject.js index aa3b713..9e94008 100644 --- a/emulator/FileSystemObject.js +++ b/emulator/FileSystemObject.js @@ -134,7 +134,7 @@ function FileSystemObject() { this.getabsolutepathname = (path) => { if (!winpath.isAbsolute(path)) path = "C:\\Users\\User\\Desktop\\" + path; const ret = winpath.resolve(path); - console.log(path, ret); + lib.logIOC("FileSystemObject", {"path": path, "absolute": ret}, "The script got an absolute path."); return ret; }; this.getdrive = (drive) => new ProxiedDrive(drive); From 989ead5ac24f3a761eb3a4acbde2a6c37c076d6a Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 25 Oct 2022 13:26:13 -0500 Subject: [PATCH 16/78] Initial support for XMLHttpRequest objects. --- boilerplate.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index dc861d9..c85451f 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -1,4 +1,5 @@ const parse = require("node-html-parser").parse; +const lib = require("./lib.js"); // atob() taken from abab.atob.js . @@ -217,6 +218,8 @@ var window = { return atob(s); }, setTimeout: function(f, i) {}, + addEventListener: function(){}, + attachEvent: function(){}, location: location, localStorage: { // Users and session to distinguish and generate statistics about website traffic. @@ -236,6 +239,9 @@ var window = { }, }; +var screen = { +}; + function __getElementsByTagName(tag) { var func = function(item) { logIOC('DOM Append', {item}, "The script added a HTML node to the DOM"); @@ -345,3 +351,20 @@ function setTimeout() {}; function clearTimeout() {}; function setInterval() {}; function clearInterval() {}; + +class XMLHttpRequest { + constructor(){ + this.method = null; + this.url = null; + }; + + addEventListener() {}; + + open(method, url) { + this.method = method; + this.url = url; + lib.logIOC("XMLHttpRequest", {method: method, url: url}, "The script opened a HTTP request."); + }; + + send() {}; +}; From f143f272ee189c843023fe3941cdbae76080d713 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 25 Oct 2022 14:26:36 -0500 Subject: [PATCH 17/78] Track URLs from XMLHttpRequest.open(). --- boilerplate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/boilerplate.js b/boilerplate.js index c85451f..aad81c2 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -364,6 +364,7 @@ class XMLHttpRequest { this.method = method; this.url = url; lib.logIOC("XMLHttpRequest", {method: method, url: url}, "The script opened a HTTP request."); + lib.logUrl("XMLHttpRequest", url); }; send() {}; From 21fe6bccb7fffe8b656d007b866f0ce2547ed59a Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 25 Oct 2022 15:25:42 -0500 Subject: [PATCH 18/78] Start of stubbing out jQuery. --- boilerplate.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index aad81c2..6fbd5ad 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -241,6 +241,18 @@ var window = { var screen = { }; +// Initial jQuery stubbing. +var onDict = { + on: function(){ return onDict }, +}; +var jQuery = function(){ + return onDict; +}; +jQuery.jquery = "3.6.1"; +jQuery.fn = { + jquery: "3.6.1" +}; +jQuery.extend = function() { return {}; }; function __getElementsByTagName(tag) { var func = function(item) { From 1e52b722495e541e2305728bb52a151d321bb1eb Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 26 Oct 2022 12:24:44 -0400 Subject: [PATCH 19/78] Added initial XMLHttpRequest and jQuery support. --- boilerplate.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index dc861d9..230e6a2 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -1,4 +1,5 @@ const parse = require("node-html-parser").parse; +const lib = require("./lib.js"); // atob() taken from abab.atob.js . @@ -217,6 +218,8 @@ var window = { return atob(s); }, setTimeout: function(f, i) {}, + addEventListener: function(){}, + attachEvent: function(){}, location: location, localStorage: { // Users and session to distinguish and generate statistics about website traffic. @@ -236,6 +239,21 @@ var window = { }, }; +var screen = { +}; +// Initial jQuery stubbing. +var onDict = { + on: function(){ return onDict }, +}; +var jQuery = function(){ + return onDict; +}; +jQuery.jquery = "2.6.1"; +jQuery.fn = { + jquery: "2.6.1" +}; +jQuery.extend = function() { return {}; }; + function __getElementsByTagName(tag) { var func = function(item) { logIOC('DOM Append', {item}, "The script added a HTML node to the DOM"); @@ -345,3 +363,21 @@ function setTimeout() {}; function clearTimeout() {}; function setInterval() {}; function clearInterval() {}; + +class XMLHttpRequest { + constructor(){ + this.method = null; + this.url = null; + }; + + addEventListener() {}; + + open(method, url) { + this.method = method; + this.url = url; + lib.logIOC("XMLHttpRequest", {method: method, url: url}, "The script opened a HTTP request."); + lib.logUrl("XMLHttpRequest", url); + }; + + send() {}; +}; From 86fa9cf8ef9bf07901e419deca7e66c0b1a56414 Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 26 Oct 2022 13:40:04 -0400 Subject: [PATCH 20/78] ShareLink(??) object. --- boilerplate.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index 230e6a2..1c472ff 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -241,6 +241,10 @@ var window = { var screen = { }; + +var ShareLink = { +}; + // Initial jQuery stubbing. var onDict = { on: function(){ return onDict }, From 293429ee982998c585e53faef5ce187d1f531fd2 Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 26 Oct 2022 14:10:40 -0400 Subject: [PATCH 21/78] Added stubbed define() function. --- boilerplate.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index 1c472ff..97c21d8 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -239,13 +239,19 @@ var window = { }, }; +// Initial stubbed object. Add items a needed. var screen = { }; +// Initial stubbed object. Add items a needed. var ShareLink = { }; -// Initial jQuery stubbing. +// Initial stubbed function. Add items a needed. +function define() {}; +define.amd = true; + +// Initial jQuery stubbing. Add items a needed. var onDict = { on: function(){ return onDict }, }; @@ -332,7 +338,9 @@ var document = { logIOC('Remote Script', {url}, "The script set a remote script source."); logUrl('Remote Script', {url}); }, - log: [] + log: [], + style: [], + appendChild: function() {}, }; return fake_elem; }, From b6e1362a437dabac7e486ef0838b5f26e3463aac Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 26 Oct 2022 14:27:06 -0400 Subject: [PATCH 22/78] Stubbed adjustIFrames() function. --- boilerplate.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index 97c21d8..38ec845 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -251,12 +251,18 @@ var ShareLink = { function define() {}; define.amd = true; +// Initial stubbed function. Add items a needed. +function adjustIframes() {}; + // Initial jQuery stubbing. Add items a needed. -var onDict = { - on: function(){ return onDict }, +var funcDict = { + on: function(){ return funcDict }, + val: function() {}, + scroll: function() {}, + ready: function() {}, }; var jQuery = function(){ - return onDict; + return funcDict; }; jQuery.jquery = "2.6.1"; jQuery.fn = { From 47602c784364910347ad00ddd33372e96752a57b Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 26 Oct 2022 14:36:14 -0400 Subject: [PATCH 23/78] Stubbed document.documentElement. --- boilerplate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/boilerplate.js b/boilerplate.js index 38ec845..b87f6bf 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -325,6 +325,7 @@ var document = { innerHTML: "" } }, + documentElement: {}, write: function (content) { logIOC('DOM Write', {content}, 'The script wrote to the DOM') eval.apply(null, [extractJSFromHTA(content)]); From da9758edea5843b20395514c7f26b4f3b0e04742 Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 26 Oct 2022 15:13:28 -0400 Subject: [PATCH 24/78] Some initial very limited Webpack stubbing. --- boilerplate.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index b87f6bf..8b042d1 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -270,6 +270,10 @@ jQuery.fn = { }; jQuery.extend = function() { return {}; }; +// Initial WebPack stubbing. +globalThis.location = "http://mylegitdomain.com:2112/and/i/have/a/path.php"; +globalThis.importScripts = true; + function __getElementsByTagName(tag) { var func = function(item) { logIOC('DOM Append', {item}, "The script added a HTML node to the DOM"); From f78d51aaa7c9240bb66e4770594560772511757c Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 26 Oct 2022 15:55:10 -0400 Subject: [PATCH 25/78] Stubbed window.getComputedStyle(). --- boilerplate.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index 8b042d1..066be50 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -220,6 +220,10 @@ var window = { setTimeout: function(f, i) {}, addEventListener: function(){}, attachEvent: function(){}, + getComputedStyle: function(){ + return ["??", + "-moz-"]; + }, location: location, localStorage: { // Users and session to distinguish and generate statistics about website traffic. From 5cce195f37fc750edb578c1600a535e9c8eae1b7 Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 26 Oct 2022 17:49:14 -0400 Subject: [PATCH 26/78] More jScript stubbing. --- boilerplate.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boilerplate.js b/boilerplate.js index 066be50..84fc581 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -270,7 +270,8 @@ var jQuery = function(){ }; jQuery.jquery = "2.6.1"; jQuery.fn = { - jquery: "2.6.1" + jquery: "2.6.1", + extend: function() {}, }; jQuery.extend = function() { return {}; }; From 4603d7f1b1cb1618d7b16f234f66ee210e67f089 Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 26 Oct 2022 18:01:10 -0400 Subject: [PATCH 27/78] More jQuery stubbing. --- boilerplate.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/boilerplate.js b/boilerplate.js index 84fc581..165d82c 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -264,6 +264,8 @@ var funcDict = { val: function() {}, scroll: function() {}, ready: function() {}, + load: function() {}, + extend: function() { return {}; }, }; var jQuery = function(){ return funcDict; @@ -271,7 +273,7 @@ var jQuery = function(){ jQuery.jquery = "2.6.1"; jQuery.fn = { jquery: "2.6.1", - extend: function() {}, + extend: function() { return {}; }, }; jQuery.extend = function() { return {}; }; From 17e05a38d9b41e4c00006f904eedff4b1a8a0b7f Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 26 Oct 2022 18:22:32 -0400 Subject: [PATCH 28/78] Added some missing variable. --- boilerplate.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index 165d82c..ca049ee 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -255,6 +255,10 @@ var ShareLink = { function define() {}; define.amd = true; +// This could be due to a bug in a sample, but added this to +// get analysis to work. +wp = {}; + // Initial stubbed function. Add items a needed. function adjustIframes() {}; From 5f0464bbb1ae3c8124266c466ba055e735f28fc8 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 09:26:45 -0500 Subject: [PATCH 29/78] Added some stub info to get a sample to analyze. --- boilerplate.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index ca049ee..293f08f 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -258,6 +258,11 @@ define.amd = true; // This could be due to a bug in a sample, but added this to // get analysis to work. wp = {}; +wprentals_map_general_start_map = function() {}; +googlecode_property_vars = {}; +wprentals_map_general_cluster = function() {}; +wprentals_map_general_spiderfy = function() {}; +wpestate_initialize_poi = function() {}; // Initial stubbed function. Add items a needed. function adjustIframes() {}; @@ -270,6 +275,7 @@ var funcDict = { ready: function() {}, load: function() {}, extend: function() { return {}; }, + attr: function(field) { return ".attr(" + field + ")"; }, }; var jQuery = function(){ return funcDict; From 0b674dc816b09b8778fc70cfabee01ea26ab7860 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 10:09:41 -0500 Subject: [PATCH 30/78] hasClass() stub. --- boilerplate.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index 293f08f..0ee403d 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -255,14 +255,15 @@ var ShareLink = { function define() {}; define.amd = true; -// This could be due to a bug in a sample, but added this to -// get analysis to work. +// These could be due to a bug in a sample, but added this to +// get analysis to work. Also could be missing globals from other scripts. wp = {}; wprentals_map_general_start_map = function() {}; googlecode_property_vars = {}; wprentals_map_general_cluster = function() {}; wprentals_map_general_spiderfy = function() {}; wpestate_initialize_poi = function() {}; +Codevz_Plus = {}; // Initial stubbed function. Add items a needed. function adjustIframes() {}; @@ -276,6 +277,8 @@ var funcDict = { load: function() {}, extend: function() { return {}; }, attr: function(field) { return ".attr(" + field + ")"; }, + codevzPlus: function() {}, + hasClass: function() { return false; }, }; var jQuery = function(){ return funcDict; @@ -319,6 +322,7 @@ function __getElementsByTagName(tag) { var document = { documentMode: 8, // Fake running in IE8 referrer: 'https://bing.com/', + body: {}, location: location, //parentNode: window.document.parentNode, getElementById : function(id) { From 9e7e63ca1c12a8972bbffe466c40104fb06da8ef Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 10:42:50 -0500 Subject: [PATCH 31/78] More jQuery stubbing. --- boilerplate.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index 0ee403d..6f2a561 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -279,6 +279,25 @@ var funcDict = { attr: function(field) { return ".attr(" + field + ")"; }, codevzPlus: function() {}, hasClass: function() { return false; }, + attr: function() {}, + attrHooks: { + value: { + get: function() {}, + set: function() {}, + }, + }, + support: { + boxModel: false, + }, + boxModel: false, + ajaxSetup: function() {}, + event: { + add: function() {}, + remove: function() {}, + trigger: function() {}, + special: {}, + }, + each: function() {}, }; var jQuery = function(){ return funcDict; @@ -287,8 +306,31 @@ jQuery.jquery = "2.6.1"; jQuery.fn = { jquery: "2.6.1", extend: function() { return {}; }, + toggle: function() {}, + live: function() {}, + die: function() {}, + load: function() {}, }; jQuery.extend = function() { return {}; }; +jQuery.attr = function() {}; +jQuery.attrHooks = { + value: { + get: function() {}, + set: function() {}, + }, +}; +jQuery.support = { + boxModel: false, +}; +jQuery.boxModel = false; +jQuery.ajaxSetup = function() {}; +jQuery.event = { + add: function() {}, + remove: function() {}, + trigger: function() {}, + special: {}, +}; +jQuery.each = function() {}; // Initial WebPack stubbing. globalThis.location = "http://mylegitdomain.com:2112/and/i/have/a/path.php"; From c68f8756cae38fc2bed7ffdfacfb6ec4a149ebdd Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 10:49:36 -0500 Subject: [PATCH 32/78] More jQuery stubbing. --- boilerplate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/boilerplate.js b/boilerplate.js index 6f2a561..874a689 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -298,6 +298,7 @@ var funcDict = { special: {}, }, each: function() {}, + one: function() {}, }; var jQuery = function(){ return funcDict; From 41fcd6e8e1b77f6f7337070d72fc2750b38d642b Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 11:04:06 -0500 Subject: [PATCH 33/78] More jQuery stubbing. --- boilerplate.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index 874a689..b0d67c0 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -311,6 +311,10 @@ jQuery.fn = { live: function() {}, die: function() {}, load: function() {}, + revolution: { + is_mobile: function() {}, + is_android: function() {}, + }, }; jQuery.extend = function() { return {}; }; jQuery.attr = function() {}; From 0202834f257a45970d4c87024e3b8799b3e04826 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 11:10:25 -0500 Subject: [PATCH 34/78] More jQuery stubbing. --- boilerplate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/boilerplate.js b/boilerplate.js index b0d67c0..f2c959a 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -299,6 +299,7 @@ var funcDict = { }, each: function() {}, one: function() {}, + mouseup: function() {}, }; var jQuery = function(){ return funcDict; From 92344ceaa628aa68d0b7bbdcdbe528d7705ee922 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 11:28:40 -0500 Subject: [PATCH 35/78] More jQuery stubbing. --- boilerplate.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index f2c959a..8fabba3 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -300,6 +300,7 @@ var funcDict = { each: function() {}, one: function() {}, mouseup: function() {}, + isFunction: function() {}, }; var jQuery = function(){ return funcDict; @@ -337,6 +338,7 @@ jQuery.event = { special: {}, }; jQuery.each = function() {}; +jQuery.isFunction = function() {}; // Initial WebPack stubbing. globalThis.location = "http://mylegitdomain.com:2112/and/i/have/a/path.php"; From ba164a39942649dabe3878ce79a097506ad3c217 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 14:04:17 -0500 Subject: [PATCH 36/78] More jQuery stubbing. --- boilerplate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/boilerplate.js b/boilerplate.js index 8fabba3..154364b 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -339,6 +339,7 @@ jQuery.event = { }; jQuery.each = function() {}; jQuery.isFunction = function() {}; +window.jQuery = jQuery // Initial WebPack stubbing. globalThis.location = "http://mylegitdomain.com:2112/and/i/have/a/path.php"; From 82ba80d15524ce8f8459d35925028cdbd3c9702e Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 14:22:31 -0500 Subject: [PATCH 37/78] More jQuery stubbing. --- boilerplate.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index 154364b..4dada12 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -301,6 +301,12 @@ var funcDict = { one: function() {}, mouseup: function() {}, isFunction: function() {}, + data: function() { return "12"; }, + outerHeight: function() {}, + css: function() {}, + // Probably not jQuery + avia_sc_messagebox: function() {}, + trigger: function() {}, }; var jQuery = function(){ return funcDict; @@ -339,6 +345,11 @@ jQuery.event = { }; jQuery.each = function() {}; jQuery.isFunction = function() {}; +jQuery.expr = { + pseudos: {}, +}; + +// Looks like that can be a window field. window.jQuery = jQuery // Initial WebPack stubbing. From b531e87d828277a465291a1e19d46d80f2d6a1bb Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 14:33:39 -0500 Subject: [PATCH 38/78] More jQuery stubbing. --- boilerplate.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/boilerplate.js b/boilerplate.js index 4dada12..dbe6143 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -307,10 +307,13 @@ var funcDict = { // Probably not jQuery avia_sc_messagebox: function() {}, trigger: function() {}, + width: function() {}, }; var jQuery = function(){ return funcDict; }; + +// Global object form of jQuery. jQuery.jquery = "2.6.1"; jQuery.fn = { jquery: "2.6.1", @@ -412,7 +415,10 @@ var document = { innerHTML: "" } }, - documentElement: {}, + documentElement: { + style: {}, + className: "", + }, write: function (content) { logIOC('DOM Write', {content}, 'The script wrote to the DOM') eval.apply(null, [extractJSFromHTA(content)]); From 9d328adc3da572ef764a266cb5da7da2d76da0cf Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 14:37:12 -0500 Subject: [PATCH 39/78] More jQuery stubbing. --- boilerplate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/boilerplate.js b/boilerplate.js index dbe6143..885bca9 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -326,6 +326,7 @@ jQuery.fn = { is_mobile: function() {}, is_android: function() {}, }, + smoothScroll: {}, }; jQuery.extend = function() { return {}; }; jQuery.attr = function() {}; From 9205af37afb20e8ec475b002720b98d216556efb Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 14:40:35 -0500 Subject: [PATCH 40/78] More jQuery stubbing. --- boilerplate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/boilerplate.js b/boilerplate.js index 885bca9..ed9392d 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -308,6 +308,7 @@ var funcDict = { avia_sc_messagebox: function() {}, trigger: function() {}, width: function() {}, + resize: function() {}, }; var jQuery = function(){ return funcDict; From 80df4ca5ce253a81c96f43a673873c87e993ad91 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 14:48:21 -0500 Subject: [PATCH 41/78] window object stubbing. --- boilerplate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/boilerplate.js b/boilerplate.js index ed9392d..2628559 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -214,6 +214,7 @@ var window = { resizeTo: function(a,b){}, moveTo: function(a,b){}, close: function(){}, + matchMedia: function(){ return {}; }, atob: function(s){ return atob(s); }, From ece887ba0b59b565fe5eb8c043e76a85403fec97 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 14:56:19 -0500 Subject: [PATCH 42/78] MediaElementPlayer and mejs module stubbing. --- boilerplate.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index 2628559..d8c3508 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -209,6 +209,7 @@ var location = { reload: function() {}, }; +// Stubbed global window object. var window = { eval: function(cmd) { eval(cmd); }, resizeTo: function(a,b){}, @@ -270,6 +271,8 @@ Codevz_Plus = {}; function adjustIframes() {}; // Initial jQuery stubbing. Add items a needed. + +// Function form of jQuery(). var funcDict = { on: function(){ return funcDict }, val: function() {}, @@ -362,6 +365,17 @@ window.jQuery = jQuery globalThis.location = "http://mylegitdomain.com:2112/and/i/have/a/path.php"; globalThis.importScripts = true; +// Mejs module stubbing. +var mejs = { + plugins: {}, + Utils: {}, +}; + +// MediaElementPlayer module stubbing. +var MediaElementPlayer = { + prototype: {}, +}; + function __getElementsByTagName(tag) { var func = function(item) { logIOC('DOM Append', {item}, "The script added a HTML node to the DOM"); From 9e0e86bf17c140b03bcf62b42edaad9b7b66e4f3 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 15:03:43 -0500 Subject: [PATCH 43/78] Stubbed out some weird functions. --- boilerplate.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boilerplate.js b/boilerplate.js index d8c3508..37f2574 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -376,6 +376,9 @@ var MediaElementPlayer = { prototype: {}, }; +// What is this? +var N2R = N2D = function() {}; + function __getElementsByTagName(tag) { var func = function(item) { logIOC('DOM Append', {item}, "The script added a HTML node to the DOM"); From db7e0dbd71899ed95f47a1d4ebe618a60b81e302 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 15:11:36 -0500 Subject: [PATCH 44/78] Start of Element class stubbing. --- boilerplate.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index 37f2574..3d00233 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -379,6 +379,11 @@ var MediaElementPlayer = { // What is this? var N2R = N2D = function() {}; +// No Element class in node-js. +class Element { + constructor() {}; +}; + function __getElementsByTagName(tag) { var func = function(item) { logIOC('DOM Append', {item}, "The script added a HTML node to the DOM"); @@ -471,18 +476,18 @@ var document = { }; class _WidgetInfo { - constructor(a1, a2, a3, a4, a5) {} -} + constructor(a1, a2, a3, a4, a5) {}; +}; var _WidgetManager = { _Init: function(a1, a2, a3) {}, _SetDataContext: function(a1) {}, - _RegisterWidget: function(a1, a2) {} -} + _RegisterWidget: function(a1, a2) {}, +}; var navigator = { - userAgent: 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; Tablet PC 2.0; InfoPath.3)' -} + userAgent: 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; Tablet PC 2.0; InfoPath.3)', +}; // We are acting like cscript when emulating. JS in cscript does not // implement Array.reduce(). From aba9d113f7f4e91fc674d8ff02b87fc02cf86bcb Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 16:45:13 -0500 Subject: [PATCH 45/78] Lots of DOM stubbing. --- analyze.js | 1 + boilerplate.js | 219 ++++++++++++++++++++++++++++--------------------- 2 files changed, 128 insertions(+), 92 deletions(-) diff --git a/analyze.js b/analyze.js index 027d8b6..d8d95db 100644 --- a/analyze.js +++ b/analyze.js @@ -524,6 +524,7 @@ require("util").inspect.defaultOptions.customInspect = false; if (argv["dangerous-vm"]) { lib.verbose("Analyzing with native vm module (dangerous!)"); const vm = require("vm"); + console.log(code); vm.runInNewContext(code, sandbox, { displayErrors: true, // lineOffset: -fs.readFileSync(path.join(__dirname, "patch.js"), "utf8").split("\n").length, diff --git a/boilerplate.js b/boilerplate.js index 3d00233..a924633 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -209,6 +209,128 @@ var location = { reload: function() {}, }; +function __getElementsByTagName(tag) { + var func = function(item) { + logIOC('DOM Append', {item}, "The script added a HTML node to the DOM"); + return ""; + }; + + // Return a dict that maps every tag name to the same fake element. + fake_dict = {}; + fake_dict = new Proxy(fake_dict, { + get(target, phrase) { // intercept reading a property from dictionary + return { + "appendChild" : func, + "insertBefore" : func, + "parentNode" : { + "appendChild" : func, + "insertBefore" : func, + }, + "getElementsByTagName" : __getElementsByTagName, + "title" : "My Fake Title", + style: {}, + getAttribute: function() { return {}; }, + }; + } + }); + return fake_dict; +}; + +function __createElement(tag) { + var fake_elem = { + set src(url) { + logIOC('Remote Script', {url}, "The script set a remote script source."); + logUrl('Remote Script', {url}); + }, + log: [], + style: [], + appendChild: function() { + return __createElement("__append__"); + }, + attributes: {}, + setAttribute: function(name, val) { + this.attributes[name] = val; + }, + getAttribute: function(name) { + return this.attributes[name]; + }, + firstChild: { + nodeType: 3, + }, + lastChild: { + nodeType: 3, + }, + getElementsByTagName: __getElementsByTagName, + cloneNode: function() { + return __createElement("__clone__"); + }, + toLowerCase: function() { + return "// NOPE"; + }, + }; + return fake_elem; +}; + +// Stubbed global document object. +var document = { + documentMode: 8, // Fake running in IE8 + nodeType: 9, + referrer: 'https://bing.com/', + body: {}, + location: location, + defaultView: {}, + getElementById : function(id) { + + var char_codes_to_string = function (str) { + var codes = "" + for (var i = 0; i < str.length; i++) { + codes += String.fromCharCode(str[i]) + } + return codes + } + + /* IDS_AND_DATA */ + + for (var i = 0; i < ids.length; i++) { + if (char_codes_to_string(ids[i]) == id) { + return { + innerHTML: char_codes_to_string(data[i]) + } + } + } + + // got nothing to return + return { + innerHTML: "" + } + }, + documentElement: { + style: {}, + className: "", + }, + write: function (content) { + logIOC('DOM Write', {content}, 'The script wrote to the DOM') + eval.apply(null, [extractJSFromHTA(content)]); + }, + appendChild: function(node) { + logIOC('DOM Append', {node}, "The script appended an HTML node to the DOM") + eval(extractJSFromHTA(node)); + }, + insertBefore: function(node) { + logIOC('DOM Insert', {node}, "The script inserted an HTML node on the DOM") + eval(extractJSFromHTA(node)); + }, + getElementsByTagName: __getElementsByTagName, + createDocumentFragment: function() { + return { + appendChild: function() {}, + }; + }, + createElement: __createElement, + createTextNode: function(text) {}, + addEventListener: function(tag, func) {} +}; + // Stubbed global window object. var window = { eval: function(cmd) { eval(cmd); }, @@ -226,6 +348,8 @@ var window = { return ["??", "-moz-"]; }, + createDocumentFragment: function() {}, + createElement: __createElement, location: location, localStorage: { // Users and session to distinguish and generate statistics about website traffic. @@ -243,6 +367,7 @@ var window = { // To record the traffic source or campaign how users ended up on the website. "__utmz" : undefined, }, + document: document, }; // Initial stubbed object. Add items a needed. @@ -313,6 +438,7 @@ var funcDict = { trigger: function() {}, width: function() {}, resize: function() {}, + blur: function() {}, }; var jQuery = function(){ return funcDict; @@ -362,7 +488,7 @@ jQuery.expr = { window.jQuery = jQuery // Initial WebPack stubbing. -globalThis.location = "http://mylegitdomain.com:2112/and/i/have/a/path.php"; +globalThis.location = location; globalThis.importScripts = true; // Mejs module stubbing. @@ -384,97 +510,6 @@ class Element { constructor() {}; }; -function __getElementsByTagName(tag) { - var func = function(item) { - logIOC('DOM Append', {item}, "The script added a HTML node to the DOM"); - return ""; - }; - - // Return a dict that maps every tag name to the same fake element. - fake_dict = {}; - fake_dict = new Proxy(fake_dict, { - get(target, phrase) { // intercept reading a property from dictionary - return { - "appendChild" : func, - "insertBefore" : func, - "parentNode" : { - "appendChild" : func, - "insertBefore" : func, - }, - "getElementsByTagName" : __getElementsByTagName, - "title" : "My Fake Title", - }; - } - }); - return fake_dict; - } - -var document = { - documentMode: 8, // Fake running in IE8 - referrer: 'https://bing.com/', - body: {}, - location: location, - //parentNode: window.document.parentNode, - getElementById : function(id) { - - var char_codes_to_string = function (str) { - var codes = "" - for (var i = 0; i < str.length; i++) { - codes += String.fromCharCode(str[i]) - } - return codes - } - - /* IDS_AND_DATA */ - - for (var i = 0; i < ids.length; i++) { - if (char_codes_to_string(ids[i]) == id) { - return { - innerHTML: char_codes_to_string(data[i]) - } - } - } - - // got nothing to return - return { - innerHTML: "" - } - }, - documentElement: { - style: {}, - className: "", - }, - write: function (content) { - logIOC('DOM Write', {content}, 'The script wrote to the DOM') - eval.apply(null, [extractJSFromHTA(content)]); - }, - appendChild: function(node) { - logIOC('DOM Append', {node}, "The script appended an HTML node to the DOM") - eval(extractJSFromHTA(node)); - }, - insertBefore: function(node) { - logIOC('DOM Insert', {node}, "The script inserted an HTML node on the DOM") - eval(extractJSFromHTA(node)); - }, - getElementsByTagName: __getElementsByTagName, - createElement: function(tag) { - var fake_elem = { - set src(url) { - logIOC('Remote Script', {url}, "The script set a remote script source."); - logUrl('Remote Script', {url}); - }, - log: [], - style: [], - appendChild: function() {}, - }; - return fake_elem; - }, - createTextNode: function(text) { - //return window.document.createTextNode(text) - }, - addEventListener: function(tag, func) {} -}; - class _WidgetInfo { constructor(a1, a2, a3, a4, a5) {}; }; From bfeb012dbdfc671e1737c681a48c353a56f0a491 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 16:55:25 -0500 Subject: [PATCH 46/78] Initial Vue module stubbing. --- analyze.js | 2 +- boilerplate.js | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/analyze.js b/analyze.js index d8d95db..b526da6 100644 --- a/analyze.js +++ b/analyze.js @@ -524,7 +524,7 @@ require("util").inspect.defaultOptions.customInspect = false; if (argv["dangerous-vm"]) { lib.verbose("Analyzing with native vm module (dangerous!)"); const vm = require("vm"); - console.log(code); + //console.log(code); vm.runInNewContext(code, sandbox, { displayErrors: true, // lineOffset: -fs.readFileSync(path.join(__dirname, "patch.js"), "utf8").split("\n").length, diff --git a/boilerplate.js b/boilerplate.js index a924633..d24ec13 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -290,11 +290,12 @@ var document = { } /* IDS_AND_DATA */ - - for (var i = 0; i < ids.length; i++) { - if (char_codes_to_string(ids[i]) == id) { - return { - innerHTML: char_codes_to_string(data[i]) + if (typeof(ids) != "undefined") { + for (var i = 0; i < ids.length; i++) { + if (char_codes_to_string(ids[i]) == id) { + return { + innerHTML: char_codes_to_string(data[i]) + } } } } @@ -502,6 +503,13 @@ var MediaElementPlayer = { prototype: {}, }; +// Vue module stubbing. +class Vue { + constructor() {}; +}; +Vue.directive = function() {}; +Vue.component = function() {}; + // What is this? var N2R = N2D = function() {}; From 1103685232b4e4a20f4a7eb7d166b9cf103a4546 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 27 Oct 2022 17:03:09 -0500 Subject: [PATCH 47/78] More DOM stubbing. --- boilerplate.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index d24ec13..67ef68e 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -323,9 +323,7 @@ var document = { }, getElementsByTagName: __getElementsByTagName, createDocumentFragment: function() { - return { - appendChild: function() {}, - }; + return __createElement("__doc_fragment__"); }, createElement: __createElement, createTextNode: function(text) {}, From ed4fecbdd1071f6d5f814829904c39d051a476a2 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Fri, 28 Oct 2022 09:09:41 -0500 Subject: [PATCH 48/78] document stubbing. --- boilerplate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/boilerplate.js b/boilerplate.js index 67ef68e..4516bc5 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -279,6 +279,7 @@ var document = { body: {}, location: location, defaultView: {}, + cookie: "test1=Hello; SameSite=None; Secure", getElementById : function(id) { var char_codes_to_string = function (str) { From ed4fdb0cbc387569bc1c11e4120a0d1116b2bfd4 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Fri, 28 Oct 2022 10:43:40 -0500 Subject: [PATCH 49/78] Stubbed navigator object. --- boilerplate.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/boilerplate.js b/boilerplate.js index 4516bc5..fd0be2e 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -271,6 +271,9 @@ function __createElement(tag) { return fake_elem; }; +// Stubbed global navigator object. +var navigator = {}; + // Stubbed global document object. var document = { documentMode: 8, // Fake running in IE8 @@ -279,7 +282,7 @@ var document = { body: {}, location: location, defaultView: {}, - cookie: "test1=Hello; SameSite=None; Secure", + cookie: "", getElementById : function(id) { var char_codes_to_string = function (str) { @@ -291,6 +294,7 @@ var document = { } /* IDS_AND_DATA */ + if (typeof(ids) != "undefined") { for (var i = 0; i < ids.length; i++) { if (char_codes_to_string(ids[i]) == id) { From 65a0003f96a87d6be45d8a3536143611fb4f4586 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Fri, 4 Nov 2022 09:28:52 -0500 Subject: [PATCH 50/78] Added navigator to window object. --- boilerplate.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index fd0be2e..0b08fca 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -272,14 +272,16 @@ function __createElement(tag) { }; // Stubbed global navigator object. -var navigator = {}; +var navigator = { + userAgent: 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; Tablet PC 2.0; InfoPath.3)', +}; // Stubbed global document object. var document = { documentMode: 8, // Fake running in IE8 nodeType: 9, referrer: 'https://bing.com/', - body: {}, + body: __createElement("__document_body__"), location: location, defaultView: {}, cookie: "", @@ -372,6 +374,7 @@ var window = { "__utmz" : undefined, }, document: document, + navigator: navigator, }; // Initial stubbed object. Add items a needed. @@ -531,10 +534,6 @@ var _WidgetManager = { _RegisterWidget: function(a1, a2) {}, }; -var navigator = { - userAgent: 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; Tablet PC 2.0; InfoPath.3)', -}; - // We are acting like cscript when emulating. JS in cscript does not // implement Array.reduce(). Array.prototype.reduce = function(a, b) { From 05533c1197f3fc36b945c5bcf421792a838ddfe8 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Mon, 7 Nov 2022 15:30:37 -0600 Subject: [PATCH 51/78] More stubbing + bug fix for legacyDate. --- boilerplate.js | 3 + patch.js | 203 +++++++++++++++++++++++++------------------------ 2 files changed, 105 insertions(+), 101 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index 0b08fca..ab86405 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -375,6 +375,9 @@ var window = { }, document: document, navigator: navigator, + _NavbarView: class _NavbarView { + constructor() {}; + }, }; // Initial stubbed object. Add items a needed. diff --git a/patch.js b/patch.js index c266765..3c8357c 100644 --- a/patch.js +++ b/patch.js @@ -1,110 +1,111 @@ /* Patches from box-js */ - window = this; +window = this; - _globalTimeOffset = 0; - WScript.sleep = function(delay) { - _globalTimeOffset += delay; - } +_globalTimeOffset = 0; +WScript.sleep = function(delay) { + _globalTimeOffset += delay; +} - let fullYearGetter = Date.prototype.getFullYear; - Date.prototype.getFullYear = function() { - console.log("Warning: the script tried to read the current date."); - console.log("If it doesn't work correctly (eg. fails to decrypt a string,"); - console.log("try editing patch.js with a different year."); +let fullYearGetter = Date.prototype.getFullYear; +Date.prototype.getFullYear = function() { + console.log("Warning: the script tried to read the current date."); + console.log("If it doesn't work correctly (eg. fails to decrypt a string,"); + console.log("try editing patch.js with a different year."); - // return 2017; - return fullYearGetter.call(this); - }; - Date.prototype.getYear = function() { - return this.getFullYear(); - }; - Date.prototype.toString = function() { - // Example format: Thu Aug 24 18:17:18 UTC+0200 2017 - const dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][this.getDay()]; - const monName = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][this.getMonth()]; - return [ - dayName, monName, this.getUTCDay(), - this.getUTCHours() + ":" + this.getUTCMinutes() + ":" + this.getUTCSeconds(), - "UTC-0500", // New York timezone - this.getFullYear() - ].join(" "); - } - const legacyDate = Date; - Date = function() { - return new Proxy({ - _actualTime: new legacyDate(...arguments), - }, { - get: (target, prop) => { - const modifiedDate = new legacyDate(target._actualTime.getTime() + _globalTimeOffset); - if (prop === Symbol.toPrimitive) return hint => { - switch (hint) { - case "string": - case "default": - return modifiedDate.toString(); - case "number": - return modifiedDate.getTime(); - default: - throw new Error("Unknown hint!"); - } - } - if (typeof prop !== "symbol") { - if (!(prop in modifiedDate) && (prop in legacyDate)) return legacyDate[prop]; - if (!(prop in legacyDate.prototype)) return undefined; - } - const boundFn = modifiedDate[prop].bind(modifiedDate); - return function() { - const ret = boundFn.apply(null, arguments); - target._actualTime = new legacyDate(modifiedDate.getTime() - _globalTimeOffset); - return ret; - } - } - }); + // return 2017; + return fullYearGetter.call(this); +}; +Date.prototype.getYear = function() { + return this.getFullYear(); +}; +Date.prototype.toString = function() { + // Example format: Thu Aug 24 18:17:18 UTC+0200 2017 + const dayName = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][this.getDay()]; + const monName = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][this.getMonth()]; + return [ + dayName, monName, this.getUTCDay(), + this.getUTCHours() + ":" + this.getUTCMinutes() + ":" + this.getUTCSeconds(), + "UTC-0500", // New York timezone + this.getFullYear() + ].join(" "); +} +const legacyDate = Date; +Date = function() { + return new Proxy({ + _actualTime: new legacyDate(...arguments), + }, { + get: (target, prop) => { + const modifiedDate = new legacyDate(target._actualTime.getTime() + _globalTimeOffset); + if (prop === Symbol.toPrimitive) return hint => { + switch (hint) { + case "string": + case "default": + return modifiedDate.toString(); + case "number": + return modifiedDate.getTime(); + default: + throw new Error("Unknown hint!"); + } + } + if (typeof prop !== "symbol") { + if (!(prop in modifiedDate) && (prop in legacyDate)) return legacyDate[prop]; + if (!(prop in legacyDate.prototype)) return undefined; + } + if (typeof(modifiedDate[prop]) === "undefined") return undefined; + const boundFn = modifiedDate[prop].bind(modifiedDate); + return function() { + const ret = boundFn.apply(null, arguments); + target._actualTime = new legacyDate(modifiedDate.getTime() - _globalTimeOffset); + return ret; + } } - Date.now = () => legacyDate.now() + _globalTimeOffset; - Date.length = 7; - Date.parse = legacyDate.parse; - Date.UTC = legacyDate.UTC; - Date.toString = () => legacyDate.toString() - Date.valueOf = () => legacyDate.valueOf() + }); +} +Date.now = () => legacyDate.now() + _globalTimeOffset; +Date.length = 7; +Date.parse = legacyDate.parse; +Date.UTC = legacyDate.UTC; +Date.toString = () => legacyDate.toString() +Date.valueOf = () => legacyDate.valueOf() - Array.prototype.Count = function() { - return this.length; - }; +Array.prototype.Count = function() { + return this.length; +}; - let _OriginalFnToString = Function.prototype.toString; - Function.prototype.toString = function() { - /** - * WSH's toString() looks a bit different for built-in functions - * than result generated by Node.js (tabbed and wrapped with newlines) - * which is sometimes checked by malicious scripts. - */ - let source = _OriginalFnToString.call(this); - let r = source.replace( - /^function (\S+) { \[native code\] }$/, - ((m, fnName) => `\nfunction ${fnName} {\n [native code]\n}\n`) - ) - // Some obfuscators flag funcs with newlines. - r = r.replace(/\n/g, "").replace(/{ +/g, "{").replace(/ +}/g, "}"); - return r; - } +let _OriginalFnToString = Function.prototype.toString; +Function.prototype.toString = function() { + /** + * WSH's toString() looks a bit different for built-in functions + * than result generated by Node.js (tabbed and wrapped with newlines) + * which is sometimes checked by malicious scripts. + */ + let source = _OriginalFnToString.call(this); + let r = source.replace( + /^function (\S+) { \[native code\] }$/, + ((m, fnName) => `\nfunction ${fnName} {\n [native code]\n}\n`) + ) + // Some obfuscators flag funcs with newlines. + r = r.replace(/\n/g, "").replace(/{ +/g, "{").replace(/ +}/g, "}"); + return r; +} - let _OriginalFunction = Function; - Function = function(...args) { - let originalSource = args.pop(); - let source; - if (typeof originalSource === "function") { - originalSource = originalSource.toString(); - source = rewrite("(" + originalSource + ")"); - } else if (typeof originalSource === "string") { - source = `/* Function arguments: ${JSON.stringify(args)} */\n` + rewrite(originalSource); - } else { - // What the fuck JS - // For some reason, IIFEs result in a call to Function. - return new _OriginalFunction(...args, source); - } - logJS(source); - return new _OriginalFunction(...args, source); - } - Function.toString = () => _OriginalFunction.toString() - Function.valueOf = () => _OriginalFunction.valueOf() +let _OriginalFunction = Function; +Function = function(...args) { + let originalSource = args.pop(); + let source; + if (typeof originalSource === "function") { + originalSource = originalSource.toString(); + source = rewrite("(" + originalSource + ")"); + } else if (typeof originalSource === "string") { + source = `/* Function arguments: ${JSON.stringify(args)} */\n` + rewrite(originalSource); + } else { + // What the fuck JS + // For some reason, IIFEs result in a call to Function. + return new _OriginalFunction(...args, source); + } + logJS(source); + return new _OriginalFunction(...args, source); +} +Function.toString = () => _OriginalFunction.toString() +Function.valueOf = () => _OriginalFunction.valueOf() /* End patches */ From 4c2988bca37ba9b04261f8950cba694331825d81 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Thu, 10 Nov 2022 17:31:10 -0600 Subject: [PATCH 52/78] Start of handling scheduled tasks. --- analyze.js | 7 +++++-- emulator/ScheduleService.js | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 emulator/ScheduleService.js diff --git a/analyze.js b/analyze.js index b526da6..f7e74b7 100644 --- a/analyze.js +++ b/analyze.js @@ -477,8 +477,9 @@ const sandbox = { lib.logUrl("InstallProduct", x); }, console: { - // log: console.log.bind(console), - log: (x) => lib.info("Script output: " + JSON.stringify(x)), + //log: (x) => console.log(x), + //log: (x) => lib.info("Script output: " + JSON.stringify(x)), + log: (x) => lib.info("Script output: " + x), }, Enumerator: require("./emulator/Enumerator"), GetObject: require("./emulator/WMI").GetObject, @@ -605,6 +606,8 @@ function ActiveXObject(name) { return require("./emulator/WBEMScriptingSWBEMLocator"); case "msscriptcontrol.scriptcontrol": return require("./emulator/MSScriptControlScriptControl"); + case "schedule.service": + return require("./emulator/ScheduleService"); default: lib.kill(`Unknown ActiveXObject ${name}`); break; diff --git a/emulator/ScheduleService.js b/emulator/ScheduleService.js new file mode 100644 index 0000000..d6cead4 --- /dev/null +++ b/emulator/ScheduleService.js @@ -0,0 +1,25 @@ +const lib = require("../lib"); + +TaskFolderObject = { + GetTask: function(name) { + lib.info('The sample looked for scheduled task "' + name + '".'); + throw "task not found"; + }, +}; + +function ScheduleService() { + + this.Language = undefined; + this.Timeout = undefined; + + this.connect = () => { + lib.info('The sample connected to the task scheduler.'); + }; + + this.getfolder = root => { + lib.info('The sample got a scheduled task folder object rooted at "' + root + '".'); + return TaskFolderObject; + } +} + +module.exports = lib.proxify(ScheduleService, "Schedule.Service"); From 8d5f09cf37fc653f8576fe8179a576a375eee22a Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Fri, 11 Nov 2022 11:59:15 -0600 Subject: [PATCH 53/78] Implemented Enumerator class. Throttle files write logging if there are lots of writes. More emulation for file and task objects. --- boilerplate.js | 22 +++ emulator/FileSystemObject.js | 45 ++++- emulator/ScheduleService.js | 68 ++++++- lib.js | 355 +++++++++++++++++++---------------- 4 files changed, 315 insertions(+), 175 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index ab86405..95af3bd 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -1,6 +1,28 @@ const parse = require("node-html-parser").parse; const lib = require("./lib.js"); +// Simple Enumerator class implementation. +class Enumerator { + constructor(collection) { + if (typeof(collection.length) == "undefined") throw "Enumerator collection has no .length attr"; + this.collection = collection; + this.currIndex = 0; + }; + + atEnd() { + return (this.currIndex >= this.collection.length); + }; + + moveNext() { + this.currIndex++; + }; + + item() { + if (this.atEnd()) throw "Over end of all Enumerator data"; + return this.collection[this.currIndex]; + }; +}; + // atob() taken from abab.atob.js . /** diff --git a/emulator/FileSystemObject.js b/emulator/FileSystemObject.js index 9e94008..4a1dbe8 100644 --- a/emulator/FileSystemObject.js +++ b/emulator/FileSystemObject.js @@ -49,17 +49,31 @@ function ProxiedTextStream(filename) { }); } +function makeFakeSubfolders(path) { + + // Make list of fake subfolders of the given path. + var r = []; + for (var x = 0; x < 6; x++) { + r[x] = path + "\\_FAKE_BOXJS_FOLDER_" + x; + } + + // Add a Count attrbute to the list to mimic ActiveX Subfolders object. + Object.defineProperty(r, 'Count', { + get: function() { return this.length } + }); + + return r; +} + function Folder(path, autospawned) { this.attributes = 16; this.datelastmodified = new Date(new Date() - 15 * 60 * 1000); // Last changed: 15 minutes ago this.files = []; this.name = (path.replace(/\w:/i, "").match(/\\(\w*)(?:\\)?$/i) || [null, ""])[1], this.path = path; - this.subfolders = autospawned ? [] : [new ProxiedFolder(path + "\\RandomFolder", true)]; + //this.subfolders = autospawned ? [] : [new ProxiedFolder(path + "\\RandomFolder", true)]; this.type = "folder"; - this.subfolders = { - "Count": 12, - }; + this.subfolders = makeFakeSubfolders(this.path); } function ProxiedFolder(path, name, autospawned = false) { @@ -76,12 +90,28 @@ function File(contents) { this.attributes = 32; this.openastextstream = () => new ProxiedTextStream(contents); this.shortpath = "C:\\PROGRA~1\\example-file.exe"; + this._name = "example-file.exe"; this.size = Infinity; this.type = "Application"; } function ProxiedFile(filename) { - return lib.proxify(File, "FileSystemObject.File"); + var r = lib.proxify(File, "FileSystemObject.File"); + Object.defineProperty(r, 'name', { + set: function(v) { + lib.info('The sample set a file name to "' + v + '".'); + this._name = v; + }, + get: function(v) { + return this._name; + } + }); + Object.defineProperty(r, 'shortname', { + get: function() { + return this._name; + } + }); + return r; } function Drive(name) { @@ -144,7 +174,10 @@ function FileSystemObject() { return ""; return matches[0]; }; - this.getfile = (filename) => new ProxiedFile(filename); + this.getfile = function(filename) { + var r = new ProxiedFile(filename); + return r; + }; this.getfileversion = () => ""; this.getfolder = (str) => new ProxiedFolder(str); this.getspecialfolder = function(id) { diff --git a/emulator/ScheduleService.js b/emulator/ScheduleService.js index d6cead4..0d98407 100644 --- a/emulator/ScheduleService.js +++ b/emulator/ScheduleService.js @@ -1,10 +1,70 @@ const lib = require("../lib"); +// WARNING: Only handles a single global task object. TaskFolderObject = { + _tasks: {}, GetTask: function(name) { lib.info('The sample looked for scheduled task "' + name + '".'); - throw "task not found"; + if (typeof(this._tasks[name]) == "undefined") throw "task not found"; + return this._tasks[name]; }, + + RegisterTaskDefinition: function(name, taskObj) { + lib.info('The sample registered task "' + name + '".'); + this._tasks[name] = taskObj; + }, +}; + +class TaskTriggerObject { + + constructor() { + }; + + set ID(v) { + lib.info('The sample set a task trigger ID to "' + v + '".'); + this.id = v; + }; + + set UserId(v) { + lib.info('The sample set a task user ID to "' + v + '".'); + this.userId = v; + }; +}; + +class TaskObject { + + constructor() { + this.settings = {}; + this.triggers = { + Create: function() { + return new TaskTriggerObject(); + }, + }; + this.Actions = { + Create: function() { + return new TaskObject(); + }, + }; + }; + + set Path(v) { + lib.info('The sample set task path to "' + v + '".'); + this.path = v; + }; + + set Arguments(v) { + lib.info('The sample set task arguments to "' + v + '".'); + this.args = v; + }; + + set WorkingDirectory(v) { + lib.info('The sample set task working directory to "' + v + '".'); + this.workingDir = v; + }; + + RunEx() { + lib.info('The sample ran a scheduled task.'); + }; }; function ScheduleService() { @@ -19,7 +79,11 @@ function ScheduleService() { this.getfolder = root => { lib.info('The sample got a scheduled task folder object rooted at "' + root + '".'); return TaskFolderObject; - } + }; + + this.newtask = () => { + return new TaskObject(); + }; } module.exports = lib.proxify(ScheduleService, "Schedule.Service"); diff --git a/lib.js b/lib.js index d1658bf..7d20969 100644 --- a/lib.js +++ b/lib.js @@ -18,192 +18,213 @@ const IOC = []; let latestUrl = ""; const logSnippet = function(filename, logContent, content) { - snippets[filename] = logContent; - fs.writeFileSync(path.join(directory, filename), content); - fs.writeFileSync(path.join(directory, "snippets.json"), JSON.stringify(snippets, null, "\t")); + snippets[filename] = logContent; + fs.writeFileSync(path.join(directory, filename), content); + fs.writeFileSync(path.join(directory, "snippets.json"), JSON.stringify(snippets, null, "\t")); }; function kill(message) { - if (argv["no-kill"]) - throw new Error(message); - console.trace(message); - console.log("Exiting (use --no-kill to just simulate a runtime error)."); - process.exit(0); + if (argv["no-kill"]) + throw new Error(message); + console.trace(message); + console.log("Exiting (use --no-kill to just simulate a runtime error)."); + process.exit(0); } function log(tag, text, toFile = true, toStdout = true) { - const levels = { - "debug": 0, - "verb": 1, - "info": 2, - "warn": 3, - "error": 4, - }; - if (!(tag in levels)) { - log("warn", `Application error: unknown logging tag ${tag}`, false); - return; - } - if (!(argv.loglevel in levels)) { - const oldLevel = argv.loglevel; // prevents infinite recursion - argv.loglevel = "debug"; - log("warn", `Log level ${oldLevel} is invalid (valid levels: ${Object.keys(levels).join(", ")}), defaulting to "info"`, false); - } - const level = levels[tag]; - if (level < levels[argv.loglevel]) return; - const message = `[${tag}] ${text}`; - if (toStdout || argv.loglevel === "debug") // Debug level always writes to stdout and file - console.log(message); - if (toFile || argv.loglevel === "debug") - fs.appendFileSync(path.join(directory, "analysis.log"), message + "\n"); + const levels = { + "debug": 0, + "verb": 1, + "info": 2, + "warn": 3, + "error": 4, + }; + if (!(tag in levels)) { + log("warn", `Application error: unknown logging tag ${tag}`, false); + return; + } + if (!(argv.loglevel in levels)) { + const oldLevel = argv.loglevel; // prevents infinite recursion + argv.loglevel = "debug"; + log("warn", `Log level ${oldLevel} is invalid (valid levels: ${Object.keys(levels).join(", ")}), defaulting to "info"`, false); + } + const level = levels[tag]; + if (level < levels[argv.loglevel]) return; + const message = `[${tag}] ${text}`; + if (toStdout || argv.loglevel === "debug") // Debug level always writes to stdout and file + console.log(message); + if (toFile || argv.loglevel === "debug") + fs.appendFileSync(path.join(directory, "analysis.log"), message + "\n"); } function hash(algo, string) { - return crypto.createHash(algo).update(string).digest("hex"); + return crypto.createHash(algo).update(string).digest("hex"); } const getUUID = uuid.v4; function logIOC(type, value, description) { - log("info", "IOC: " + description); - IOC.push({type, value, description}); - fs.writeFileSync(path.join(directory, "IOC.json"), JSON.stringify(IOC, null, "\t")); + log("info", "IOC: " + description); + IOC.push({type, value, description}); + fs.writeFileSync(path.join(directory, "IOC.json"), JSON.stringify(IOC, null, "\t")); } function logUrl(method, url) { - log("info", `${method} ${url}`); - latestUrl = url; - if (urls.indexOf(url) === -1) urls.push(url); - fs.writeFileSync(path.join(directory, "urls.json"), JSON.stringify(urls, null, "\t")); + log("info", `${method} ${url}`); + latestUrl = url; + if (urls.indexOf(url) === -1) urls.push(url); + fs.writeFileSync(path.join(directory, "urls.json"), JSON.stringify(urls, null, "\t")); } +// Track the # of times we have seen a file written to so we don't spam +// emulation output. +const MAXWRITES = 10; +fileWriteCount = {}; + module.exports = { - argv, - kill, - getUUID, - - debug: log.bind(null, "debug"), - verbose: log.bind(null, "verb"), - info: log.bind(null, "info"), - warning: log.bind(null, "warn"), - error: log.bind(null, "error"), - - proxify: (actualObject, objectName = "") => { - /* Creating a Proxy is a common operation, because they normalize property names - * and help catch unimplemented features. This function implements this behaviour. - */ - return new Proxy(new actualObject, { - get: function(target, prop) { - const lProp = prop.toLowerCase(); - if (lProp in target) return target[lProp]; - kill(`${objectName}.${prop} not implemented!`); - }, - set: function(a, b, c) { - b = b.toLowerCase(); - a[b] = c; - return true; - }, - }); - }, - fetchUrl: function(method, url, headers = {}, body) { - // Ignore HTTPS errors - process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; - logUrl(method, url); - logIOC("UrlFetch", {method, url, headers, body}, "The script fetched an URL."); - if (!doDownload) { - lib.info("Returning HTTP 404 (Not found); use --download to try to download the payload"); - return { - body: new Buffer(""), - headers: {}, - }; - } - try { - log("info", "Downloading..."); - - headers["User-Agent"] = "Mozilla/4.0 (Windows; MSIE 6.0; Windows NT 6.0)"; - const options = { - headers, - maxRedirects: 20, - timeout: 4000, - }; - if (body) - options.body = body; - if (argv.proxy) - options.proxy = argv.proxy; - - const file = request(method, url, options); - Buffer.prototype.charCodeAt = function(index) { - return this[index]; - }; - log("info", `Downloaded ${file.body.length} bytes.`); - return file; - } catch (e) { - // Log and rethrow - log("error", `An error occurred while emulating a ${method} request to ${url}.`); - log("error", e); - throw e; - } - }, - writeFile: function(filename, contents) { - logIOC("FileWrite", {file: filename, contents}, "The script wrote a file."); - files[filename] = contents; - }, - readFile: function(filename) { - logIOC("FileRead", {file: filename}, "The script read a file."); - return files[filename]; - }, - logUrl, - logResource: function(resourceName, emulatedPath, content) { - const filePath = path.join(directory, resourceName); - fs.writeFileSync(filePath, content); - log("info", `Saved ${filePath} (${content.length} bytes)`); - - let filetype = child_process.execSync("file " + JSON.stringify(filePath)).toString("utf8"); - filetype = filetype.replace(`${filePath}: `, "").replace("\n", ""); - log("info", `${filePath} has been detected as ${filetype}.`); - - if (/executable/.test(filetype)) { - log("info", `Active URL detected: ${latestUrl}`); - // Log active url - if (activeUrls.indexOf(latestUrl) === -1) - activeUrls.push(latestUrl); - fs.writeFileSync(path.join(directory, "active_urls.json"), JSON.stringify(activeUrls, null, "\t")); - } - - const md5 = hash("md5", content); - log("verb", "md5: " + md5); - const sha1 = hash("sha1", content); - log("verb", "sha1: " + sha1); - const sha256 = hash("sha256", content); - log("verb", "sha256: " + sha256); - - const resource = { - path: emulatedPath, - type: filetype, - latestUrl, - md5, - sha1, - sha256 - }; - resources[resourceName] = resource; - logIOC("NewResource", resource, "The script created a resource."); - fs.writeFileSync(path.join(directory, "resources.json"), JSON.stringify(resources, null, "\t")); - }, - logSnippet, - logJS: function(code) { - const filename = uuid.v4() + ".js"; - log("verb", `Code saved to ${filename}`); - logSnippet(filename, {as: "eval'd JS"}, code); - return code; // Helps with tail call optimization - }, - logIOC, - runShellCommand: (command) => { - const filename = getUUID(); - logIOC("Run", {command}, "The script ran a command."); - log("info", `Executing ${path.join(directory, filename)} in the WScript shell`); - logSnippet(filename, {as: "WScript code"}, command); - process.send("expect-shell-error"); - if (!argv["no-shell-error"]) - throw new Error("If you can read this, re-run box.js with the --no-shell-error flag."); - process.send("no-expect-shell-error"); + argv, + kill, + getUUID, + + debug: log.bind(null, "debug"), + verbose: log.bind(null, "verb"), + info: log.bind(null, "info"), + warning: log.bind(null, "warn"), + error: log.bind(null, "error"), + + proxify: (actualObject, objectName = "") => { + /* Creating a Proxy is a common operation, because they normalize property names + * and help catch unimplemented features. This function implements this behaviour. + */ + return new Proxy(new actualObject, { + get: function(target, prop) { + const lProp = prop.toLowerCase(); + if (lProp in target) return target[lProp]; + kill(`${objectName}.${prop} not implemented!`); + }, + set: function(a, b, c) { + b = b.toLowerCase(); + a[b] = c; + return true; + }, + }); + }, + fetchUrl: function(method, url, headers = {}, body) { + // Ignore HTTPS errors + process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; + logUrl(method, url); + logIOC("UrlFetch", {method, url, headers, body}, "The script fetched an URL."); + if (!doDownload) { + lib.info("Returning HTTP 404 (Not found); use --download to try to download the payload"); + return { + body: new Buffer(""), + headers: {}, + }; } + try { + log("info", "Downloading..."); + + headers["User-Agent"] = "Mozilla/4.0 (Windows; MSIE 6.0; Windows NT 6.0)"; + const options = { + headers, + maxRedirects: 20, + timeout: 4000, + }; + if (body) + options.body = body; + if (argv.proxy) + options.proxy = argv.proxy; + + const file = request(method, url, options); + Buffer.prototype.charCodeAt = function(index) { + return this[index]; + }; + log("info", `Downloaded ${file.body.length} bytes.`); + return file; + } catch (e) { + // Log and rethrow + log("error", `An error occurred while emulating a ${method} request to ${url}.`); + log("error", e); + throw e; + } + }, + writeFile: function(filename, contents) { + // Don't spam lots of file write info to same file. + if (typeof(fileWriteCount[filename]) == "undefined") fileWriteCount[filename] = 0; + fileWriteCount[filename]++; + var doLog = (fileWriteCount[filename] <= MAXWRITES); + if (doLog) logIOC("FileWrite", {file: filename, contents}, "The script wrote file '" + filename + "'."); + files[filename] = contents; + }, + readFile: function(filename) { + logIOC("FileRead", {file: filename}, "The script read a file."); + return files[filename]; + }, + logUrl, + logResource: function(resourceName, emulatedPath, content) { + const filePath = path.join(directory, resourceName); + fs.writeFileSync(filePath, content); + + // Don't spam lots of file write info to same file. + if (typeof(fileWriteCount[filePath]) == "undefined") fileWriteCount[filePath] = 0; + fileWriteCount[filePath]++; + var doLog = (fileWriteCount[filePath] <= MAXWRITES); + let filetype = ""; + if (doLog) { + log("info", `Saved ${filePath} (${content.length} bytes)`); + filetype = child_process.execSync("file " + JSON.stringify(filePath)).toString("utf8"); + filetype = filetype.replace(`${filePath}: `, "").replace("\n", ""); + log("info", `${filePath} has been detected as ${filetype}.`); + } + if (fileWriteCount[filePath] == (MAXWRITES + 1)) { + log("info", "Throttling file write reporting for " + filePath); + } + + if (/executable/.test(filetype)) { + if (doLog) log("info", `Active URL detected: ${latestUrl}`); + // Log active url + if (activeUrls.indexOf(latestUrl) === -1) + activeUrls.push(latestUrl); + fs.writeFileSync(path.join(directory, "active_urls.json"), JSON.stringify(activeUrls, null, "\t")); + } + + if (doLog) { + const md5 = hash("md5", content); + log("verb", "md5: " + md5); + const sha1 = hash("sha1", content); + log("verb", "sha1: " + sha1); + const sha256 = hash("sha256", content); + log("verb", "sha256: " + sha256); + + const resource = { + path: emulatedPath, + type: filetype, + latestUrl, + md5, + sha1, + sha256 + }; + logIOC("NewResource", resource, "The script created a resource."); + fs.writeFileSync(path.join(directory, "resources.json"), JSON.stringify(resources, null, "\t")); + resources[resourceName] = resource; + } + }, + logSnippet, + logJS: function(code) { + const filename = uuid.v4() + ".js"; + log("verb", `Code saved to ${filename}`); + logSnippet(filename, {as: "eval'd JS"}, code); + return code; // Helps with tail call optimization + }, + logIOC, + runShellCommand: (command) => { + const filename = getUUID(); + logIOC("Run", {command}, "The script ran a command."); + log("info", `Executing ${path.join(directory, filename)} in the WScript shell`); + logSnippet(filename, {as: "WScript code"}, command); + process.send("expect-shell-error"); + if (!argv["no-shell-error"]) + throw new Error("If you can read this, re-run box.js with the --no-shell-error flag."); + process.send("no-expect-shell-error"); + } }; From cf3631f9e590ea0cacf6c7cfd6bd37427f399a7e Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Fri, 11 Nov 2022 14:45:52 -0600 Subject: [PATCH 54/78] Added a --throttle-writes option to throttle track large amounts of file writes. --- analyze.js | 10 ++++++++-- emulator/ScheduleService.js | 14 +++++++------- flags.json | 5 +++++ lib.js | 30 ++++++++++++++++++++++++++---- 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/analyze.js b/analyze.js index f7e74b7..a512e17 100644 --- a/analyze.js +++ b/analyze.js @@ -186,8 +186,11 @@ cc decoder.c -o decoder lib.verbose(" Rewriting loops...", false); traverse(tree, loop_rewriter.rewriteSimpleWaitLoop); traverse(tree, loop_rewriter.rewriteSimpleControlLoop); - } + }; + if (argv["throttle-writes"]) { + lib.throttleFileWrites(true); + }; if (argv.preprocess) { lib.verbose(` Preprocessing with uglify-es v${require("uglify-es/package.json").version} (remove --preprocess to skip)...`, false); @@ -409,6 +412,10 @@ var wscript_proxy = new Proxy({ //scriptfullname: "C:\\Users\\Sysop12\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\ons.jse", scriptfullname: "C:\Users\\Sysop12\\AppData\\Roaming\\Microsoft\\Templates\\0.2638666.jse", scriptname: "0.2638666.jse", + quit: function() { + lib.info("The sample called WScript.Quit(). Exiting."); + process.exit(0); + }, get stderr() { lib.error("WScript.StdErr not implemented"); }, @@ -430,7 +437,6 @@ var wscript_proxy = new Proxy({ get getobject() { lib.error("WScript.GetObject not implemented"); }, - quit() {}, // Note that Sleep() is implemented in patch.js because it requires // access to the variable _globalTimeOffset, which belongs to the script // and not to the emulator. diff --git a/emulator/ScheduleService.js b/emulator/ScheduleService.js index 0d98407..44c21d6 100644 --- a/emulator/ScheduleService.js +++ b/emulator/ScheduleService.js @@ -4,13 +4,13 @@ const lib = require("../lib"); TaskFolderObject = { _tasks: {}, GetTask: function(name) { - lib.info('The sample looked for scheduled task "' + name + '".'); + lib.logIOC("Task", name, 'The sample looked for scheduled task "' + name + '".'); if (typeof(this._tasks[name]) == "undefined") throw "task not found"; return this._tasks[name]; }, RegisterTaskDefinition: function(name, taskObj) { - lib.info('The sample registered task "' + name + '".'); + lib.logIOC("Task", name, 'The sample registered task "' + name + '".'); this._tasks[name] = taskObj; }, }; @@ -21,12 +21,12 @@ class TaskTriggerObject { }; set ID(v) { - lib.info('The sample set a task trigger ID to "' + v + '".'); + lib.logIOC("Task", v, 'The sample set a task trigger ID to "' + v + '".'); this.id = v; }; set UserId(v) { - lib.info('The sample set a task user ID to "' + v + '".'); + lib.logIOC("Task", v, 'The sample set a task user ID to "' + v + '".'); this.userId = v; }; }; @@ -48,17 +48,17 @@ class TaskObject { }; set Path(v) { - lib.info('The sample set task path to "' + v + '".'); + lib.logIOC("Task", v, 'The sample set task path to "' + v + '".'); this.path = v; }; set Arguments(v) { - lib.info('The sample set task arguments to "' + v + '".'); + lib.logIOC("Task", v, 'The sample set task arguments to "' + v + '".'); this.args = v; }; set WorkingDirectory(v) { - lib.info('The sample set task working directory to "' + v + '".'); + lib.logIOC("Task", v, 'The sample set task working directory to "' + v + '".'); this.workingDir = v; }; diff --git a/flags.json b/flags.json index 0a1888b..38435d6 100644 --- a/flags.json +++ b/flags.json @@ -151,6 +151,11 @@ "name": "rewrite-loops", "type": "Boolean", "description": "Rewrite some types of loops to make analysis faster" + }, + { + "name": "throttle-writes", + "type": "Boolean", + "description": "Throttle reporting and data tracking of file writes that write a LOT of data" } ], "export": [ diff --git a/lib.js b/lib.js index 7d20969..2bec6b8 100644 --- a/lib.js +++ b/lib.js @@ -81,10 +81,21 @@ function logUrl(method, url) { const MAXWRITES = 10; fileWriteCount = {}; +// If needed stop writing bytes to very large files. +const MAXBYTES = 1e+6 * 10; // 10MB +var throttleWrites = false; +tooBigFiles = {}; + +// Function for enabling/disabling file write throttling. +function throttleFileWrites(val) { + throttleWrites = val; +}; + module.exports = { argv, kill, getUUID, + throttleFileWrites, debug: log.bind(null, "debug"), verbose: log.bind(null, "verb"), @@ -152,7 +163,7 @@ module.exports = { // Don't spam lots of file write info to same file. if (typeof(fileWriteCount[filename]) == "undefined") fileWriteCount[filename] = 0; fileWriteCount[filename]++; - var doLog = (fileWriteCount[filename] <= MAXWRITES); + var doLog = throttleWrites && (fileWriteCount[filename] <= MAXWRITES); if (doLog) logIOC("FileWrite", {file: filename, contents}, "The script wrote file '" + filename + "'."); files[filename] = contents; }, @@ -162,13 +173,24 @@ module.exports = { }, logUrl, logResource: function(resourceName, emulatedPath, content) { - const filePath = path.join(directory, resourceName); + + // Has this file aready gotten too large? + const filePath = path.join(directory, resourceName); + if (throttleWrites && (content.length > MAXBYTES)) { + if (typeof(tooBigFiles[filePath]) == "undefined") { + log("warn", "File '" + filePath + "' is too big. Not writing."); + tooBigFiles[filePath] = true; + } + return; + }; + + // Save the new file contents. fs.writeFileSync(filePath, content); // Don't spam lots of file write info to same file. if (typeof(fileWriteCount[filePath]) == "undefined") fileWriteCount[filePath] = 0; fileWriteCount[filePath]++; - var doLog = (fileWriteCount[filePath] <= MAXWRITES); + var doLog = throttleWrites && (fileWriteCount[filePath] <= MAXWRITES); let filetype = ""; if (doLog) { log("info", `Saved ${filePath} (${content.length} bytes)`); @@ -177,7 +199,7 @@ module.exports = { log("info", `${filePath} has been detected as ${filetype}.`); } if (fileWriteCount[filePath] == (MAXWRITES + 1)) { - log("info", "Throttling file write reporting for " + filePath); + log("warn", "Throttling file write reporting for " + filePath); } if (/executable/.test(filetype)) { From 57a2600581068dcf3d50b5c579cb817a0aef0331 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Fri, 11 Nov 2022 17:00:20 -0600 Subject: [PATCH 55/78] Handle piping stdin to a running process during sandboxing. --- emulator/WScriptShell.js | 13 ++++-- lib.js | 85 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/emulator/WScriptShell.js b/emulator/WScriptShell.js index b8e7940..7786a7c 100644 --- a/emulator/WScriptShell.js +++ b/emulator/WScriptShell.js @@ -84,16 +84,23 @@ function WScriptShell() { return 0; }; - this.exec = cmd => { + this.exec = function(cmd) { + console.log("EXEC: 1"); + console.log(cmd); lib.runShellCommand(cmd); - return { + var r = { ExitCode: 1, ProcessID: Math.floor(Math.random() * 1000), Status: 1, // Finished StdErr: null, - StdIn: null, + StdIn: { + writeline: function(txt) { + lib.logIOC("Run", {txt}, "The script piped text to a process: '" + txt + "'."); + }, + }, StdOut: new TextStream(``), }; + return lib.noCasePropObj(r); }; if (!this._reg_entries) { diff --git a/lib.js b/lib.js index 2bec6b8..9337266 100644 --- a/lib.js +++ b/lib.js @@ -91,12 +91,92 @@ function throttleFileWrites(val) { throttleWrites = val; }; +function noCasePropObj(obj) +{ + var handler = + { + get: function(target, key) + { + //console.log("key: " + key.toString()); + if (typeof key == "string") + { + var uKey = key.toUpperCase(); + + if ((key != uKey) && (key in target)) + return target[key]; + return target[uKey]; + } + return target[key]; + }, + set: function(target, key, value) + { + if (typeof key == "string") + { + var uKey = key.toUpperCase(); + + if ((key != uKey) && (key in target)) + target[key] = value; + target[uKey] = value; + } + else + target[key] = value; + }, + deleteProperty: function(target, key) + { + if (typeof key == "string") + { + var uKey = key.toUpperCase(); + + if ((key != uKey) && (key in target)) + delete target[key]; + if (uKey in target) + delete target[uKey]; + } + else + delete target[key]; + }, + }; + function checkAtomic(value) + { + if (typeof value == "object") + return new noCasePropObj(value); // recursive call only for Objects + return value; + } + + var newObj; + + if (typeof obj == "object") + { + newObj = new Proxy({}, handler); + // traverse the Original object converting string keys to upper case + for (var key in obj) + { + if (typeof key == "string") + { + var objKey = key.toUpperCase(); + + if (!(key in newObj)) + newObj[objKey] = checkAtomic(obj[key]); + } + } + } + else if (Array.isArray(obj)) + { + // in an array of objects convert to upper case string keys within each row + newObj = new Array(); + for (var i = 0; i < obj.length; i++) + newObj[i] = checkAtomic(obj[i]); + } + return newObj; // object with upper cased keys +}; + module.exports = { argv, kill, getUUID, throttleFileWrites, - + noCasePropObj, + debug: log.bind(null, "debug"), verbose: log.bind(null, "verb"), info: log.bind(null, "info"), @@ -241,8 +321,7 @@ module.exports = { logIOC, runShellCommand: (command) => { const filename = getUUID(); - logIOC("Run", {command}, "The script ran a command."); - log("info", `Executing ${path.join(directory, filename)} in the WScript shell`); + logIOC("Run", {command}, "The script ran the command '" + command + "'."); logSnippet(filename, {as: "WScript code"}, command); process.send("expect-shell-error"); if (!argv["no-shell-error"]) From 857d215bdbc209c65d7dcf1ee2ae449a6f6f646d Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Fri, 11 Nov 2022 17:10:07 -0600 Subject: [PATCH 56/78] Simulate being run with cscript. --- analyze.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/analyze.js b/analyze.js index a512e17..9c22303 100644 --- a/analyze.js +++ b/analyze.js @@ -404,9 +404,9 @@ var wscript_proxy = new Proxy({ }, }), buildversion: "1234", - fullname: "C:\\WINDOWS\\system32\\wscript.exe", + fullname: "C:\\WINDOWS\\system32\\cscript.exe", interactive: true, - name: "wscript.exe", + name: "cscript.exe", path: "C:\\TestFolder\\", //scriptfullname: "C:\\Documents and Settings\\User\\Desktop\\sample.js", //scriptfullname: "C:\\Users\\Sysop12\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\ons.jse", From 5f41e3f68883a44ec978dbb8c9cbef3a2eae694f Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Fri, 11 Nov 2022 17:11:16 -0600 Subject: [PATCH 57/78] Removed debug statement. --- emulator/WScriptShell.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/emulator/WScriptShell.js b/emulator/WScriptShell.js index 7786a7c..21443b4 100644 --- a/emulator/WScriptShell.js +++ b/emulator/WScriptShell.js @@ -85,8 +85,6 @@ function WScriptShell() { }; this.exec = function(cmd) { - console.log("EXEC: 1"); - console.log(cmd); lib.runShellCommand(cmd); var r = { ExitCode: 1, From e164b0cedcea90ac1b9dd060a2e000b003421363 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Mon, 14 Nov 2022 11:06:12 -0600 Subject: [PATCH 58/78] Gather up all task info about registered task in IOC JSON. --- analyze.js | 9 ++++++--- emulator/ScheduleService.js | 39 +++++++++++++++++++++++++++---------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/analyze.js b/analyze.js index 9c22303..14de322 100644 --- a/analyze.js +++ b/analyze.js @@ -404,13 +404,16 @@ var wscript_proxy = new Proxy({ }, }), buildversion: "1234", - fullname: "C:\\WINDOWS\\system32\\cscript.exe", + // TODO: Add --engine= option to set whether to fake cscript or wscript. + //fullname: "C:\\WINDOWS\\system32\\cscript.exe", + fullname: "C:\\WINDOWS\\system32\\wscript.exe", interactive: true, - name: "cscript.exe", + //name: "cscript.exe", + name: "wscript.exe", path: "C:\\TestFolder\\", //scriptfullname: "C:\\Documents and Settings\\User\\Desktop\\sample.js", //scriptfullname: "C:\\Users\\Sysop12\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\ons.jse", - scriptfullname: "C:\Users\\Sysop12\\AppData\\Roaming\\Microsoft\\Templates\\0.2638666.jse", + scriptfullname: "C:\Users\\Sysop12\\AppData\\Roaming\\Microsoft\\Templates\\CURRENT_SCRIPT_IN_FAKED_DIR.js", scriptname: "0.2638666.jse", quit: function() { lib.info("The sample called WScript.Quit(). Exiting."); diff --git a/emulator/ScheduleService.js b/emulator/ScheduleService.js index 44c21d6..0af4b02 100644 --- a/emulator/ScheduleService.js +++ b/emulator/ScheduleService.js @@ -4,13 +4,23 @@ const lib = require("../lib"); TaskFolderObject = { _tasks: {}, GetTask: function(name) { - lib.logIOC("Task", name, 'The sample looked for scheduled task "' + name + '".'); + lib.info('The sample looked for scheduled task "' + name + '".'); if (typeof(this._tasks[name]) == "undefined") throw "task not found"; return this._tasks[name]; }, RegisterTaskDefinition: function(name, taskObj) { - lib.logIOC("Task", name, 'The sample registered task "' + name + '".'); + var taskInfo = { + name: name, + path: taskObj.path, + args: taskObj.args, + workingDir: taskObj.workingDir, + }; + if (typeof(taskObj.triggerObj) != "undefined") { + taskInfo.triggerId = taskObj.triggerObj.id; + taskInfo.triggerUserId = taskObj.triggerObj.userId; + }; + lib.logIOC("Task", taskInfo, 'The sample registered task "' + name + '".'); this._tasks[name] = taskObj; }, }; @@ -21,44 +31,53 @@ class TaskTriggerObject { }; set ID(v) { - lib.logIOC("Task", v, 'The sample set a task trigger ID to "' + v + '".'); + lib.info('The sample set a task trigger ID to "' + v + '".'); this.id = v; }; set UserId(v) { - lib.logIOC("Task", v, 'The sample set a task user ID to "' + v + '".'); + lib.info('The sample set a task user ID to "' + v + '".'); this.userId = v; }; }; +//debug +var num = 0; class TaskObject { constructor() { this.settings = {}; this.triggers = { Create: function() { - return new TaskTriggerObject(); + var r = new TaskTriggerObject(); + this.taskObj.triggerObj = r; + return r; }, }; this.Actions = { Create: function() { - return new TaskObject(); + return this.taskObj; }, - }; + }; + this.Actions.Create.taskObj = this; + this.Actions.Create = this.Actions.Create.bind(this.Actions.Create); + this.triggers.Create.taskObj = this; + this.triggers.Create = this.triggers.Create.bind(this.triggers.Create); + this.debug = "DEBUG_" + (num++); }; set Path(v) { - lib.logIOC("Task", v, 'The sample set task path to "' + v + '".'); + lib.info('The sample set task path to "' + v + '".'); this.path = v; }; set Arguments(v) { - lib.logIOC("Task", v, 'The sample set task arguments to "' + v + '".'); + lib.info('The sample set task arguments to "' + v + '".'); this.args = v; }; set WorkingDirectory(v) { - lib.logIOC("Task", v, 'The sample set task working directory to "' + v + '".'); + lib.info('The sample set task working directory to "' + v + '".'); this.workingDir = v; }; From 171a00d2b5bceb6cb5d8577bdacbea0a2984db73 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Mon, 14 Nov 2022 11:19:26 -0600 Subject: [PATCH 59/78] Added command line option to specify what script engine to fake. --- analyze.js | 18 ++++++++++++------ flags.json | 5 +++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/analyze.js b/analyze.js index 14de322..6be64ed 100644 --- a/analyze.js +++ b/analyze.js @@ -380,6 +380,15 @@ Array.prototype.Count = function() { return this.length; }; +// Set the fake scripting engine to report. +var fakeEngineShort = "wscript.exe" +console.log("ARGV!!"); +console.log(argv["fake-script-engine"]); +if (argv["fake-script-engine"]) { + fakeEngineShort = argv["fake-script-engine"]; +} +var fakeEngineFull = "C:\\WINDOWS\\system32\\" + fakeEngineShort; + var wscript_proxy = new Proxy({ arguments: new Proxy((n) => `${n}th argument`, { get: function(target, name) { @@ -404,17 +413,14 @@ var wscript_proxy = new Proxy({ }, }), buildversion: "1234", - // TODO: Add --engine= option to set whether to fake cscript or wscript. - //fullname: "C:\\WINDOWS\\system32\\cscript.exe", - fullname: "C:\\WINDOWS\\system32\\wscript.exe", interactive: true, - //name: "cscript.exe", - name: "wscript.exe", + fullname: fakeEngineFull, + name: fakeEngineShort, path: "C:\\TestFolder\\", //scriptfullname: "C:\\Documents and Settings\\User\\Desktop\\sample.js", //scriptfullname: "C:\\Users\\Sysop12\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\ons.jse", scriptfullname: "C:\Users\\Sysop12\\AppData\\Roaming\\Microsoft\\Templates\\CURRENT_SCRIPT_IN_FAKED_DIR.js", - scriptname: "0.2638666.jse", + scriptname: "CURRENT_SCRIPT_IN_FAKED_DIR.js", quit: function() { lib.info("The sample called WScript.Quit(). Exiting."); process.exit(0); diff --git a/flags.json b/flags.json index 38435d6..d6f163e 100644 --- a/flags.json +++ b/flags.json @@ -67,6 +67,11 @@ "type": "String", "description": "Input file or directory containing code that should be prepended to the JS file(s) we're analyzing. If directory is given, prepends contents of all files in the directory in " }, + { + "name": "fake-script-engine", + "type": "String", + "description": "The script engine to report in WScript.FullName and WScript.Name (ex. 'cscript.exe' or 'wscript.exe'). Default is wscript.exe." + }, { "name": "no-kill", "type": "Boolean", From 4d46eb9a72806fbb403c958af67249d0cde351fa Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Mon, 14 Nov 2022 11:21:59 -0600 Subject: [PATCH 60/78] Removed debug. --- analyze.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/analyze.js b/analyze.js index 6be64ed..bba57ad 100644 --- a/analyze.js +++ b/analyze.js @@ -382,8 +382,6 @@ Array.prototype.Count = function() { // Set the fake scripting engine to report. var fakeEngineShort = "wscript.exe" -console.log("ARGV!!"); -console.log(argv["fake-script-engine"]); if (argv["fake-script-engine"]) { fakeEngineShort = argv["fake-script-engine"]; } From d9364f7155988fea4f5f9ba05c9183df402d2c06 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Mon, 14 Nov 2022 12:17:40 -0600 Subject: [PATCH 61/78] Report piped text more cleanly in IOC.json. --- emulator/WScriptShell.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emulator/WScriptShell.js b/emulator/WScriptShell.js index 21443b4..c9145fe 100644 --- a/emulator/WScriptShell.js +++ b/emulator/WScriptShell.js @@ -93,7 +93,7 @@ function WScriptShell() { StdErr: null, StdIn: { writeline: function(txt) { - lib.logIOC("Run", {txt}, "The script piped text to a process: '" + txt + "'."); + lib.logIOC("Run", txt, "The script piped text to a process: '" + txt + "'."); }, }, StdOut: new TextStream(``), From 269e4fbfb0f38f89a97565647fc82620e21d28c5 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 15 Nov 2022 09:03:39 -0600 Subject: [PATCH 62/78] Try to fix fullYearGetter bug. --- patch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patch.js b/patch.js index 3c8357c..d0d67eb 100644 --- a/patch.js +++ b/patch.js @@ -6,14 +6,14 @@ WScript.sleep = function(delay) { _globalTimeOffset += delay; } -let fullYearGetter = Date.prototype.getFullYear; +let fullYearGetter007 = Date.prototype.getFullYear; Date.prototype.getFullYear = function() { console.log("Warning: the script tried to read the current date."); console.log("If it doesn't work correctly (eg. fails to decrypt a string,"); console.log("try editing patch.js with a different year."); // return 2017; - return fullYearGetter.call(this); + return fullYearGetter007.call(this); }; Date.prototype.getYear = function() { return this.getFullYear(); From c7181176347b20849018f51a137b239215f69287 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 15 Nov 2022 09:44:40 -0600 Subject: [PATCH 63/78] Undo non-working fix. --- patch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patch.js b/patch.js index d0d67eb..3c8357c 100644 --- a/patch.js +++ b/patch.js @@ -6,14 +6,14 @@ WScript.sleep = function(delay) { _globalTimeOffset += delay; } -let fullYearGetter007 = Date.prototype.getFullYear; +let fullYearGetter = Date.prototype.getFullYear; Date.prototype.getFullYear = function() { console.log("Warning: the script tried to read the current date."); console.log("If it doesn't work correctly (eg. fails to decrypt a string,"); console.log("try editing patch.js with a different year."); // return 2017; - return fullYearGetter007.call(this); + return fullYearGetter.call(this); }; Date.prototype.getYear = function() { return this.getFullYear(); From a0de62a00e05f8ad074c88c8622099fd23f63757 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 15 Nov 2022 09:54:03 -0600 Subject: [PATCH 64/78] Don't add patch code twice. --- analyze.js | 9 +++++++-- patch.js | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/analyze.js b/analyze.js index bba57ad..4961baa 100644 --- a/analyze.js +++ b/analyze.js @@ -368,8 +368,13 @@ if (argv["prepended-code"]) { code = prependedCode + "\n\n" + code } -// prepend patch code -code = fs.readFileSync(path.join(__dirname, "patch.js"), "utf8") + code; +// prepend patch code, unless it is already there. +if (!code.includes("let __PATCH_CODE_ADDED__ = true;")) { + code = fs.readFileSync(path.join(__dirname, "patch.js"), "utf8") + code; +} +else { + console.log("Patch code already added."); +} // append more code code += "\n\n" + fs.readFileSync(path.join(__dirname, "appended-code.js")); diff --git a/patch.js b/patch.js index 3c8357c..e7d658b 100644 --- a/patch.js +++ b/patch.js @@ -1,4 +1,5 @@ -/* Patches from box-js */ +/* !!!! Patches from box-js !!!! */ +let __PATCH_CODE_ADDED__ = true; window = this; _globalTimeOffset = 0; From 31c9091a5e594326c1596c4b5cf0447a856693dc Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 16 Nov 2022 14:36:47 -0500 Subject: [PATCH 65/78] Don't batch analyze files in output dir. --- _run.js | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/_run.js b/_run.js index 368d5ee..b5560bf 100644 --- a/_run.js +++ b/_run.js @@ -4,6 +4,17 @@ const path = require("path"); const walk = require("walk-sync"); const argv = require("./argv.js").run; +function list_delete(arr, item) { + for( var i = 0; i < arr.length; i++){ + + if ( arr[i] === item) { + arr.splice(i, 1); + i--; + } + } + return arr; +} + // Track whether we should return an error shell code or not. var single_sample = false; @@ -75,7 +86,13 @@ const [targets, options] = args.functionalSplit(fs.existsSync); // Array of {filepath, filename} const tasks = []; -const [folders, files] = targets.functionalSplit(path => fs.statSync(path).isDirectory()); +var [folders, files] = targets.functionalSplit(path => fs.statSync(path).isDirectory()); + +// The output dir does not have samples to analyze. +const outputDir = argv["output-dir"] || "./"; +if (outputDir != "./") { + folders = list_delete(folders, outputDir); +} files .map(filepath => ({ @@ -108,15 +125,16 @@ if (argv.threads === 0) q.concurrency = Infinity; else if (argv.threads) q.concurrency = argv.threads; else q.concurrency = require("os").cpus().length; -if (tasks.length > 1) // If batch mode - if (argv.threads) +if (tasks.length > 1) { // If batch mode + if (argv.threads) { console.log(`Analyzing ${tasks.length} items with ${q.concurrency} threads`) -else { - console.log(`Analyzing ${tasks.length} items with ${q.concurrency} threads (use --threads to change this value)`) + } + else { + console.log(`Analyzing ${tasks.length} items with ${q.concurrency} threads (use --threads to change this value)`) + } } // queue the input files for analysis -const outputDir = argv["output-dir"] || "./"; tasks.forEach(({filepath, filename}) => q.push(cb => analyze(filepath, filename, cb))); let completed = 0; From 43f42436ba6437e049ad2b246bf2e8c91e748d8c Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Mon, 21 Nov 2022 10:57:36 -0600 Subject: [PATCH 66/78] Better rewriting of 'use strict'. --- analyze.js | 2 +- boilerplate.js | 5 + package-lock.json | 3727 +-------------------------------------------- 3 files changed, 26 insertions(+), 3708 deletions(-) diff --git a/analyze.js b/analyze.js index 4961baa..505db77 100644 --- a/analyze.js +++ b/analyze.js @@ -64,7 +64,7 @@ function rewrite(code) { // box-js is assuming that the JS will be run on Windows with cscript or wscript. // Neither of these engines supports strict JS mode, so remove those calls from // the code. - code = code.toString().replace(/"use strict"/g, '"STRICT MODE NOT SUPPORTED"'); + code = code.toString().replace(/("|')use strict("|')/g, '"STRICT MODE NOT SUPPORTED"'); // Some samples (for example that use JQuery libraries as a basis to which to // add malicious code) won't emulate properly for some reason if there is not diff --git a/boilerplate.js b/boilerplate.js index 95af3bd..5bfccd6 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -588,3 +588,8 @@ class XMLHttpRequest { send() {}; }; + +// Some JS checks to see if these are defined. Do very basic stubbing +// until better stubbing is needed. +exports = {}; +module = {}; diff --git a/package-lock.json b/package-lock.json index d4863b8..2267bca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,3692 +1,8 @@ { "name": "box-js", "version": "1.9.18", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "box-js", - "version": "1.9.16", - "license": "MIT", - "dependencies": { - "acorn": "^5.6.2", - "columnify": "*", - "command-line-args": "^4.0.7", - "escodegen": "^1.9.1", - "global": "^4.4.0", - "iconv-lite": "^0.4.23", - "jschardet": "^1.6.0", - "jsdom": "^16.2.2", - "limiter": "^1.1.3", - "node-html-parser": "*", - "queue": "^4.4.2", - "sync-request": "^6.0.0", - "system-registry": "^1.0.0", - "uglify-es": "^3.3.9", - "uuid": "^3.2.1", - "vm2": "^3.9.10", - "walk-sync": "^0.3.2" - }, - "bin": { - "box-export": "integrations/export/export.js", - "box-js": "run.js" - }, - "devDependencies": { - "babel-eslint": "^8.2.3", - "eslint": "^8.21.0", - "eslint-config-google": "*", - "mocha": "^10.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz", - "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==", - "dev": true, - "dependencies": { - "@babel/highlight": "7.0.0-beta.44" - } - }, - "node_modules/@babel/generator": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz", - "integrity": "sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ==", - "dev": true, - "dependencies": { - "@babel/types": "7.0.0-beta.44", - "jsesc": "^2.5.1", - "lodash": "^4.2.0", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz", - "integrity": "sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg==", - "dev": true, - "dependencies": { - "@babel/helper-get-function-arity": "7.0.0-beta.44", - "@babel/template": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz", - "integrity": "sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw==", - "dev": true, - "dependencies": { - "@babel/types": "7.0.0-beta.44" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz", - "integrity": "sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA==", - "dev": true, - "dependencies": { - "@babel/types": "7.0.0-beta.44" - } - }, - "node_modules/@babel/highlight": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz", - "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==", - "dev": true, - "dependencies": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "node_modules/@babel/template": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz", - "integrity": "sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44", - "babylon": "7.0.0-beta.44", - "lodash": "^4.2.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz", - "integrity": "sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.0.0-beta.44", - "@babel/generator": "7.0.0-beta.44", - "@babel/helper-function-name": "7.0.0-beta.44", - "@babel/helper-split-export-declaration": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44", - "babylon": "7.0.0-beta.44", - "debug": "^3.1.0", - "globals": "^11.1.0", - "invariant": "^2.2.0", - "lodash": "^4.2.0" - } - }, - "node_modules/@babel/types": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz", - "integrity": "sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "lodash": "^4.2.0", - "to-fast-properties": "^2.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", - "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-OU2+C7X+5Gs42JZzXoto7yOQ0A0=", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/form-data": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", - "integrity": "sha1-yayFsqX9GENbjIXZ7LUObWyJP/g=", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "9.6.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.21.tgz", - "integrity": "sha512-zQS6mHzxEstR8Vvnpc3JDUCDGWnHFzMTcBu9UCZoVLuj1Uvkkk0qFKJQEhlvbsX34m3xt12ejV09eO/ljZcn7A==" - }, - "node_modules/@types/qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-mNhVdZHdtKHMMxbqzNK3RzkBcN1cux3AvuCYGTvjEIQT2uheH3eCAyYsbMbh2Bq8nXkeOWs1kyDiF7geWRFQ4Q==" - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" - }, - "node_modules/acorn": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", - "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", - "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz", - "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/babel-eslint": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.3.tgz", - "integrity": "sha512-0HeSTtaXg/Em7FCUWxwOT+KeFSO1O7LuRuzhk7g+1BjwdlQGlHq4OyMi3GqGxrNfEq8jEi6Hmt5ylEQUhurgiQ==", - "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.0.0-beta.44", - "@babel/traverse": "7.0.0-beta.44", - "@babel/types": "7.0.0-beta.44", - "babylon": "7.0.0-beta.44", - "eslint-scope": "~3.7.1", - "eslint-visitor-keys": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/babylon": { - "version": "7.0.0-beta.44", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz", - "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g==", - "dev": true, - "bin": { - "babylon": "bin/babylon.js" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/buffer-from": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", - "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "node_modules/chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", - "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", - "deprecated": "XSS vulnerability fixed in v1.0.3", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, - "dependencies": { - "color-name": "^1.1.1" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/columnify": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", - "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", - "dependencies": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" - } - }, - "node_modules/combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/command-line-args": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz", - "integrity": "sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA==", - "dependencies": { - "array-back": "^2.0.0", - "find-replace": "^1.0.3", - "typical": "^2.6.1" - }, - "bin": { - "command-line-args": "bin/cli.js" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" - }, - "node_modules/data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" - }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" - }, - "node_modules/defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dependencies": { - "clone": "^1.0.2" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/ensure-posix-path": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ensure-posix-path/-/ensure-posix-path-1.0.2.tgz", - "integrity": "sha1-pls+QtC3HPxYXrd0+ZQ8jZuRsMI=" - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz", - "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", - "dependencies": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=4.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.21.0.tgz", - "integrity": "sha512-/XJ1+Qurf1T9G2M5IHrsjp+xrGT73RZf23xA1z5wB1ZzzEAWSZKvRwhWxTFp1rvkvCfwcvAUNAP31bhKTTGfDA==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.10.4", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.3", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-google": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.9.1.tgz", - "integrity": "sha512-5A83D+lH0PA81QMESKbLJd/a3ic8tPZtwUmqNrxMRo54nfFaUvtt89q/+icQ+fd66c2xQHn0KyFkzJDoAUfpZA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - }, - "peerDependencies": { - "eslint": ">=4.1.1" - } - }, - "node_modules/eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "dev": true, - "dependencies": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/eslint/node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint/node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/espree": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.3.tgz", - "integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==", - "dev": true, - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/espree/node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-replace": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-1.0.3.tgz", - "integrity": "sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A=", - "dependencies": { - "array-back": "^1.0.4", - "test-value": "^2.1.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/find-replace/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", - "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", - "dev": true - }, - "node_modules/form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", - "engines": { - "node": ">=4" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "dependencies": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, - "node_modules/globals": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.5.0.tgz", - "integrity": "sha512-hYyf+kI8dm3nORsiiXUQigOU62hDLfJ9G01uyGMxhc6BKsircrUhC4uJPQPUSuq2GrTmiiEt7ewxlMdBewfmKQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dependencies": { - "whatwg-encoding": "^1.0.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/http-basic": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-7.0.0.tgz", - "integrity": "sha1-gvClBr6UJzLsje6+6A50bvVzbbo=", - "dependencies": { - "@types/concat-stream": "^1.6.0", - "@types/node": "^9.4.1", - "caseless": "~0.12.0", - "concat-stream": "^1.4.6", - "http-response-object": "^3.0.1", - "parse-cache-control": "^1.0.1" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/http-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/http-response-object": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.1.tgz", - "integrity": "sha512-6L0Fkd6TozA8kFSfh9Widst0wfza3U1Ex2RjJ6zNDK0vR1U1auUR6jY4Nn2Xl7CCy0ikFmxW1XcspVpb9RvwTg==", - "dependencies": { - "@types/node": "^9.3.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jschardet": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.6.0.tgz", - "integrity": "sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ==", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/jsdom/node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/jsdom/node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/jsdom/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jsdom/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/jsdom/node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jsdom/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jsesc": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", - "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/limiter": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.3.tgz", - "integrity": "sha512-zrycnIMsLw/3ZxTbW7HCez56rcFGecWTx5OZNplzcXUUmJLmoYArC6qdJzmAN5BWiNXGcpjhF9RQ1HSv5zebEw==" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true, - "dependencies": { - "js-tokens": "^3.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/matcher-collection": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/matcher-collection/-/matcher-collection-1.0.4.tgz", - "integrity": "sha1-L2auCGmZbynkPQtiyD3R1D5YF1U=", - "dependencies": { - "minimatch": "^3.0.2" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "dependencies": { - "mime-db": "~1.33.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", - "dependencies": { - "dom-walk": "^0.1.0" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", - "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==", - "dev": true, - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/node-html-parser": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-5.4.1.tgz", - "integrity": "sha512-xy/O2wOEBJsIRLs4avwa1lVY7tIpXXOoHHUJLa0GvnoPPqMG1hgBVl1tNI3GHOwRktTVZy+Y6rjghk4B9/NLyg==", - "dependencies": { - "css-select": "^4.2.1", - "he": "1.2.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-cache-control": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha1-juqz5U+laSD+Fro493+iGqzC104=" - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "node_modules/promise": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.0.1.tgz", - "integrity": "sha1-5F1osAoXZHttpxG/he1u1HII9FA=", - "dependencies": { - "asap": "~2.0.3" - } - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/queue": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz", - "integrity": "sha512-fSMRXbwhMwipcDZ08enW2vl+YDmAmhcNcr43sCJL8DIg+CFOsoRLG23ctxA+fwNk1w55SePSiS7oqQQSgQoVJQ==", - "dependencies": { - "inherits": "~2.0.0" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" - }, - "node_modules/sync-request": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.0.0.tgz", - "integrity": "sha512-jGNIAlCi9iU4X3Dm4oQnNQshDD3h0/1A7r79LyqjbjUnj69sX6mShAXlhRXgImsfVKtTcnra1jfzabdZvp+Lmw==", - "dependencies": { - "http-response-object": "^3.0.1", - "sync-rpc": "^1.2.1", - "then-request": "^6.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/sync-rpc": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.4.tgz", - "integrity": "sha512-Iug+t1ICVFenUcTnDu8WXFnT+k8IVoLKGh8VA3eXUtl2Rt9SjKX3YEv33OenABqpTPL9QEaHv1+CNn2LK8vMow==", - "dependencies": { - "get-port": "^3.1.0" - } - }, - "node_modules/system-registry": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/system-registry/-/system-registry-1.0.0.tgz", - "integrity": "sha512-FygfR3B5PNT84gGW84Qn3jjO+HUd3iYV1AI46IvLtl87vOBs5ctzM1qf2IK/l6AhM36Rovb2XQRoJSPVNKKK4g==" - }, - "node_modules/test-value": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", - "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", - "dependencies": { - "array-back": "^1.0.3", - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/test-value/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/then-request": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.0.tgz", - "integrity": "sha512-xA+7uEMc+jsQIoyySJ93Ad08Kuqnik7u6jLS5hR91Z3smAoCfL3M8/MqMlobAa9gzBfO9pA88A/AntfepkkMJQ==", - "dependencies": { - "@types/concat-stream": "^1.6.0", - "@types/form-data": "0.0.33", - "@types/node": "^8.0.0", - "@types/qs": "^6.2.31", - "caseless": "~0.12.0", - "concat-stream": "^1.6.0", - "form-data": "^2.2.0", - "http-basic": "^7.0.0", - "http-response-object": "^3.0.1", - "promise": "^8.0.0", - "qs": "^6.4.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/then-request/node_modules/@types/node": { - "version": "8.10.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.19.tgz", - "integrity": "sha512-+PU57o6DtOSx0/algmxgCwWrmCiomwC/K+LPfXonT0tQMbNTjHEqVzwL9dFEhFoPmLFIiSWjRorLH6Z0hJMT+Q==" - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "node_modules/typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=" - }, - "node_modules/uglify-es": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", - "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", - "deprecated": "support for ECMAScript is superseded by `uglify-js` as of v3.13.0", - "dependencies": { - "commander": "~2.13.0", - "source-map": "~0.6.1" - }, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uglify-es/node_modules/commander": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==" - }, - "node_modules/uglify-es/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/vm2": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.10.tgz", - "integrity": "sha512-AuECTSvwu2OHLAZYhG716YzwodKCIJxB6u1zG7PgSQwIgAlEaoXH52bxdcvT8GkGjnYK7r7yWDW0m0sOsPuBjQ==", - "dependencies": { - "acorn": "^8.7.0", - "acorn-walk": "^8.2.0" - }, - "bin": { - "vm2": "bin/vm2" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/vm2/node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/vm2/node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/walk-sync": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/walk-sync/-/walk-sync-0.3.2.tgz", - "integrity": "sha512-FMB5VqpLqOCcqrzA9okZFc0wq0Qbmdm396qJxvQZhDpyu0W95G9JCmp74tx7iyYnyOcBtUuKJsgIKAqjozvmmQ==", - "dependencies": { - "ensure-posix-path": "^1.0.0", - "matcher-collection": "^1.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "engines": { - "node": ">=10.4" - } - }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dependencies": { - "iconv-lite": "0.4.24" - } - }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" - }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, "dependencies": { "@babel/code-frame": { "version": "7.0.0-beta.44", @@ -4106,7 +422,7 @@ "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, "brace-expansion": { "version": "1.1.8", @@ -4725,8 +1041,7 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.9.1.tgz", "integrity": "sha512-5A83D+lH0PA81QMESKbLJd/a3ic8tPZtwUmqNrxMRo54nfFaUvtt89q/+icQ+fd66c2xQHn0KyFkzJDoAUfpZA==", - "dev": true, - "requires": {} + "dev": true }, "eslint-scope": { "version": "3.7.1", @@ -4782,8 +1097,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "eslint-visitor-keys": { "version": "3.3.0", @@ -4974,7 +1288,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "fsevents": { @@ -5181,7 +1495,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { "once": "^1.3.0", @@ -5263,7 +1577,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "js-tokens": { @@ -5685,7 +1999,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { "wrappy": "1" @@ -5750,7 +2064,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, "path-key": { @@ -5951,14 +2265,6 @@ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -5987,6 +2293,14 @@ } } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -6369,14 +2683,13 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "ws": { "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "requires": {} + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==" }, "xml-name-validator": { "version": "3.0.0", @@ -6434,4 +2747,4 @@ "dev": true } } -} \ No newline at end of file +} From 7e4b8f3619ed7cb667d92d2cb67eeea91fdfbd68 Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 21 Dec 2022 14:30:17 -0500 Subject: [PATCH 67/78] Return shell code 0 when timing out. --- _run.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_run.js b/_run.js index b5560bf..0925c54 100644 --- a/_run.js +++ b/_run.js @@ -169,7 +169,7 @@ function analyze(filepath, filename, cb) { console.log("Hint: if the script is heavily obfuscated, --preprocess --unsafe-preprocess can speed up the emulation."); worker.kill(); // Useful analysis may have occurred. - if (argv.debug) process.exit(0); + process.exit(0); cb(); }, timeout * 1000); From e4d50d849cb029be9441d71d67ee10b0a664335c Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Fri, 23 Dec 2022 13:28:54 -0600 Subject: [PATCH 68/78] More object stubbing. --- boilerplate.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index 5bfccd6..809822b 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -305,8 +305,17 @@ var document = { referrer: 'https://bing.com/', body: __createElement("__document_body__"), location: location, + head: { + innerHTML: "", + append: function(x) { + console.log(x); + }, + }, defaultView: {}, cookie: "", + ready: function(func) { + func(); + }, getElementById : function(id) { var char_codes_to_string = function (str) { @@ -411,7 +420,10 @@ var ShareLink = { }; // Initial stubbed function. Add items a needed. -function define() {}; +function define(path, func) { + // Run the function. + func({}, {}, {}, {}, {}); +}; define.amd = true; // These could be due to a bug in a sample, but added this to @@ -435,6 +447,7 @@ var funcDict = { val: function() {}, scroll: function() {}, ready: function() {}, + document: function() {}, load: function() {}, extend: function() { return {}; }, attr: function(field) { return ".attr(" + field + ")"; }, @@ -472,11 +485,15 @@ var funcDict = { resize: function() {}, blur: function() {}, }; -var jQuery = function(){ +var jQuery = function(field){ + if (typeof(field) != "undefined") { + return field; + }; return funcDict; }; // Global object form of jQuery. +$ = jQuery; // Ugh, shorthand name. jQuery.jquery = "2.6.1"; jQuery.fn = { jquery: "2.6.1", From a065c8132b18b92e37a8cccc2bdd4d9b4bc7f4a4 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 27 Dec 2022 16:28:27 -0600 Subject: [PATCH 69/78] Loop rewriting tweak. --- loop_rewriter.js | 3 +++ patches/except_while_loop.js | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/loop_rewriter.js b/loop_rewriter.js index aa84c16..08c7807 100644 --- a/loop_rewriter.js +++ b/loop_rewriter.js @@ -72,6 +72,9 @@ function rewriteSimpleControlLoop(key, val) { // Possible calling funtion from array in try block? if (line1.type != "ExpressionStatement") return; line1 = line1.expression; + if (line1.type == "AssignmentExpression") { + line1 = line1.right; + } if (line1.type != "CallExpression") return; if (line1.callee.type != "MemberExpression") return; diff --git a/patches/except_while_loop.js b/patches/except_while_loop.js index ba8b6fe..e7236d9 100644 --- a/patches/except_while_loop.js +++ b/patches/except_while_loop.js @@ -31,13 +31,25 @@ function GenSimpleLoop(fexpr) { // Do function calls only for defined entries in an array. var tryBody = oldBody.body[0].block.body; - var arrayAcc = tryBody[0].expression.callee; + if (Array.isArray(tryBody)) { + tryBody = tryBody[0]; + } + if ((tryBody.type == "ExpressionStatement") && (tryBody.expression.type == "AssignmentExpression")) { + tryBody = tryBody.expression.right; + } + var arrayAcc = ""; + if (typeof(tryBody.expression) != "undefined") { + arrayAcc = tryBody.expression.callee; + } + else { + arrayAcc = tryBody.callee; + } var undef = { type: "Identifier", name: "undefined" }; var ifTest = MakeBinaryExpression(arrayAcc, undef, "!="); - var funcCall = tryBody[0]; + var funcCall = tryBody; var newIf = MakeIfThen(ifTest, funcCall); // In new loop body do guarded call followed by existing var update. From be7bcd790d465a4c49c92d8f510c4fdf2d5bdc7b Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Mon, 9 Jan 2023 14:30:44 -0600 Subject: [PATCH 70/78] Handle many small writes to a large file. --- lib.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lib.js b/lib.js index 9337266..3cc1832 100644 --- a/lib.js +++ b/lib.js @@ -83,6 +83,7 @@ fileWriteCount = {}; // If needed stop writing bytes to very large files. const MAXBYTES = 1e+6 * 10; // 10MB +resourceWriteCount = {}; var throttleWrites = false; tooBigFiles = {}; @@ -254,8 +255,21 @@ module.exports = { logUrl, logResource: function(resourceName, emulatedPath, content) { - // Has this file aready gotten too large? + // Throttle lots of small writes to a resource when the resource is large. const filePath = path.join(directory, resourceName); + if (typeof(resourceWriteCount[resourceName]) == "undefined") resourceWriteCount[resourceName] = 0; + resourceWriteCount[resourceName]++; + var throttle = (resourceWriteCount[resourceName] > MAXWRITES * 50) && + (content.length > MAXBYTES/5) && throttleWrites + if (throttle) { + if (typeof(tooBigFiles[filePath]) == "undefined") { + log("warn", "File '" + filePath + "' is too big with too many small writes. Not writing."); + tooBigFiles[filePath] = true; + } + return; + } + + // Has this file aready gotten too large? if (throttleWrites && (content.length > MAXBYTES)) { if (typeof(tooBigFiles[filePath]) == "undefined") { log("warn", "File '" + filePath + "' is too big. Not writing."); @@ -282,9 +296,9 @@ module.exports = { log("warn", "Throttling file write reporting for " + filePath); } - if (/executable/.test(filetype)) { - if (doLog) log("info", `Active URL detected: ${latestUrl}`); + if (doLog && (/executable/.test(filetype))) { // Log active url + log("info", `Active URL detected: ${latestUrl}`); if (activeUrls.indexOf(latestUrl) === -1) activeUrls.push(latestUrl); fs.writeFileSync(path.join(directory, "active_urls.json"), JSON.stringify(activeUrls, null, "\t")); From 130f6a9507f1f22e310dae5805873a8004deae11 Mon Sep 17 00:00:00 2001 From: Kirk Sayre Date: Wed, 18 Jan 2023 14:13:30 -0500 Subject: [PATCH 71/78] Track GetObject("script:http...") URLs. --- emulator/WMI.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/emulator/WMI.js b/emulator/WMI.js index 231e448..8070e14 100644 --- a/emulator/WMI.js +++ b/emulator/WMI.js @@ -332,6 +332,14 @@ module.exports.GetObject = function(name) { lib.kill(`GetObject(${name}) not implemented!`); } */ + + // Track URLs from 'script:...' GetObject() creations. + const lname = name.toLowerCase(); + if (lname.startsWith("script:http")) { + lib.logUrl("GetObject()", lname.replace("script:http", "http")); + } + + // Fake up an object. return new Proxy({ UserName: "_Fake_Box-JS_User_", InstancesOf: getTable, From 3a65e9cfdd1b1f838fe01381572e9216dc5fa44a Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 24 Jan 2023 14:02:16 -0600 Subject: [PATCH 72/78] Added start of emulation for WindowsInstaller.installer ActiveX object. --- analyze.js | 3 +-- emulator/WindowsInstaller.js | 11 +++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 emulator/WindowsInstaller.js diff --git a/analyze.js b/analyze.js index 505db77..ac05bb1 100644 --- a/analyze.js +++ b/analyze.js @@ -598,8 +598,7 @@ function ActiveXObject(name) { switch (name) { case "windowsinstaller.installer": - // Stubbed out for now. - return ""; + return require("./emulator/WindowsInstaller"); case "adodb.stream": return require("./emulator/ADODBStream")(); case "adodb.recordset": diff --git a/emulator/WindowsInstaller.js b/emulator/WindowsInstaller.js new file mode 100644 index 0000000..ac2d697 --- /dev/null +++ b/emulator/WindowsInstaller.js @@ -0,0 +1,11 @@ +const lib = require("../lib"); + +function WindowsInstaller() { + + this.installproduct = function(url) { + lib.logIOC("WindowsInstaller", {"url": url}, "The script installed a remote MSI."); + lib.logUrl('Remote MSI Install', url); + }; +} + +module.exports = lib.proxify(WindowsInstaller, "WindowsInstaller"); From 5cd60af8ac558ef951995235c9390e9c55cfa0c5 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 31 Jan 2023 17:24:48 -0600 Subject: [PATCH 73/78] Tweak for reading HTML element data contents. --- boilerplate.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boilerplate.js b/boilerplate.js index 809822b..be0ade6 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -332,7 +332,8 @@ var document = { for (var i = 0; i < ids.length; i++) { if (char_codes_to_string(ids[i]) == id) { return { - innerHTML: char_codes_to_string(data[i]) + innerHTML: char_codes_to_string(data[i]), + innerText: char_codes_to_string(data[i]) } } } From ea726391c2c9b6707af8f64b780ce35ce5f1cf46 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Fri, 3 Feb 2023 10:53:16 -0600 Subject: [PATCH 74/78] Partial extension for document.querySelector(). --- boilerplate.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index be0ade6..46927e5 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -283,6 +283,11 @@ function __createElement(tag) { nodeType: 3, }, getElementsByTagName: __getElementsByTagName, + // Probably wrong, fix this if it causes problems. + querySelector: function(tag) { + return __createElement(tag); + }, + setAttribute : function() {}, cloneNode: function() { return __createElement("__clone__"); }, @@ -339,10 +344,8 @@ var document = { } } - // got nothing to return - return { - innerHTML: "" - } + // got nothing to return. Make up some fake element and hope for the best. + return __createElement(id); }, documentElement: { style: {}, From b0b7562a5e4a711aa846745cd9badfde0255cfb0 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Fri, 3 Feb 2023 18:21:43 -0600 Subject: [PATCH 75/78] Better handling of getElementById() and setTimeout(). --- boilerplate.js | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/boilerplate.js b/boilerplate.js index 46927e5..1800e7c 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -321,8 +321,12 @@ var document = { ready: function(func) { func(); }, + elementCache : {}, getElementById : function(id) { + // Already looked this up? + if (typeof(this.elementCache[id]) !== "undefined") return this.elementCache[id]; + var char_codes_to_string = function (str) { var codes = "" for (var i = 0; i < str.length; i++) { @@ -336,10 +340,20 @@ var document = { if (typeof(ids) != "undefined") { for (var i = 0; i < ids.length; i++) { if (char_codes_to_string(ids[i]) == id) { - return { + var r = { innerHTML: char_codes_to_string(data[i]), - innerText: char_codes_to_string(data[i]) - } + innerText: char_codes_to_string(data[i]), + onclick: undefined, + click: function() { + if (typeof(this.onclick) !== "undefined") this.onclick(); + }, + getAttribute: function(attrId) { + return this.attrs[attrId]; + } + }; + r.attrs = attrs[i]; + this.elementCache[id] = r; + return r; } } } @@ -586,8 +600,9 @@ Array.prototype.reduce = function(a, b) { throw "CScript JScript has no Array.reduce() method." }; -// Stubbed out for now. -function setTimeout() {}; +function setTimeout(func, time) { + func(); +}; function clearTimeout() {}; function setInterval() {}; function clearInterval() {}; From b128e7222131d8db9d2de12231f010064d28e83e Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Tue, 14 Feb 2023 12:43:01 -0600 Subject: [PATCH 76/78] Fast forward through time. --- analyze.js | 12 ------------ boilerplate.js | 29 +++++++++++++++++++++++++++++ emulator/FileSystemObject.js | 21 +++++++++++++++++---- lib.js | 6 +++--- patch.js | 17 ++++++++++++++--- 5 files changed, 63 insertions(+), 22 deletions(-) diff --git a/analyze.js b/analyze.js index ac05bb1..f7660de 100644 --- a/analyze.js +++ b/analyze.js @@ -1,4 +1,3 @@ -//const Blob = require("cross-blob"); const lib = require("./lib"); const loop_rewriter = require("./loop_rewriter"); const escodegen = require("escodegen"); @@ -484,7 +483,6 @@ const sandbox = { throw("Callback must be a function"); } }, - //Blob : Blob, logJS: lib.logJS, logIOC: lib.logIOC, logUrl: lib.logUrl, @@ -556,16 +554,6 @@ if (argv["dangerous-vm"]) { timeout: (argv.timeout || 10) * 1000, sandbox, }); - /* - const vm = new NodeVM({ - timeout: (argv.timeout || 10) * 1000, - sandbox: {}, - require: { - external: ['blob'], - import: ['blob'], - }, - }); - */ // Fake cscript.exe style ReferenceError messages. code = "ReferenceError.prototype.toString = function() { return \"[object Error]\";};\n\n" + code; diff --git a/boilerplate.js b/boilerplate.js index 1800e7c..a2b04a7 100644 --- a/boilerplate.js +++ b/boilerplate.js @@ -1,6 +1,32 @@ const parse = require("node-html-parser").parse; const lib = require("./lib.js"); +// Handle Blobs. All Blob methods in the real Blob class for dumping +// the data in a Blob are asynch and box-js is all synchronous, so +// rather than rewriting the entire tool to be asynch we are just +// stubbing out a simple Blob class that is synchronous. +class Blob { + constructor(data, type) { + this.raw_data = data; + // Convert to a data string if this is an array of bytes. + this.data = ""; + var flat = []; + for (let i = 0; i < data.length; i++) { + if ((Array.isArray(data[i])) || (data[i].constructor.name == "Uint8Array")) { + for (let j = 0; j < data[i].length; j++) { + flat.push(data[i][j]); + } + } + } + if (!flat.some(i => (!Number.isInteger(i) || (i < 0) || (i > 255)))) { + for (let i = 0; i < flat.length; i++) { + this.data += String.fromCharCode(flat[i]); + }; + } + }; +}; +Object.prototype.Blob = Blob; + // Simple Enumerator class implementation. class Enumerator { constructor(collection) { @@ -294,6 +320,9 @@ function __createElement(tag) { toLowerCase: function() { return "// NOPE"; }, + click: function() { + lib.info("click() method called on a document element."); + }, }; return fake_elem; }; diff --git a/emulator/FileSystemObject.js b/emulator/FileSystemObject.js index 4a1dbe8..ea3d44b 100644 --- a/emulator/FileSystemObject.js +++ b/emulator/FileSystemObject.js @@ -1,6 +1,7 @@ const lib = require("../lib"); const argv = require("../argv.js").run; const winpath = require("path").win32; +const crypto = require('crypto'); function TextStream(filename) { this.buffer = lib.readFile(filename) || ""; @@ -86,13 +87,24 @@ function ProxiedFolder(path, name, autospawned = false) { }); } -function File(contents) { +function File(contents, name = "example-file.exe", typ = "Application") { + lib.info("The sample created a file named '" + name + "'.") + // Handle blobs/arrays. + if ((contents.constructor.name == "Array") && (contents.length > 0)) { + contents = contents[0]; + } + if (contents.constructor.name == "Blob") { + contents = contents.data; + } + lib.writeFile(name, contents); + this.uuid = crypto.randomUUID(); + lib.logResource(this.uuid, name, contents); this.attributes = 32; this.openastextstream = () => new ProxiedTextStream(contents); this.shortpath = "C:\\PROGRA~1\\example-file.exe"; - this._name = "example-file.exe"; + this._name = name; this.size = Infinity; - this.type = "Application"; + this.type = typ; } function ProxiedFile(filename) { @@ -211,7 +223,8 @@ function FileSystemObject() { r = path.substring(start, path.length); } return r; - } + }; + this.file = File; } module.exports = lib.proxify(FileSystemObject, "FileSystemObject"); diff --git a/lib.js b/lib.js index 3cc1832..1238b4a 100644 --- a/lib.js +++ b/lib.js @@ -244,8 +244,8 @@ module.exports = { // Don't spam lots of file write info to same file. if (typeof(fileWriteCount[filename]) == "undefined") fileWriteCount[filename] = 0; fileWriteCount[filename]++; - var doLog = throttleWrites && (fileWriteCount[filename] <= MAXWRITES); - if (doLog) logIOC("FileWrite", {file: filename, contents}, "The script wrote file '" + filename + "'."); + var doLog = (!throttleWrites) || (fileWriteCount[filename] <= MAXWRITES); + if (doLog) logIOC("FileWrite", {file: filename, contents}, "The script wrote file '" + filename + "'."); files[filename] = contents; }, readFile: function(filename) { @@ -284,7 +284,7 @@ module.exports = { // Don't spam lots of file write info to same file. if (typeof(fileWriteCount[filePath]) == "undefined") fileWriteCount[filePath] = 0; fileWriteCount[filePath]++; - var doLog = throttleWrites && (fileWriteCount[filePath] <= MAXWRITES); + var doLog = (!throttleWrites) || (fileWriteCount[filePath] <= MAXWRITES); let filetype = ""; if (doLog) { log("info", `Saved ${filePath} (${content.length} bytes)`); diff --git a/patch.js b/patch.js index e7d658b..0e1c883 100644 --- a/patch.js +++ b/patch.js @@ -36,14 +36,25 @@ Date = function() { _actualTime: new legacyDate(...arguments), }, { get: (target, prop) => { - const modifiedDate = new legacyDate(target._actualTime.getTime() + _globalTimeOffset); + // Fast forward through time to foil anti-sandboxing busy + // loops. The _myOffset field caches the faked time offset + // used when the Date object was 1st looked at and + // advances if so future date objects jump forward in + // time. + if (typeof(target._myOffset) == "undefined") { + target._myOffset = _globalTimeOffset; + _globalTimeOffset += 100; + } + const modifiedDate = new legacyDate(target._actualTime.getTime() + target._myOffset); if (prop === Symbol.toPrimitive) return hint => { switch (hint) { case "string": - case "default": + case "default": { return modifiedDate.toString(); - case "number": + } + case "number": { return modifiedDate.getTime(); + } default: throw new Error("Unknown hint!"); } From 472606fa310aa9deec3adea1db1de14de2e5fdc7 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Wed, 15 Feb 2023 11:40:33 -0600 Subject: [PATCH 77/78] Tweak to loop rewriting. --- loop_rewriter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loop_rewriter.js b/loop_rewriter.js index 08c7807..23e785c 100644 --- a/loop_rewriter.js +++ b/loop_rewriter.js @@ -78,12 +78,12 @@ function rewriteSimpleControlLoop(key, val) { if (line1.type != "CallExpression") return; if (line1.callee.type != "MemberExpression") return; - // 1 statement in catch block. + // 1 or 2 statement in catch block. var catch_line = val.body.body[0].handler; if ((catch_line == undefined) || (catch_line.type != "CatchClause")) return; var catch_body = catch_line.body; if (catch_body.type != "BlockStatement") return; - if (catch_body.body.length != 1) return; + if ((catch_body.body.length != 1) && (catch_body.body.length != 2)) return; catch_body = catch_body.body[0]; // Catch statement should be an assignment. From 393e5ad2f7a734d0ec58281332812c67fa5dd945 Mon Sep 17 00:00:00 2001 From: "Kirk.Sayre" Date: Wed, 15 Feb 2023 14:03:43 -0600 Subject: [PATCH 78/78] Preparation for 1.19.20 release. --- README.md | 8 +++++++- RELEASE_NOTES.txt | 17 +++++++++++++++++ package.json | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 RELEASE_NOTES.txt diff --git a/README.md b/README.md index 84efd54..6ca6810 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,12 @@ Box.js will emulate a Windows JScript environment, print a summary of the emulat >If you wish to automate the analysis, you can use the return codes - documented in `integrations/README.md` - to distinguish between different types of errors. -## Analysis Fails Due to Missing 'document' Object +## Analysis Fails Due to Missing 'document' Object or Other Objects/Functions The box-js repository from git includes a `boilerplate.js` file. This file defines some stubbed versions of common browser objects such as document. Try rerunning your analysis with the `--prepended-code=DIR/boilerplate.js` option, where `DIR` is the directory of the cloned box-js repository. The `--prepended-code` option tells box-js to prepend the JavaScript in the given file to the sample being analyzed. +Note that you can copy boilerplate.js and add your own stubbed classes, objects, etc. as needed. + ## Batch usage While box.js is typically used on single files, it can also run batch analyses. You can simply pass a list of files or folders to analyse: @@ -88,6 +90,8 @@ cat ./*.results/active_urls.json | sort | uniq --preprocess Preprocess the original source code (makes reverse engineering easier, but takes a few seconds) --prepended-code Prepend the JavaScript in the given file to the sample prior to sandboxing + --fake-script-engine The script engine to report in WScript.FullName and WScript.Name (ex. + 'cscript.exe' or 'wscript.exe'). Default is wscript.exe. --unsafe-preprocess More aggressive preprocessing. Often results in better code, but can break on some edge cases (eg. redefining prototypes) --no-kill Do not kill the application when runtime errors occur @@ -114,6 +118,8 @@ cat ./*.results/active_urls.json | sort | uniq --dangerous-vm Use the `vm` module, rather than `vm2`. This sandbox can be broken, so **don't use this** unless you're 100% sure of what you're doing. Helps with debugging by giving correct stack traces. + --rewrite-loops Rewrite some types of loops to make analysis faster + --throttle-writes Throttle reporting and data tracking of file writes that write a LOT of data # Analyzing the output diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt new file mode 100644 index 0000000..b07a4b4 --- /dev/null +++ b/RELEASE_NOTES.txt @@ -0,0 +1,17 @@ +Version 1.19.20, 2/15/2023 +-------------------------- + +* Added anti-emulation loop rewriting functionality. +* Added functionality for faking being run with cscript.exe or wscript.exe. +* Added functionality for throttling lots of small file writes. +* Added support for WMI.GetObject.Run(). +* Added support for ADODBStream.flush(). +* Added support for InternetExplorer.Application. +* Added support for XMLHttpRequest. +* Added some stubbed JQuery functionality. +* Added support for ScheduleService. +* Track IOCs being passed through the '|' operator in analyzed JS code. +* Added support for WindowsInstaller.installer. + + + diff --git a/package.json b/package.json index 7263138..1e86ca8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "box-js", - "version": "1.9.18", + "version": "1.9.20", "description": "A tool for studying JavaScript malware.", "dependencies": { "acorn": "^5.6.2",