diff --git a/README.md b/README.md index 1c2088f..535cb78 100644 --- a/README.md +++ b/README.md @@ -45,13 +45,13 @@ Learn more about the [availible scripts](#scripts) bellow or pass the `--help` f ### [connect.js](./scripts/connect.js) **RAM:** 1.85 GB -Connect to a device on a different network. +Search the network for a device and connect to it. ``` [home ~/]> run /scripts/connect.js --help Running script with 1 thread(s), pid 1 and args: ["--help"]. /scripts/connect.js: -Connect to a device on a different network. +Search the network for a device and connect to it. Usage: run connect.js DEVICE run connect.js --help @@ -86,15 +86,15 @@ Options: ``` ### [crawler.js](./scripts/crawler.js) -**RAM:** 4.05 GB +**RAM:** 4.10 GB -Search the network for targets to execute a script against. +Search the network for devices to execute a script against. ``` [home ~/]> run scripts/crawler.js --help Running script with 1 thread(s), pid 1 and args: ["--help"]. /scripts/crawler.js: -Search the network for targets to execute a script against. +Search the network for devices to execute a script against. Usage: run crawler.js [OPTIONS] SCRIPT [ARGS]... run crawler.js --help @@ -107,6 +107,7 @@ Options: -d --depth Depth to scan to, defaults to 3 -l --level Exclude targets with higher hack level, defaults to current hack level -p --ports Exclute targets with too many closed ports + -s --silent Surpress program output -h --help Display this help message ``` @@ -128,19 +129,20 @@ Usage: run hacknet-manager.js [OPTIONS] [LIMIT] Options: -b --balance Prevent spending bellow point + -s --sleep Amount of time to wait between purchases, defaults to 1 (second) -h --help Display this help message ``` ### [miner.js](./scripts/miner.js) **RAM:** 2.45 GB -Weaken, Grow, Hack loop to "mine" machine for money. +Weaken, Grow, Hack loop to "mine" device for money. Tail for live updates. ``` [home ~/]> run scripts/miner.js --help Running script with 1 thread(s), pid 1 and args: ["--help"]. /scripts/miner.js: -Weaken, Grow, Hack loop to "mine" machine for money. +Weaken, Grow, Hack loop to "mine" device for money. Tail for live updates. Usage: run miner.js [DEVICE] run miner.js --help @@ -205,6 +207,7 @@ Usage: run rootkit.js [OPTIONS] [DEVICE] [SCRIPT] [ARGS]... Options: -c --cpu Number of CPU threads to use with script + -s --silent Surpress program output -h --help Display this help message ``` diff --git a/scripts/copy.js b/scripts/copy.js index b4a197d..0f5a8ef 100644 --- a/scripts/copy.js +++ b/scripts/copy.js @@ -1,5 +1,5 @@ import {ArgError, ArgParser} from '/scripts/lib/arg-parser'; -import {copyWithDependencies, percentageBar} from '/scripts/lib/utils'; +import {copyWithDependencies, progressBar} from '/scripts/lib/utils'; /** * BitBurner autocomplete @@ -18,7 +18,7 @@ export async function main(ns) { {name: 'file', desc: 'File to copy', type: 'string'}, {name: 'device', desc: 'Device to copy file(s) to', type: 'string'}, {name: 'noDeps', desc: 'Skip copying dependencies', flags: ['-d', '--no-deps'], type: 'bool'}, - {name: 'silent', desc: 'Surpress program output', flags: ['-s', '--silent'], type: 'bool'} + {name: 'silent', desc: 'Suppress program output', flags: ['-s', '--silent'], type: 'bool'} ], true); try { @@ -38,12 +38,12 @@ export async function main(ns) { // Copy files & create download bar if(args['noDeps']) { await ns.scp(args['file'], args['device']); - if(!args['silent']) await percentageBar(ns, args['file']); + if(!args['silent']) await progressBar(ns, args['file']); } else { const files = await copyWithDependencies(ns, args['file'], args['device']); if(!args['silent']) { for(let file of files) { - await percentageBar(ns, file, 1); + await progressBar(ns, file); } } } diff --git a/scripts/crawler.js b/scripts/crawler.js index 15b40a8..b5f81d3 100644 --- a/scripts/crawler.js +++ b/scripts/crawler.js @@ -24,7 +24,7 @@ export async function main(ns) { {name: 'depth', desc: 'Depth to scan to, defaults to 3', flags: ['-d', '--depth'], default: Infinity, type: 'num'}, {name: 'level', desc: 'Exclude targets with higher hack level, defaults to current hack level', flags: ['-l', '--level'], default: ns.getHackingLevel(), type: 'num'}, {name: 'ports', desc: 'Exclute targets with too many closed ports', flags: ['-p', '--ports'], default: Infinity, type: 'num'}, - {name: 'silent', desc: 'Surpress program output', flags: ['-s', '--silent'], type: 'bool'} + {name: 'silent', desc: 'Suppress program output', flags: ['-s', '--silent'], type: 'bool'} ], true); try { diff --git a/scripts/lib/utils.js b/scripts/lib/utils.js index aafb078..98d35e0 100644 --- a/scripts/lib/utils.js +++ b/scripts/lib/utils.js @@ -23,17 +23,15 @@ export async function copyWithDependencies(ns, src, device) { } /** - * Display a percentage bar in the terminal which updates in real time. - * - * **Example:** - * - * `/script/test.js [||||||||||----------] 50% (24.2 MB/s)` + * Display a progress bar in the terminal which updates in real time. + * **Example:** `/script/test.js [||||||||||----------] 50% (24.2 MB/s)` * * @param ns {NS} - BitBurner API * @param name {string} - Name to display at the begging of bar + * @param showSpeed {boolean} - Show the speed in the progress bar * @param time {number} - Time it takes for bar to fill */ -export async function percentageBar(ns, name, time = 1) { +export async function progressBar(ns, name, showSpeed = true, time = Math.random() + 0.5) { const text = (percentage, speed) => { const p = percentage > 1 ? 1 : percentage < 0 ? 0 : percentage; const spacer = Array(30 - name.length).fill(' ').join(''); @@ -52,7 +50,7 @@ export async function percentageBar(ns, name, time = 1) { for(let p = 0; p <= 100; p++) { await ns.sleep((time * 1000) / 100); if(p % 5 == 0) speed = Math.round((speed + (Math.random() > 0.5 ? 1 : -1) * Math.random()) * 10) / 10; - updateLine.innerText = `${script}: ${text(p / 100, p == 0 ? 0 : speed)}`; + updateLine.innerText = `${script}: ${text(p / 100, showSpeed ? p == 0 ? 0 : speed : null)}`; } return; } diff --git a/scripts/miner.js b/scripts/miner.js index c41f775..781807d 100644 --- a/scripts/miner.js +++ b/scripts/miner.js @@ -17,7 +17,7 @@ export function autocomplete(data) { export async function main(ns) { // Setup ns.disableLog('ALL'); - const argParser = new ArgParser('miner.js', 'Weaken, Grow, Hack loop to "mine" machine for money. Tail for live updates', null, [ + const argParser = new ArgParser('miner.js', 'Weaken, Grow, Hack loop to "mine" device for money. Tail for live updates.', null, [ {name: 'device', desc: 'Device to mine, defaults to current machine', optional: true, default: ns.getHostname(), type: 'string'} ]); diff --git a/scripts/rootkit.js b/scripts/rootkit.js index c45663d..e5e04a5 100644 --- a/scripts/rootkit.js +++ b/scripts/rootkit.js @@ -1,5 +1,14 @@ -import {ArgError, ArgParser} from './scripts/lib/arg-parser'; -import {downloadPrint, slowPrint} from './scripts/lib/utils'; +import {ArgError, ArgParser} from '/scripts/lib/arg-parser'; +import {copyWithDependencies, progressBar, slowPrint} from '/scripts/lib/utils'; + +/** + * BitBurner autocomplete + * @param data {server: string[], txts: string[], scripts: string[], flags: string[]} - Contextual information + * @returns {string[]} - Pool of autocomplete options + */ +export function autocomplete(data) { + return [...data.servers, ...data.scripts]; +} /** * Pwn a target server with availible tools. Additionally can copy & execute a script after pwning. @@ -11,89 +20,86 @@ export async function main(ns) { const argParser = new ArgParser('rootkit.js', 'Automatically gain root access to a device. A file can also be uploaded & executed.', null, [ {name: 'device', desc: 'Device to root, defaults to current machine', optional: true, default: ns.getHostname(), type: 'string'}, {name: 'script', desc: 'Script to copy & execute', optional: true, type: 'string'}, - {name: 'args', desc: 'Arguments for script. Forward the current target with: {{TARGET}}', optional: true, extras: true, type: 'string'}, + {name: 'args', desc: 'Arguments for script. Forward the current target with: {{TARGET}}', optional: true, extras: true, type: 'string'}, {name: 'cpu', desc: 'Number of CPU threads to use with script', flags: ['-c', '--cpu'], type: 'num'}, + {name: 'silent', desc: 'Surpress program output', flags: ['-s', '--silent'], type: 'bool'} ], true); - let args; + try { - args = argParser.parse(ns.args); + const args = argParser.parse(ns.args); if(args['script'] && !args['cpu']) args['cpu'] = ~~(ns.getServerMaxRam(args['device']) / ns.getScriptRam(args['script'], 'home')) || 1; + + // Banner + if(!args['silent']) { + ns.tprint('==================================================='); + ns.tprint(`Rooting: ${args['device']}`); + ns.tprint('==================================================='); + } + + let spacer = false; + const sleep = 750; + try { + // Run exploits + ns.brutessh(args['device']); + if(!args['silent']) { + await slowPrint(ns, `Attacking over SSH (${args['device']}:22)...`, 0.5, 1.5); + await ns.sleep(sleep); + spacer = true; + } + ns.ftpcrack(args['device']); + if(!args['silent']) { + await slowPrint(ns, `Attacking over FTP (${args['device']}:24)...`, 0.5, 1.5); + await ns.sleep(sleep); + } + ns.relaysmtp(args['device']); + if(!args['silent']) { + await slowPrint(ns, `Attacking over SMTP (${args['device']}:25)...`, 0.5, 1.5); + await ns.sleep(sleep); + } + } catch { + } finally { + try { + // Attempt root + if(spacer) ns.tprint(''); + ns.nuke(args['device']) + if(!args['silent']) { + ns.tprint(`Root: Success!`); + ns.tprint(''); + } + } catch { + if(!args['silent']) { + ns.tprint(`Root: Failed`); + ns.tprint(''); + } + ns.exit(); + } + } + + if(args['script']) { + // Detect script dependencies & copy everything to target + const files = await copyWithDependencies(ns, args['script'], args['device']); + if(!args['silent']) { + await ns.sleep(500); + ns.tprint('Copying files:'); + for(let file of files) await progressBar(ns, file); + } + + // Run script + if(!args['silent']) { + ns.tprint(''); + ns.tprint(`Executing with ${args['cpu']} thread${args['cpu'] > 1 ? 's' : ''}...`); + await ns.sleep(500); + } + ns.scriptKill(args['script'], args['device']); + const pid = ns.exec(args['script'], args['device'], args['cpu'], ...args['args'] + .map(a => a == '{{TARGET}}' ? args['device'] : a)); + if(!args['silent']) { + ns.tprint(!!pid ? 'Done!' : 'Failed to start'); + ns.tprint(''); + } + } } catch(err) { if(err instanceof ArgError) return ns.tprint(argParser.help(err.message)); throw err; } - - /** - * Detect import statements inside script & build a dependency tree. - * @params file {string} - Path to file to search - * @returns {string[]} - Array of required files - */ - async function dependencyFinder(file) { - const queue = [file], found = []; - while(queue.length) { - const imports = new RegExp(/from ["']\.(.+)["']/g); - const script = await ns.read(queue.splice(0, 1)[0]); - let match; - while((match = imports.exec(script)) != null) { - const path = `${match[1]}.js`; - queue.push(path); - found.push(path); - } - } - return found; - } - - // Banner - ns.tprint('==================================================='); - ns.tprint(`Rooting: ${args['device']}`); - await slowPrint(ns, '==================================================='); - - let spacer = false; - try { - // Run exploits - ns.brutessh(args['device']); - await slowPrint(ns, `Attacking over SSH (${args['device']}:22)...`, 1, 2); - spacer = true; - ns.ftpcrack(args['device']); - await slowPrint(ns, `Attacking over FTP (${args['device']}:24)...`, 1, 2); - ns.relaysmtp(args['device']); - await slowPrint(ns, `Attacking over SMTP (${args['device']}:25)...`, 1, 2); - } catch { - } finally { - try { - // Attempt root - if(spacer) ns.tprint(''); - ns.nuke(args['device']) - ns.tprint(`Root: Success!`); - ns.tprint(''); - } catch { - ns.tprint(`Root: Failed`); - ns.tprint(''); - ns.exit(); - } - } - - if(args['script']) { - // Detect script dependencies & copy everything to target - await ns.sleep(0.5); - await slowPrint(ns, 'Copying files:'); - const deps = [...(await dependencyFinder(args['script'])), args['script']]; - for(let dep of deps) { - await ns.scp(dep, args['device']); - await downloadPrint(ns, dep); - } - - // Run script - ns.tprint(''); - await slowPrint(ns, `Executing with ${args['cpu']} thread${args['cpu'] > 1 ? 's' : ''}...`); - ns.scriptKill(args['script'], args['device']); - const pid = ns.exec(args['script'], args['device'], args['cpu'], ...args['args'] - .map(a => a == '{{TARGET}}' ? args['device'] : a)); - ns.tprint(!!pid ? 'Done!' : 'Failed to start'); - ns.tprint(''); - } -} - -export function autocomplete(data) { - return [...data.servers, ...data.scripts]; }