4LostInSpace

This commit is contained in:
2025-02-22 12:36:16 -06:00
commit 6c01fe8122
24 changed files with 4067 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
node_modules
notes.txt
tmp

4
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"editor.formatOnPaste": false,
"editor.formatOnSave": false
}

268
convert.js Normal file
View File

@@ -0,0 +1,268 @@
"use strict";
const fs = require('fs');
const JavaScriptObfuscator = require('javascript-obfuscator');
const KeyPadCode = 94;
const randomkey = (len) => (new Array(len)).fill(0).map(v => Math.round(Math.random() * 0xffffff));
// MARK: keys
function parseKeysFile() {
function parse(line) {
const re = /^\s*?(.*?)\s*?:\s*?(.*?)(?:$|\s*?#\s*?(\d+)\s*?,\s*?(.*?)\s*?$)/.exec(line);
if (!re || re.length < 3 || !re[1]) {
throw "Cannot Parse";
}
let name = re[1].trim(), data = re[2].trim(), offset, obfuscatedname;
if (re.length < 5 || re[3] === undefined) {
offset = Math.round(Math.random() * (data.length - 2) + 1);
// add a random multiple of data.length, no effect but may obfuscate the shift
offset += data.length * Math.round(Math.random() * 4);
obfuscatedname = '_0x' + Math.round(Math.random() * 0xffffff).toString(16);
}
else {
offset = parseInt(re[3].trim());
if (isNaN(offset)) {
throw 'offset is NaN';
}
obfuscatedname = re[4].trim();
}
return {
name, data, offset, obfuscatedname,
cleanLine: `${name}: ${data} # ${offset}, ${obfuscatedname}`
};
}
function createscript({ name, data, offset }) {
const k = randomkey(data.length);
const d = data.split('').map((ch, i) => {
const kk = k[(i + offset) % data.length];
if (ch === '*') {
return KeyPadCode + kk;
}
return ch.charCodeAt(0) + kk;
});
return `function ${name}key() { return ${JSON.stringify(k)} }
function ${name}data() { return ${JSON.stringify(d)} }
function ${name}check(str) { return str === getdata(${name}key, ${name}data, ${offset}) }`;
}
const file = fs.readFileSync('./src/flags').toString();
const filelines = file.split('\n');
let newfile = '';
let scriptfile = '';
let names = [];
for (let i = 0; i < filelines.length; i++) {
const line = filelines[i];
if (line.trim().length === 0) {
continue;
}
if (line.startsWith('#!')) {
continue;
}
try {
const parsed = parse(line);
newfile += parsed.cleanLine + '\n';
scriptfile += createscript(parsed) + '\n';
names.push([`${parsed.name}check`, parsed.obfuscatedname]);
}
catch (e) {
throw `Error on line ${i + 1}: ${e}`;
}
}
fs.writeFileSync('./src/flags', newfile);
fs.writeFileSync('./out/debug/flags', newfile);
return { scriptfile, names };
}
// MARK: hints
function parseHints() {
function parse(line) {
const re = /^(.*?):\s*?(.*?)(?:$|\s*?;\s*?(.*?)(?:$|\s*?#\s*?(\d+)\s*?,\s*?(.*?)\s*?$))/.exec(line);
if (!re || re.length < 3 || re[1] === undefined) {
throw "Cannot Parse";
}
let name = re[1].trim(), hintraw = re[2].trim(), alertraw = (re[3] ?? '').trim(), offset, obfuscatedname;
let hint = hintraw.replaceAll('\\n', '\n');
let alert = alertraw.replaceAll('\\n', '\n');
let data = btoa(JSON.stringify([hint, alert]));
if (re.length < 6 || !re[4]) {
offset = Math.round(Math.random() * (data.length - 2) + 1);
// add a random multiple of data.length, no effect but may obfuscate the shift
offset += data.length * Math.round(Math.random() * 4);
obfuscatedname = '_0x' + Math.round(Math.random() * 0xffffff).toString(16);
}
else {
offset = parseInt(re[4].trim());
if (isNaN(offset)) {
throw 'offset is NaN';
}
obfuscatedname = re[5].trim();
}
return {
name, data, offset, obfuscatedname,
cleanLine: `${name}: ${hintraw} ; ${alertraw} # ${offset}, ${obfuscatedname}`
};
}
function createscript({ name, data, offset }) {
const k = randomkey(data.length);
const d = data.split('').map((ch, i) => {
const kk = k[(i + offset) % data.length];
if (ch === '*') {
return KeyPadCode + kk;
}
return ch.charCodeAt(0) + kk;
});
return `function h_${name}key() { return ${JSON.stringify(k)} }
function h_${name}data() { return ${JSON.stringify(d)} }
function hint_${name}() { return getdata(h_${name}key, h_${name}data, ${offset}) }`;
}
const file = fs.readFileSync('./src/hints').toString();
const filelines = file.split('\n');
let newfile = '';
let scriptfile = '';
let names = [];
for (let i = 0; i < filelines.length; i++) {
const line = filelines[i];
if (line.trim().length === 0 || line.startsWith('#')) {
continue;
}
try {
const parsed = parse(line);
newfile += parsed.cleanLine + '\n';
scriptfile += createscript(parsed) + '\n';
names.push([`hint_${parsed.name}`, parsed.obfuscatedname]);
}
catch (e) {
throw `Error on line ${i + 1}: ${e}`;
}
}
fs.writeFileSync('./src/hints', newfile);
fs.writeFileSync('./out/debug/hints', newfile);
return { scriptfile, names };
}
// MARK: obfuscate
function obfuscateCore(core, reservedNames) {
return JavaScriptObfuscator.obfuscate(core, {
optionsPreset: 'default',
seed: 7,
target: 'browser',
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1,
identifierNamesGenerator: 'hexadecimal',
numbersToExpressions: true,
renameGlobals: true,
renameProperties: true,
renamePropertiesMode: 'safe',
reservedNames,
stringArray: false,
transformObjectKeys: true,
}).getObfuscatedCode();
}
function obfuscateMain(mainjs) {
const file = fs.readFileSync('./src/core.js').toString();
mainjs += '\n' + file;
return JavaScriptObfuscator.obfuscate(mainjs, {
optionsPreset: 'high-obfuscation',
seed: 13,
target: 'browser',
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 0.9,
deadCodeInjection: true,
deadCodeInjectionThreshold: 0.8,
debugProtection: true,
debugProtectionInterval: 2000,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
numbersToExpressions: true,
renameGlobals: true,
renameProperties: true,
renamePropertiesMode: 'safe',
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 4,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 0.9,
stringArrayEncoding: ['rc4'],
stringArrayIndexesType: ['hexadecimal-number', 'hexadecimal-numeric-string'],
stringArrayWrappersCount: 1,
stringArrayWrappersParametersMaxCount: 3,
stringArrayWrappersType: 'function',
stringArrayThreshold: 0.9,
transformObjectKeys: true,
log: true
//domainLock
}).getObfuscatedCode();
}
function doswap(b64) {
function swap(b64, c1, c2) { return b64.replaceAll(c1, '#').replaceAll(c2, c1).replaceAll('#', c2); }
b64 = swap(b64, '8', 'f');
b64 = swap(b64, 'W', '2');
b64 = swap(b64, 'M', 'C');
b64 = swap(b64, 'z', 'm');
b64 = swap(b64, 'a', 'S');
b64 = swap(b64, 'H', 'l');
b64 = swap(b64, 'e', 'Y');
return b64;
}
// MARK: templating
function loadMainjs(coreObfuscatedB64swap) {
const file = fs.readFileSync('./src/main.js').toString();
return file.replace('{{TEXT}}', coreObfuscatedB64swap);
}
function loadDesign(script) {
const file = fs.readFileSync('./src/design.html').toString();
const split = file.split('{{TEXT}}');
return split[0] + script + split[1];
//return file.replace('{{TEXT}}', script)
}
// MARK: main
function main() {
if (fs.existsSync('./out')) {
fs.rmSync('./out', { recursive: true, force: true });
}
fs.mkdirSync('./out');
fs.mkdirSync('./out/debug');
console.log('Parsing keys');
const keysFile = parseKeysFile();
console.log('Parsing hints');
const hintsFile = parseHints();
const renames = [
["getFinalImage", "_0xc65ffb"],
...keysFile.names,
...hintsFile.names
];
console.log('Loading core.js');
const file = fs.readFileSync('./src/core.js').toString();
const scriptfile = keysFile.scriptfile + '\n' + hintsFile.scriptfile + '\n' + file;
fs.writeFileSync('./out/debug/core.js', scriptfile);
console.log('Obfuscating core.js');
let coreObfuscated = obfuscateCore(scriptfile, [...renames.map(v => v[0])]);
for (let name of renames) {
coreObfuscated = coreObfuscated.replace(`function ${name[0]}(`, `function ${name[1]}(`);
}
coreObfuscated += `function dear_osint_hater() { return "You made it so far! The end is almost here. Since you decided to destroy my hard work, you will not reach the final prize the normal way, so here you go: https://zomo.land/hosted/startrekctf.png. Good luck finding the flag!" }`;
fs.writeFileSync('./out/debug/core.obfuscated', coreObfuscated);
console.log('Converting core.js to base64');
const coreObfuscatedB64 = btoa(coreObfuscated);
fs.writeFileSync('./out/debug/core.obfuscated.base64', coreObfuscatedB64);
console.log('Obfuscating core.js base64');
const coreObfuscatedB64swap = doswap(coreObfuscatedB64);
fs.writeFileSync('./out/debug/core.obfuscated.base64.obfuscated', coreObfuscatedB64swap);
console.log('Loading main.js');
const mainjs = loadMainjs(coreObfuscatedB64swap);
fs.writeFileSync('./out/debug/main.js', mainjs);
console.log('Creating nonobfuscated.html');
const mainhtml = loadDesign(mainjs);
fs.writeFileSync('./out/debug/nonobfuscated.html', mainhtml);
if (process.argv[2] === 'dev') {
console.log('Flag dev: skipping obfuscation');
return;
}
console.log('Obfuscating main.js');
const mainjsObfuscated = obfuscateMain(mainjs);
fs.writeFileSync('./out/debug/main.obfuscated', mainjsObfuscated);
console.log('Creating file.html');
const mainhtmlObfuscated = loadDesign(mainjsObfuscated);
fs.writeFileSync('./out/debug/final.html', mainhtmlObfuscated);
fs.writeFileSync('./out/4LostInSpace.html', mainhtmlObfuscated);
}
main();

327
convert.ts Normal file
View File

@@ -0,0 +1,327 @@
const fs = require('fs')
const JavaScriptObfuscator = require('javascript-obfuscator');
const KeyPadCode = 94
const randomkey = (len: number) => (new Array(len)).fill(0).map(v => Math.round(Math.random() * 0xffffff))
interface parsedKeyedLine {
name: string,
data: string,
offset: number,
obfuscatedname: string,
cleanLine: string
}
// MARK: keys
function parseKeysFile() {
function parse(line: string): parsedKeyedLine {
const re = /^\s*?(.*?)\s*?:\s*?(.*?)(?:$|\s*?#\s*?(\d+)\s*?,\s*?(.*?)\s*?$)/.exec(line)
if (!re || re.length < 3 || !re[1]) {
throw "Cannot Parse"
}
let name = re[1].trim(),
data = re[2].trim(),
offset: number,
obfuscatedname: string
if (re.length < 5 || re[3] === undefined) {
offset = Math.round(Math.random() * (data.length - 2) + 1)
// add a random multiple of data.length, no effect but may obfuscate the shift
offset += data.length * Math.round(Math.random() * 4)
obfuscatedname = '_0x' + Math.round(Math.random() * 0xffffff).toString(16)
} else {
offset = parseInt(re[3].trim())
if (isNaN(offset)) {
throw 'offset is NaN'
}
obfuscatedname = re[4].trim()
}
return {
name, data, offset, obfuscatedname,
cleanLine: `${name}: ${data} # ${offset}, ${obfuscatedname}`
}
}
function createscript({ name, data, offset }: parsedKeyedLine) {
const k = randomkey(data.length)
const d = data.split('').map((ch, i) => {
const kk = k[(i + offset) % data.length]
if (ch === '*') {
return KeyPadCode + kk
}
return ch.charCodeAt(0) + kk
})
return `function ${name}key() { return ${JSON.stringify(k)} }
function ${name}data() { return ${JSON.stringify(d)} }
function ${name}check(str) { return str === getdata(${name}key, ${name}data, ${offset}) }`
}
const file = fs.readFileSync('./src/flags').toString()
const filelines = file.split('\n')
let newfile = ''
let scriptfile = ''
let names: [string, string][] = []
for (let i = 0; i < filelines.length; i++) {
const line = filelines[i]
if (line.trim().length === 0) {
continue
}
if (line.startsWith('#!')) {
continue
}
try {
const parsed = parse(line)
newfile += parsed.cleanLine + '\n'
scriptfile += createscript(parsed) + '\n'
names.push([`${parsed.name}check`, parsed.obfuscatedname])
} catch (e) {
throw `Error on line ${i + 1}: ${e}`
}
}
fs.writeFileSync('./src/flags', newfile)
fs.writeFileSync('./out/debug/flags', newfile)
return {scriptfile, names}
}
// MARK: hints
function parseHints() {
function parse(line: string): parsedKeyedLine {
const re = /^(.*?):\s*?(.*?)(?:$|\s*?;\s*?(.*?)(?:$|\s*?#\s*?(\d+)\s*?,\s*?(.*?)\s*?$))/.exec(line)
if (!re || re.length < 3 || re[1] === undefined) {
throw "Cannot Parse"
}
let name = re[1].trim(),
hintraw = re[2].trim(),
alertraw = (re[3] ?? '').trim(),
offset: number,
obfuscatedname: string
let hint = hintraw.replaceAll('\\n', '\n')
let alert = alertraw.replaceAll('\\n', '\n')
let data = btoa(JSON.stringify([hint, alert]))
if (re.length < 6 || !re[4]) {
offset = Math.round(Math.random() * (data.length - 2) + 1)
// add a random multiple of data.length, no effect but may obfuscate the shift
offset += data.length * Math.round(Math.random() * 4)
obfuscatedname = '_0x' + Math.round(Math.random() * 0xffffff).toString(16)
} else {
offset = parseInt(re[4].trim())
if (isNaN(offset)) {
throw 'offset is NaN'
}
obfuscatedname = re[5].trim()
}
return {
name, data, offset, obfuscatedname,
cleanLine: `${name}: ${hintraw} ; ${alertraw} # ${offset}, ${obfuscatedname}`
}
}
function createscript({ name, data, offset }: parsedKeyedLine) {
const k = randomkey(data.length)
const d = data.split('').map((ch, i) => {
const kk = k[(i + offset) % data.length]
if (ch === '*') {
return KeyPadCode + kk
}
return ch.charCodeAt(0) + kk
})
return `function h_${name}key() { return ${JSON.stringify(k)} }
function h_${name}data() { return ${JSON.stringify(d)} }
function hint_${name}() { return getdata(h_${name}key, h_${name}data, ${offset}) }`
}
const file = fs.readFileSync('./src/hints').toString()
const filelines = file.split('\n')
let newfile = ''
let scriptfile = ''
let names: [string, string][] = []
for (let i = 0; i < filelines.length; i++) {
const line = filelines[i]
if (line.trim().length === 0 || line.startsWith('#')) {
continue
}
try {
const parsed = parse(line)
newfile += parsed.cleanLine + '\n'
scriptfile += createscript(parsed) + '\n'
names.push([`hint_${parsed.name}`, parsed.obfuscatedname])
} catch (e) {
throw `Error on line ${i + 1}: ${e}`
}
}
fs.writeFileSync('./src/hints', newfile)
fs.writeFileSync('./out/debug/hints', newfile)
return {scriptfile, names}
}
// MARK: obfuscate
function obfuscateCore(core: string, reservedNames: string[]) {
return JavaScriptObfuscator.obfuscate(core, {
optionsPreset: 'default',
seed: 7,
target: 'browser',
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1,
identifierNamesGenerator: 'hexadecimal',
numbersToExpressions: true,
renameGlobals: true,
renameProperties: true,
renamePropertiesMode: 'safe',
reservedNames,
stringArray: false,
transformObjectKeys: true,
}).getObfuscatedCode()
}
function obfuscateMain(mainjs: string) {
const file = fs.readFileSync('./src/core.js').toString()
mainjs += '\n' + file
return JavaScriptObfuscator.obfuscate(mainjs, {
optionsPreset: 'high-obfuscation',
seed: 13,
target: 'browser',
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 0.8,
deadCodeInjection: true,
deadCodeInjectionThreshold: 0.8,
debugProtection: true,
debugProtectionInterval: 2000,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
numbersToExpressions: true,
renameGlobals: true,
renameProperties: true,
renamePropertiesMode: 'safe',
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 4,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 0.8,
stringArrayEncoding: ['rc4'],
stringArrayIndexesType: ['hexadecimal-number', 'hexadecimal-numeric-string'],
stringArrayWrappersCount: 2,
stringArrayWrappersParametersMaxCount: 3,
stringArrayWrappersType: 'function',
stringArrayThreshold: 0.8,
transformObjectKeys: true,
log: true
//domainLock
}).getObfuscatedCode()
}
function doswap(b64: string) {
function swap(b64: string, c1: string, c2: string) { return b64.replaceAll(c1, '#').replaceAll(c2, c1).replaceAll('#', c2) }
b64 = swap(b64, '8', 'f')
b64 = swap(b64, 'W', '2')
b64 = swap(b64, 'M', 'C')
b64 = swap(b64, 'z', 'm')
b64 = swap(b64, 'a', 'S')
b64 = swap(b64, 'H', 'l')
b64 = swap(b64, 'e', 'Y')
return b64
}
// MARK: templating
function loadMainjs(coreObfuscatedB64swap: string) {
const file = fs.readFileSync('./src/main.js').toString()
return file.replace('{{TEXT}}', coreObfuscatedB64swap)
}
function loadDesign(script: string) {
const file = fs.readFileSync('./src/design.html').toString()
const split = file.split('{{TEXT}}')
return split[0] + script + split[1]
//return file.replace('{{TEXT}}', script)
}
// MARK: main
function main() {
if (fs.existsSync('./out')) {
fs.rmSync('./out', { recursive: true, force: true })
}
fs.mkdirSync('./out')
fs.mkdirSync('./out/debug')
console.log('Parsing keys')
const keysFile = parseKeysFile()
console.log('Parsing hints')
const hintsFile = parseHints()
const renames = [
["getFinalImage", "_0xc65ffb"],
...keysFile.names,
...hintsFile.names
]
console.log('Loading core.js')
const file = fs.readFileSync('./src/core.js').toString()
const scriptfile = keysFile.scriptfile + '\n' + hintsFile.scriptfile + '\n' + file
fs.writeFileSync('./out/debug/core.js', scriptfile)
console.log('Obfuscating core.js')
let coreObfuscated = obfuscateCore(scriptfile, [...renames.map(v => v[0])])
for (let name of renames) {
coreObfuscated = coreObfuscated.replace(`function ${name[0]}(`, `function ${name[1]}(`)
}
coreObfuscated += `function dear_osint_hater() { return "You made it so far! The end is almost here. Since you decided to destroy my hard work, you will not reach the final prize the normal way, so here you go: https://zomo.land/hosted/startrekctf.png. Good luck finding the flag!" }`
fs.writeFileSync('./out/debug/core.obfuscated', coreObfuscated)
console.log('Converting core.js to base64')
const coreObfuscatedB64 = btoa(coreObfuscated)
fs.writeFileSync('./out/debug/core.obfuscated.base64', coreObfuscatedB64)
console.log('Obfuscating core.js base64')
const coreObfuscatedB64swap = doswap(coreObfuscatedB64)
fs.writeFileSync('./out/debug/core.obfuscated.base64.obfuscated', coreObfuscatedB64swap)
console.log('Loading main.js')
const mainjs = loadMainjs(coreObfuscatedB64swap)
fs.writeFileSync('./out/debug/main.js', mainjs)
console.log('Creating nonobfuscated.html')
const mainhtml = loadDesign(mainjs)
fs.writeFileSync('./out/debug/nonobfuscated.html', mainhtml)
if (process.argv[2] === 'dev') {
console.log('Flag dev: skipping obfuscation')
return
}
console.log('Obfuscating main.js')
const mainjsObfuscated = obfuscateMain(mainjs)
fs.writeFileSync('./out/debug/main.obfuscated', mainjsObfuscated)
console.log('Creating file.html')
const mainhtmlObfuscated = loadDesign(mainjsObfuscated)
fs.writeFileSync('./out/debug/final.html', mainhtmlObfuscated)
fs.writeFileSync('./out/4LostInSpace.html', mainhtmlObfuscated)
}
main()

487
out/4LostInSpace.html Normal file

File diff suppressed because one or more lines are too long

66
out/debug/core.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

487
out/debug/final.html Normal file

File diff suppressed because one or more lines are too long

6
out/debug/flags Normal file
View File

@@ -0,0 +1,6 @@
hint1: 6Q2*1 # 12, _0x87cc7c
hint2: 01*121 # 23, _0xb6a36c
hint3partial1: **78 # 7, _0x279e46
hint3: 0*11*2178 # 43, _0x9c8bd3
hint4partial1: T*T0*112*1*78 # 43, _0x469c8f
flag: MAI*A*COR*D_T*T011*217*8 # 75, _0x823ebe

6
out/debug/hints Normal file
View File

@@ -0,0 +1,6 @@
hint1: [CHK] 6Q21 is an interesting code, but it isn't quite right.\nI believe the first number got stuck in our transmission matrix a little too long.\nMaybe if I remodulate the endianness and leave it in its dichotomous state, I can get closer.\nAccording to my notes, this part shouldn't have any letters. ; # 1639, _0xe37b3b
hint2: [CHK] 01121** ; ERROR: Improper Neutralization of Special Elements used in an OS Command # 73, _0xd43b
hint3partial1: You're missing a few numbers ; # 181, _0x96d801
hint3: [CHK] Final Hint\nMAIACORD_**0112178 ; # 248, _0x363c3c
hint4partial1: Enter the whole flag ; # 74, _0x7824e4
flag: Congrats! ; # 111, _0xedb404

145
out/debug/main.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

20
package.json Normal file
View File

@@ -0,0 +1,20 @@
{
"name": "startrekctf",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "node --max-old-space-size=32768 convert.js",
"watch": "node --watch-path=./src/core.js --watch-path=./src/main.js --watch-path=./src/design.html convert.js dev"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"javascript-obfuscator": "^4.1.1"
},
"dependencies": {
"@types/node": "^22.13.4",
"obfuscator-io-deobfuscator": "^1.0.4"
}
}

929
pnpm-lock.yaml generated Normal file
View File

@@ -0,0 +1,929 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
'@types/node':
specifier: ^22.13.4
version: 22.13.4
obfuscator-io-deobfuscator:
specifier: ^1.0.4
version: 1.0.4
devDependencies:
javascript-obfuscator:
specifier: ^4.1.1
version: 4.1.1
packages:
'@babel/code-frame@7.26.2':
resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==}
engines: {node: '>=6.9.0'}
'@babel/generator@7.26.9':
resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==}
engines: {node: '>=6.9.0'}
'@babel/helper-string-parser@7.25.9':
resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==}
engines: {node: '>=6.9.0'}
'@babel/helper-validator-identifier@7.25.9':
resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==}
engines: {node: '>=6.9.0'}
'@babel/parser@7.26.9':
resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==}
engines: {node: '>=6.0.0'}
hasBin: true
'@babel/template@7.26.9':
resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==}
engines: {node: '>=6.9.0'}
'@babel/traverse@7.26.9':
resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==}
engines: {node: '>=6.9.0'}
'@babel/types@7.26.9':
resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==}
engines: {node: '>=6.9.0'}
'@javascript-obfuscator/escodegen@2.3.0':
resolution: {integrity: sha512-QVXwMIKqYMl3KwtTirYIA6gOCiJ0ZDtptXqAv/8KWLG9uQU2fZqTVy7a/A5RvcoZhbDoFfveTxuGxJ5ibzQtkw==}
engines: {node: '>=6.0'}
'@javascript-obfuscator/estraverse@5.4.0':
resolution: {integrity: sha512-CZFX7UZVN9VopGbjTx4UXaXsi9ewoM1buL0kY7j1ftYdSs7p2spv9opxFjHlQ/QGTgh4UqufYqJJ0WKLml7b6w==}
engines: {node: '>=4.0'}
'@jridgewell/gen-mapping@0.3.8':
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
engines: {node: '>=6.0.0'}
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
'@jridgewell/set-array@1.2.1':
resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
engines: {node: '>=6.0.0'}
'@jridgewell/sourcemap-codec@1.5.0':
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
'@jridgewell/trace-mapping@0.3.25':
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
'@types/minimatch@3.0.5':
resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==}
'@types/node@20.17.19':
resolution: {integrity: sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==}
'@types/node@22.13.4':
resolution: {integrity: sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==}
'@types/validator@13.12.2':
resolution: {integrity: sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==}
acorn@8.8.2:
resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
engines: {node: '>=0.4.0'}
hasBin: true
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
array-differ@3.0.0:
resolution: {integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==}
engines: {node: '>=8'}
array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
arrify@2.0.1:
resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==}
engines: {node: '>=8'}
assert@2.0.0:
resolution: {integrity: sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==}
available-typed-arrays@1.0.7:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
call-bind-apply-helpers@1.0.2:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'}
call-bind@1.0.8:
resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
engines: {node: '>= 0.4'}
call-bound@1.0.3:
resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==}
engines: {node: '>= 0.4'}
chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
chance@1.1.9:
resolution: {integrity: sha512-TfxnA/DcZXRTA4OekA2zL9GH8qscbbl6X0ZqU4tXhGveVY/mXWvEQLt5GwZcYXTEyEFflVtj+pG8nc8EwSm1RQ==}
char-regex@1.0.2:
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
engines: {node: '>=10'}
charenc@0.0.2:
resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==}
class-validator@0.14.1:
resolution: {integrity: sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==}
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
commander@10.0.0:
resolution: {integrity: sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==}
engines: {node: '>=14'}
commander@12.1.0:
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
crypt@0.0.2:
resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==}
debug@4.4.0:
resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
define-data-property@1.1.4:
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
engines: {node: '>= 0.4'}
define-properties@1.2.1:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
engines: {node: '>= 0.4'}
dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
es-define-property@1.0.1:
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
engines: {node: '>= 0.4'}
es-errors@1.3.0:
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
engines: {node: '>= 0.4'}
es-object-atoms@1.1.1:
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
engines: {node: '>= 0.4'}
es6-object-assign@1.1.0:
resolution: {integrity: sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==}
eslint-scope@7.1.1:
resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
eslint-visitor-keys@3.3.0:
resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
esprima@4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'}
hasBin: true
esrecurse@4.3.0:
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
engines: {node: '>=4.0'}
estraverse@5.3.0:
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
engines: {node: '>=4.0'}
esutils@2.0.3:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
for-each@0.3.5:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
get-intrinsic@1.2.7:
resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==}
engines: {node: '>= 0.4'}
get-proto@1.0.1:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
globals@11.12.0:
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
engines: {node: '>=4'}
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
has-property-descriptors@1.0.2:
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
has-symbols@1.1.0:
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
engines: {node: '>= 0.4'}
has-tostringtag@1.0.2:
resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
engines: {node: '>= 0.4'}
hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
inversify@6.0.1:
resolution: {integrity: sha512-B3ex30927698TJENHR++8FfEaJGqoWOgI6ZY5Ht/nLUsFCwHn6akbwtnUAPCgUepAnTpe2qHxhDNjoKLyz6rgQ==}
is-arguments@1.2.0:
resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==}
engines: {node: '>= 0.4'}
is-buffer@1.1.6:
resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
is-callable@1.2.7:
resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
engines: {node: '>= 0.4'}
is-generator-function@1.1.0:
resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==}
engines: {node: '>= 0.4'}
is-nan@1.3.2:
resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==}
engines: {node: '>= 0.4'}
is-regex@1.2.1:
resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
engines: {node: '>= 0.4'}
is-typed-array@1.1.15:
resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
engines: {node: '>= 0.4'}
javascript-obfuscator@4.1.1:
resolution: {integrity: sha512-gt+KZpIIrrxXHEQGD8xZrL8mTRwRY0U76/xz/YX0gZdPrSqQhT/c7dYLASlLlecT3r+FxE7je/+C0oLnTDCx4A==}
engines: {node: '>=12.22.0'}
hasBin: true
js-string-escape@1.0.1:
resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==}
engines: {node: '>= 0.8'}
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
jsesc@3.1.0:
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
engines: {node: '>=6'}
hasBin: true
levn@0.3.0:
resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==}
engines: {node: '>= 0.8.0'}
libphonenumber-js@1.11.20:
resolution: {integrity: sha512-/ipwAMvtSZRdiQBHqW1qxqeYiBMzncOQLVA+62MWYr7N4m7Q2jqpJ0WgT7zlOEOpyLRSqrMXidbJpC0J77AaKA==}
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
md5@2.3.0:
resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==}
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
mkdirp@2.1.3:
resolution: {integrity: sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw==}
engines: {node: '>=10'}
hasBin: true
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
multimatch@5.0.0:
resolution: {integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==}
engines: {node: '>=10'}
obfuscator-io-deobfuscator@1.0.4:
resolution: {integrity: sha512-Msh0tzCgDSlh71ptjVfMY7rQo4takGGR9Trpw+gaAKr7NYeCz+/QfSn19rojQP3cNph2qPjlaiYY0WFcmpeXiw==}
hasBin: true
object-is@1.1.6:
resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==}
engines: {node: '>= 0.4'}
object-keys@1.1.1:
resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
engines: {node: '>= 0.4'}
opencollective-postinstall@2.0.3:
resolution: {integrity: sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==}
hasBin: true
optionator@0.8.3:
resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==}
engines: {node: '>= 0.8.0'}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
possible-typed-array-names@1.1.0:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
prelude-ls@1.1.2:
resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==}
engines: {node: '>= 0.8.0'}
process@0.11.10:
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
engines: {node: '>= 0.6.0'}
reflect-metadata@0.1.13:
resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==}
safe-regex-test@1.1.0:
resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
engines: {node: '>= 0.4'}
set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
source-map-support@0.5.21:
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
source-map@0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
string-template@1.0.0:
resolution: {integrity: sha512-SLqR3GBUXuoPP5MmYtD7ompvXiG87QjT6lzOszyXjTM86Uu7At7vNnt2xgyTLq5o9T4IxTYFyGxcULqpsmsfdg==}
stringz@2.1.0:
resolution: {integrity: sha512-KlywLT+MZ+v0IRepfMxRtnSvDCMc3nR1qqCs3m/qIbSOWkNZYT8XHQA31rS3TnKp0c5xjZu3M4GY/2aRKSi/6A==}
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
tslib@2.5.0:
resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
type-check@0.3.2:
resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==}
engines: {node: '>= 0.8.0'}
undici-types@6.19.8:
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
undici-types@6.20.0:
resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
util@0.12.5:
resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==}
validator@13.12.0:
resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==}
engines: {node: '>= 0.10'}
which-typed-array@1.1.18:
resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==}
engines: {node: '>= 0.4'}
word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
snapshots:
'@babel/code-frame@7.26.2':
dependencies:
'@babel/helper-validator-identifier': 7.25.9
js-tokens: 4.0.0
picocolors: 1.1.1
'@babel/generator@7.26.9':
dependencies:
'@babel/parser': 7.26.9
'@babel/types': 7.26.9
'@jridgewell/gen-mapping': 0.3.8
'@jridgewell/trace-mapping': 0.3.25
jsesc: 3.1.0
'@babel/helper-string-parser@7.25.9': {}
'@babel/helper-validator-identifier@7.25.9': {}
'@babel/parser@7.26.9':
dependencies:
'@babel/types': 7.26.9
'@babel/template@7.26.9':
dependencies:
'@babel/code-frame': 7.26.2
'@babel/parser': 7.26.9
'@babel/types': 7.26.9
'@babel/traverse@7.26.9':
dependencies:
'@babel/code-frame': 7.26.2
'@babel/generator': 7.26.9
'@babel/parser': 7.26.9
'@babel/template': 7.26.9
'@babel/types': 7.26.9
debug: 4.4.0
globals: 11.12.0
transitivePeerDependencies:
- supports-color
'@babel/types@7.26.9':
dependencies:
'@babel/helper-string-parser': 7.25.9
'@babel/helper-validator-identifier': 7.25.9
'@javascript-obfuscator/escodegen@2.3.0':
dependencies:
'@javascript-obfuscator/estraverse': 5.4.0
esprima: 4.0.1
esutils: 2.0.3
optionator: 0.8.3
optionalDependencies:
source-map: 0.6.1
'@javascript-obfuscator/estraverse@5.4.0': {}
'@jridgewell/gen-mapping@0.3.8':
dependencies:
'@jridgewell/set-array': 1.2.1
'@jridgewell/sourcemap-codec': 1.5.0
'@jridgewell/trace-mapping': 0.3.25
'@jridgewell/resolve-uri@3.1.2': {}
'@jridgewell/set-array@1.2.1': {}
'@jridgewell/sourcemap-codec@1.5.0': {}
'@jridgewell/trace-mapping@0.3.25':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
'@types/minimatch@3.0.5': {}
'@types/node@20.17.19':
dependencies:
undici-types: 6.19.8
'@types/node@22.13.4':
dependencies:
undici-types: 6.20.0
'@types/validator@13.12.2': {}
acorn@8.8.2: {}
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
array-differ@3.0.0: {}
array-union@2.1.0: {}
arrify@2.0.1: {}
assert@2.0.0:
dependencies:
es6-object-assign: 1.1.0
is-nan: 1.3.2
object-is: 1.1.6
util: 0.12.5
available-typed-arrays@1.0.7:
dependencies:
possible-typed-array-names: 1.1.0
balanced-match@1.0.2: {}
brace-expansion@1.1.11:
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
buffer-from@1.1.2: {}
call-bind-apply-helpers@1.0.2:
dependencies:
es-errors: 1.3.0
function-bind: 1.1.2
call-bind@1.0.8:
dependencies:
call-bind-apply-helpers: 1.0.2
es-define-property: 1.0.1
get-intrinsic: 1.2.7
set-function-length: 1.2.2
call-bound@1.0.3:
dependencies:
call-bind-apply-helpers: 1.0.2
get-intrinsic: 1.2.7
chalk@4.1.2:
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
chance@1.1.9: {}
char-regex@1.0.2: {}
charenc@0.0.2: {}
class-validator@0.14.1:
dependencies:
'@types/validator': 13.12.2
libphonenumber-js: 1.11.20
validator: 13.12.0
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
color-name@1.1.4: {}
commander@10.0.0: {}
commander@12.1.0: {}
concat-map@0.0.1: {}
crypt@0.0.2: {}
debug@4.4.0:
dependencies:
ms: 2.1.3
deep-is@0.1.4: {}
define-data-property@1.1.4:
dependencies:
es-define-property: 1.0.1
es-errors: 1.3.0
gopd: 1.2.0
define-properties@1.2.1:
dependencies:
define-data-property: 1.1.4
has-property-descriptors: 1.0.2
object-keys: 1.1.1
dunder-proto@1.0.1:
dependencies:
call-bind-apply-helpers: 1.0.2
es-errors: 1.3.0
gopd: 1.2.0
es-define-property@1.0.1: {}
es-errors@1.3.0: {}
es-object-atoms@1.1.1:
dependencies:
es-errors: 1.3.0
es6-object-assign@1.1.0: {}
eslint-scope@7.1.1:
dependencies:
esrecurse: 4.3.0
estraverse: 5.3.0
eslint-visitor-keys@3.3.0: {}
esprima@4.0.1: {}
esrecurse@4.3.0:
dependencies:
estraverse: 5.3.0
estraverse@5.3.0: {}
esutils@2.0.3: {}
fast-deep-equal@3.1.3: {}
fast-levenshtein@2.0.6: {}
for-each@0.3.5:
dependencies:
is-callable: 1.2.7
function-bind@1.1.2: {}
get-intrinsic@1.2.7:
dependencies:
call-bind-apply-helpers: 1.0.2
es-define-property: 1.0.1
es-errors: 1.3.0
es-object-atoms: 1.1.1
function-bind: 1.1.2
get-proto: 1.0.1
gopd: 1.2.0
has-symbols: 1.1.0
hasown: 2.0.2
math-intrinsics: 1.1.0
get-proto@1.0.1:
dependencies:
dunder-proto: 1.0.1
es-object-atoms: 1.1.1
globals@11.12.0: {}
gopd@1.2.0: {}
has-flag@4.0.0: {}
has-property-descriptors@1.0.2:
dependencies:
es-define-property: 1.0.1
has-symbols@1.1.0: {}
has-tostringtag@1.0.2:
dependencies:
has-symbols: 1.1.0
hasown@2.0.2:
dependencies:
function-bind: 1.1.2
inherits@2.0.4: {}
inversify@6.0.1: {}
is-arguments@1.2.0:
dependencies:
call-bound: 1.0.3
has-tostringtag: 1.0.2
is-buffer@1.1.6: {}
is-callable@1.2.7: {}
is-generator-function@1.1.0:
dependencies:
call-bound: 1.0.3
get-proto: 1.0.1
has-tostringtag: 1.0.2
safe-regex-test: 1.1.0
is-nan@1.3.2:
dependencies:
call-bind: 1.0.8
define-properties: 1.2.1
is-regex@1.2.1:
dependencies:
call-bound: 1.0.3
gopd: 1.2.0
has-tostringtag: 1.0.2
hasown: 2.0.2
is-typed-array@1.1.15:
dependencies:
which-typed-array: 1.1.18
javascript-obfuscator@4.1.1:
dependencies:
'@javascript-obfuscator/escodegen': 2.3.0
'@javascript-obfuscator/estraverse': 5.4.0
acorn: 8.8.2
assert: 2.0.0
chalk: 4.1.2
chance: 1.1.9
class-validator: 0.14.1
commander: 10.0.0
eslint-scope: 7.1.1
eslint-visitor-keys: 3.3.0
fast-deep-equal: 3.1.3
inversify: 6.0.1
js-string-escape: 1.0.1
md5: 2.3.0
mkdirp: 2.1.3
multimatch: 5.0.0
opencollective-postinstall: 2.0.3
process: 0.11.10
reflect-metadata: 0.1.13
source-map-support: 0.5.21
string-template: 1.0.0
stringz: 2.1.0
tslib: 2.5.0
js-string-escape@1.0.1: {}
js-tokens@4.0.0: {}
jsesc@3.1.0: {}
levn@0.3.0:
dependencies:
prelude-ls: 1.1.2
type-check: 0.3.2
libphonenumber-js@1.11.20: {}
math-intrinsics@1.1.0: {}
md5@2.3.0:
dependencies:
charenc: 0.0.2
crypt: 0.0.2
is-buffer: 1.1.6
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.11
mkdirp@2.1.3: {}
ms@2.1.3: {}
multimatch@5.0.0:
dependencies:
'@types/minimatch': 3.0.5
array-differ: 3.0.0
array-union: 2.1.0
arrify: 2.0.1
minimatch: 3.1.2
obfuscator-io-deobfuscator@1.0.4:
dependencies:
'@babel/generator': 7.26.9
'@babel/parser': 7.26.9
'@babel/traverse': 7.26.9
'@babel/types': 7.26.9
'@types/node': 20.17.19
commander: 12.1.0
transitivePeerDependencies:
- supports-color
object-is@1.1.6:
dependencies:
call-bind: 1.0.8
define-properties: 1.2.1
object-keys@1.1.1: {}
opencollective-postinstall@2.0.3: {}
optionator@0.8.3:
dependencies:
deep-is: 0.1.4
fast-levenshtein: 2.0.6
levn: 0.3.0
prelude-ls: 1.1.2
type-check: 0.3.2
word-wrap: 1.2.5
picocolors@1.1.1: {}
possible-typed-array-names@1.1.0: {}
prelude-ls@1.1.2: {}
process@0.11.10: {}
reflect-metadata@0.1.13: {}
safe-regex-test@1.1.0:
dependencies:
call-bound: 1.0.3
es-errors: 1.3.0
is-regex: 1.2.1
set-function-length@1.2.2:
dependencies:
define-data-property: 1.1.4
es-errors: 1.3.0
function-bind: 1.1.2
get-intrinsic: 1.2.7
gopd: 1.2.0
has-property-descriptors: 1.0.2
source-map-support@0.5.21:
dependencies:
buffer-from: 1.1.2
source-map: 0.6.1
source-map@0.6.1: {}
string-template@1.0.0: {}
stringz@2.1.0:
dependencies:
char-regex: 1.0.2
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
tslib@2.5.0: {}
type-check@0.3.2:
dependencies:
prelude-ls: 1.1.2
undici-types@6.19.8: {}
undici-types@6.20.0: {}
util@0.12.5:
dependencies:
inherits: 2.0.4
is-arguments: 1.2.0
is-generator-function: 1.1.0
is-typed-array: 1.1.15
which-typed-array: 1.1.18
validator@13.12.0: {}
which-typed-array@1.1.18:
dependencies:
available-typed-arrays: 1.0.7
call-bind: 1.0.8
call-bound: 1.0.3
for-each: 0.3.5
gopd: 1.2.0
has-tostringtag: 1.0.2
word-wrap@1.2.5: {}

28
src/core.js Normal file

File diff suppressed because one or more lines are too long

487
src/design.html Normal file
View File

@@ -0,0 +1,487 @@
<!DOCTYPE html>
<html>
<head>
<title>Star Trek CTF</title>
<link
href="https://fonts.googleapis.com/css2?family=Antonio:wght@400;700&display=swap"
rel="stylesheet"
/>
<style>
:root {
--color1: #cc99cc;
--color2: #9999ff;
--color3: #ff9900;
--color4: #ffcc99;
--color5: #cc6666;
}
body,
h1,
h2 {
margin: 0;
}
* {
font-family: Antonio;
}
body {
padding: 0.6em;
box-sizing: border-box;
background: black;
width: 100vw;
min-width: 1200px;
height: 100vh;
min-height: 700px;
display: flex;
flex-direction: column;
gap: 0.6em;
user-select: none;
color: var(--color3);
overflow: hidden;
}
h1 {
font-size: 3em;
}
h2 {
font-size: 1.5em;
}
#meta,
#data {
position: relative;
width: 100%;
}
#meta {
flex-grow: 1;
}
#data {
flex-grow: 2;
}
#accesshistory {
position: absolute;
top: 0;
left: 0;
margin: 0.5em;
color: var(--color3);
text-align: left;
font-size: 1em;
}
#accesshistorybody div::before {
content: '> ';
}
#accesshistorybody div {
user-select: text;
}
#accessalert {
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
color: var(--color5);
font-size: 2em;
margin-bottom: 0.5em;
}
#accesshint {
color: var(--color4);
font-size: 1em;
position: absolute;
top: 1em;
text-align: center;
}
#accessform {
position: absolute;
bottom: 1em;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.background {
width: 100%;
height: 100%;
display: grid;
gap: 0.6em;
overflow: hidden;
}
.foreground {
background: black;
overflow: hidden;
position: absolute;
}
#popup {
display: none;
}
#popup[visible] {
position: absolute;
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
animation: popup 0.2s cubic-bezier(0.64, 0.23, 0.58, 1.61)
forwards,
opacity 0.15s ease-in forwards;
}
#popup > div {
position: relative;
}
#popupclose {
position: absolute;
top: 0.5em;
right: 0.5em;
width: 2em;
height: 4em;
background: black;
display: flex;
align-items: center;
justify-content: center;
border-top-left-radius: 0.2em;
border-bottom-right-radius: 0.2em;
border-top-right-radius: 5em 1.5em;
border-bottom-left-radius: 5em 1.5em;
}
#popupclose svg {
height: 1em;
fill: var(--color3);
}
#meta .background {
grid-template-columns: 10fr 2fr 1fr 4fr;
grid-template-rows: 4fr 3fr;
border-bottom-left-radius: 160px 60px;
}
#meta .foreground {
border-bottom-left-radius: 100px 40px;
width: 90%;
height: 90%;
top: 0;
right: 0;
text-align: right;
}
#meta .background .one {
background: var(--color1);
grid-column: 1;
grid-row: 1;
}
#meta .background .two {
background: var(--color2);
grid-column: 1;
grid-row: 2;
}
#meta .background .three {
background: var(--color3);
grid-column: 2;
grid-row: 2;
}
#meta .background .four {
background: var(--color4);
grid-column: 3;
grid-row: 2;
}
#meta .background .five {
background: var(--color5);
grid-column: 4;
grid-row: 2;
}
#data .background {
grid-template-columns: 10fr 2fr 1fr 4fr;
grid-template-rows: 8fr 1fr 1fr 2fr 1fr 4fr;
border-top-left-radius: 160px 60px;
}
#data .foreground {
border-top-left-radius: 100px 40px;
width: 90%;
height: 90%;
bottom: 0;
right: 0;
display: flex;
justify-content: center;
}
#data .background .one {
background: var(--color3);
grid-column: 1;
grid-row: 6;
}
#data .background .two {
background: var(--color2);
grid-column: 1;
grid-row: 5;
}
#data .background .three {
background: var(--color4);
grid-column: 1;
grid-row: 4;
}
#data .background .four {
background: var(--color5);
grid-column: 1;
grid-row: 3;
}
#data .background .five {
background: var(--color5);
grid-column: 1;
grid-row: 2;
}
#data .background .six {
background: var(--color3);
grid-column: 1;
grid-row: 1;
}
#data .background .seven {
background: var(--color4);
grid-column: 2;
grid-row: 1;
}
#data .background .eight {
background: var(--color4);
grid-column: 3;
grid-row: 1;
}
#data .background .nine {
background: var(--color2);
grid-column: 4;
grid-row: 1;
}
#data .foreground .input {
display: flex;
align-items: center;
justify-content: center;
}
#data .foreground .input .left,
#data .foreground .input .right {
width: 60px;
height: 220px;
background: var(--color2);
position: relative;
}
#data .foreground .input .left::after,
#data .foreground .input .right::after {
content: '';
position: absolute;
top: 30px;
width: 45px;
height: 160px;
background: black;
}
#data .foreground .input .left {
border-top-left-radius: 30px 60px;
border-bottom-left-radius: 30px 60px;
}
#data .foreground .input .left::after {
right: 0;
border-top-left-radius: 20px 40px;
border-bottom-left-radius: 20px 40px;
}
#data .foreground .input .right {
border-top-right-radius: 30px 60px;
border-bottom-right-radius: 30px 60px;
}
#data .foreground .input .right::after {
left: 0;
border-top-right-radius: 20px 40px;
border-bottom-right-radius: 20px 40px;
}
#data .foreground .input input {
background: none;
text-transform: uppercase;
border: none;
outline: none;
text-align: center;
font-size: 5em;
color: var(--color3);
width: 900px;
}
#data .foreground .button {
background: var(--color3);
padding: 12px 28px;
border-radius: 20px / 40px;
text-align: center;
font-size: 40px;
color: black;
}
@keyframes popup {
from {
transform: scale(0.8);
}
to {
transform: scale(1);
}
}
@keyframes opacity {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>
<script>
{{TEXT}}
</script>
</head>
<body>
<div id="meta">
<div class="background">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
<div class="four"></div>
<div class="five"></div>
</div>
<div class="foreground">
<h1>THE LCARS COMPUTER NETWORK</h1>
<h2>AUTHORIZED ACCESS ONLY</h2>
<div id="accesshistory">
<div>ACCESS HISTORY</div>
<div id="accesshistorybody" clickable></div>
</div>
<h1 id="accessalert"></h1>
</div>
</div>
<div id="data">
<div class="background">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
<div class="four"></div>
<div class="five"></div>
<div class="six">
<!--
Stardate: 54973.4
To: Starfleet Command, United Federation of Planets
From: Captain Kathryn Janeway, USS Voyager (NCC-74656)
Subject: Anomalous Message Discovered in the Delta Quadrant
Dear Starfleet Command,
I am writing to report a highly unusual and perplexing discovery made by the crew of the USS Voyager during our ongoing
mission in the Delta Quadrant. While conducting routine scans of a derelict communication relay in a remote sector, we
intercepted an anomalous message that has thus far eluded all attempts at interpretation. The message is as follows:
"sdrow 5 gniniatnoc tnemgarf citehporp"
Despite extensive analysis by my senior staff, including Ensign Harry Kim and Seven of Nine, we have been unable to
decipher its meaning or determine its origin. The message does not correspond to any known language, encryption
protocol, or communication pattern in our databases. Its structure is irregular, and its purpose remains entirely
unclear.
Initial hypotheses suggest that the message could be encoded, fragmented, or written in a highly obscure or alien
linguistic format. However, without additional context or reference points, our efforts to decode it have reached an
impasse. The possibility that it is part of a larger transmission or a piece of a puzzle cannot be ruled out, but this
remains speculative at best. Our best hypothesis is that the code follows the form ?Q??, but we have no way to confirm this.
I am forwarding this message to Starfleet Command in the hope that your resources and expertise may yield insights that
we, isolated in the Delta Quadrant, are unable to achieve. It is possible that this transmission holds significance,
whether as a warning, a distress signal, or a piece of scientific or strategic information—but its true nature remains
shrouded in mystery.
I have ordered my crew to continue monitoring the area for additional signals or clues that may shed light on the
message's origin or purpose. Should we uncover further information, I will provide immediate updates.
In the meantime, I urge Starfleet to treat this matter with the seriousness it may warrant. While we cannot yet
determine the message's intent, its very existence raises questions about its source and potential implications.
I remain committed to the principles and ideals of the United Federation of Planets, even as we navigate the uncharted
and often enigmatic reaches of the Delta Quadrant.
Respectfully submitted,
Captain Kathryn Janeway
Commanding Officer, USS Voyager
End Transmission
-->
</div>
<div class="seven"></div>
<div class="eight"></div>
<div class="nine"></div>
</div>
<div class="foreground">
<div id="accesshint"></div>
<div id="accessform">
<label class="input">
<div class="left"></div>
<input id="accesscode" type="text" />
<div class="right"></div>
</label>
<div id="accessbutton" class="button" clickable>ACCESS</div>
</div>
</div>
</div>
<div id="popup">
<div>
<div id="popupclose">
<svg viewBox="0 0 460.775 460.775">
<path
d="M285.08,230.397L456.218,59.27c6.076-6.077,6.076-15.911,0-21.986L423.511,4.565c-2.913-2.911-6.866-4.55-10.992-4.55
c-4.127,0-8.08,1.639-10.993,4.55l-171.138,171.14L59.25,4.565c-2.913-2.911-6.866-4.55-10.993-4.55
c-4.126,0-8.08,1.639-10.992,4.55L4.558,37.284c-6.077,6.075-6.077,15.909,0,21.986l171.138,171.128L4.575,401.505
c-6.074,6.077-6.074,15.911,0,21.986l32.709,32.719c2.911,2.911,6.865,4.55,10.992,4.55c4.127,0,8.08-1.639,10.994-4.55
l171.117-171.12l171.118,171.12c2.913,2.911,6.866,4.55,10.993,4.55c4.128,0,8.081-1.639,10.992-4.55l32.709-32.719
c6.074-6.075,6.074-15.909,0-21.986L285.08,230.397z"
/>
</svg>
</div>
<img id="popupimg" />
</div>
</div>
</body>
</html>

6
src/flags Normal file
View File

@@ -0,0 +1,6 @@
hint1: 6Q2*1 # 12, _0x87cc7c
hint2: 01*121 # 23, _0xb6a36c
hint3partial1: **78 # 7, _0x279e46
hint3: 0*11*2178 # 43, _0x9c8bd3
hint4partial1: T*T0*112*1*78 # 43, _0x469c8f
flag: MAI*A*COR*D_T*T011*217*8 # 75, _0x823ebe

6
src/hints Normal file
View File

@@ -0,0 +1,6 @@
hint1: [CHK] 6Q21 is an interesting code, but it isn't quite right.\nI believe the first number got stuck in our transmission matrix a little too long.\nMaybe if I remodulate the endianness and leave it in its dichotomous state, I can get closer.\nAccording to my notes, this part shouldn't have any letters. ; # 1639, _0xe37b3b
hint2: [CHK] 01121** ; ERROR: Improper Neutralization of Special Elements used in an OS Command # 73, _0xd43b
hint3partial1: You're missing a few numbers ; # 181, _0x96d801
hint3: [CHK] Final Hint\nMAIACORD_**0112178 ; # 248, _0x363c3c
hint4partial1: Enter the whole flag ; # 74, _0x7824e4
flag: Congrats! ; # 111, _0xedb404

145
src/main.js Normal file
View File

@@ -0,0 +1,145 @@
function loadPayload() {
function swap(b64, c1, c2) { return b64.replaceAll(c1, '#').replaceAll(c2, c1).replaceAll('#', c2) }
// encoded flag.obfuscated.base64.obfuscated
let b64 = '{{TEXT}}'
b64 = swap(b64, '8', 'f')
b64 = swap(b64, 'W', '2')
b64 = swap(b64, 'M', 'C')
b64 = swap(b64, 'z', 'm')
b64 = swap(b64, 'a', 'S')
b64 = swap(b64, 'H', 'l')
b64 = swap(b64, 'e', 'Y')
return atob(b64)
}
function isClickable(elem) {
if (elem.tagName === 'HTML') {
return false
}
return elem.hasAttribute('clickable') || isClickable(elem.parentElement)
}
function doEval(str) {
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()(str)
}
addEventListener('load', () => {
const accesscode = document.getElementById('accesscode')
const accessbutton = document.getElementById('accessbutton')
const accesshistory = document.getElementById('accesshistorybody')
const accessalert = document.getElementById('accessalert')
const accesshint = document.getElementById('accesshint')
const popup = document.getElementById('popup')
const popupimg = document.getElementById('popupimg')
const popupclose = document.getElementById('popupclose')
const history = []
doEval(loadPayload())
// from flags
const check_hint1 = _0x87cc7c
const check_hint2 = _0xb6a36c
const check_hint3partial1 = _0x279e46
const check_hint3 = _0x9c8bd3
const check_hint4partial1 = _0x469c8f
const check_flag = _0x823ebe
const hint_hint1 = _0xe37b3b
const hint_hint2 = _0xd43b
const hint_hint3partial1 = _0x96d801
const hint_hint3 = _0x363c3c
const hint_hint4partial1 = _0x7824e4
const hint_flag = _0xedb404
const getFinalImage = _0xc65ffb
document.addEventListener('click', e => {
if (!isClickable(e.target)) {
accesscode.focus()
}
})
function getHint(hintFn) {
const data = hintFn()
const str = atob(data)
const hint = JSON.parse(str)
return hint
}
function doHint(code, hintFn) {
const hint = getHint(hintFn)
accesshint.innerText = hint[0]
accessalert.innerText = hint[1]
if (!history.includes(code)) {
history.push(code)
}
accesshistory.innerHTML = ''
for (let h of history) {
const div = document.createElement('div')
div.innerText = h
accesshistory.appendChild(div)
}
}
function doHintPartial(code, hintBaseFn, hintPartialFn) {
const hintBase = getHint(hintBaseFn)
const hintPartial = getHint(hintPartialFn)
accesshint.innerText = hintBase[0] + '\n' + hintPartial[0]
accessalert.innerText = hintBase[1] + '\n' + hintPartial[1]
if (!history.includes(code)) {
history.push(code)
}
accesshistory.innerHTML = ''
for (let h of history) {
const div = document.createElement('div')
div.innerText = h
accesshistory.appendChild(div)
}
}
let state = 0
// Define the function to be called on click
function submit() {
const code = accesscode.value.toUpperCase()
if (check_hint1(code)) {
state = 1
doHint(code, hint_hint1)
} else if (check_hint2(code)) {
state = 2
doHint(code, hint_hint2)
} else if (state == 2 && check_hint3partial1(code)) {
doHintPartial(code, hint_hint2, hint_hint3partial1)
} else if (check_hint3(code)) {
state = 3
doHint(code, hint_hint3)
} else if (state == 3 && check_hint4partial1(code)) {
doHintPartial(code, hint_hint3, hint_hint4partial1)
} else if (check_flag(code)) {
state = 4
doHint(code, hint_flag)
accesscode.blur()
popupimg.setAttribute('src', getFinalImage())
popup.setAttribute('visible', '')
outer.appendChild(div)
document.body.appendChild(outer)
} else {
alert('incorrect')
// incorrect
}
}
accesscode.addEventListener('keypress', e => e.key === 'Enter' && submit());
accessbutton.addEventListener('click', submit);
popupclose.addEventListener('click', () => {
popup.removeAttribute('visible')
})
})

BIN
startrekctf.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

11
tsconfig.json Normal file
View File

@@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "esnext",
"lib": ["ES2021"],
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}