From efd3d28bcea7463c04615d4fac206968513de748 Mon Sep 17 00:00:00 2001 From: ztimson Date: Sat, 2 Apr 2022 12:14:24 -0400 Subject: [PATCH] Added server-manager & did some small updates to botnet-manger --- README.md | 48 ++++++++++++++++++++++++--- scripts/botnet-manager.js | 14 ++++---- scripts/lib/arg-parser2.js | 10 +++--- scripts/server-manager.js | 67 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 scripts/server-manager.js diff --git a/README.md b/README.md index 27a19d3..400c347 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ These scripts are for playing the [open source](https://github.com/danielyxie/bi - [miner.js](#minerjs) - [network-graph.js](#network-graphjs) - [rootkit.js](#rootkitjs) + - [server-manager.js](#server-managerjs) - [update.js](#updatejs) ## Quick Start @@ -49,7 +50,7 @@ Learn more about the [availible scripts](#scripts) bellow or pass the `--help` f ## Scripts ### [botnet-manager.js (WIP)](./scripts/botnet-manager.js) -**RAM:** ?.?? GB +**RAM:** 7.15 GB Connect & manage a network of devices to launch distributed attacks. ``` @@ -57,6 +58,23 @@ Connect & manage a network of devices to launch distributed attacks. Running script with 1 thread(s), pid 1 and args: ["--help"]. /scripts/botnet-manager.js: +Connect & manage a network of devices to launch distributed attacks. + +Usage: run botnet-manager.js [OPTIONS] + run botnet-manager.js [OPTIONS] COMMAND + run botnet-manager.js --help [COMMAND] + +Options: + -s, --silent Suppress program output + -h, --help Display this help message + +Commands: + copy Copy file & dependencies to swarm nodes + join Connect device as a worker node to the swarm + kill Kill any scripts running on worker nodes + leave Disconnect worker node from swarm + run Copy & run script on all worker nodes + start Start this device as the swarm manager ``` ### [connect.js](./scripts/connect.js) @@ -230,11 +248,11 @@ Options: ``` ### [rootkit.js](./scripts/rootkit.js) -**RAM:** 4.80 GB - 4.95 GB (depending on un-commented programs) - -Automatically gain root on a target machine. A file can also be uploaded & executed. +**RAM:** 5.05 GB (Can be reduced to 4.80 GB) Programs can be commented out to lower the cost of running. + +Automatically gain root on a target machine. A file can also be uploaded & executed. ``` [home ~/]> run scripts/rootkit.js --help Running script with 1 thread(s), pid 1 and args: ["--help"]. @@ -255,6 +273,28 @@ Options: -h --help Display this help message ``` +### [server-manager.js](./scripts/server-manager.js) +**RAM:** 9.35 GB + +Automate the buying & upgrading of servers. +``` +[home ~/]> run /scripts/server-manager.js --help +Running script with 1 thread(s), pid 1 and args: ["--help"]. +/scripts/server-manager.js: + +Automate the buying & upgrading of servers. + +Usage: run server-manager.js [OPTIONS] + run server-manager.js --help + +Options: + -b, --balance Prevent spending bellow point + -l, --limit Limit the number of servers that can be purchased, defaults to 25 + -r, --ram Amount of RAM to purchase new servers with, defaults to 8 GB + -s, --sleep Amount of time to wait between purchases, defaults to 1 (second) + -h, --help Display this help message +``` + ### [update.js](./scripts/update.js) **RAM:** 2.65 GB diff --git a/scripts/botnet-manager.js b/scripts/botnet-manager.js index 5c2a6fa..bfde787 100644 --- a/scripts/botnet-manager.js +++ b/scripts/botnet-manager.js @@ -125,25 +125,25 @@ export async function main(ns) { // Setup ns.disableLog('ALL'); const hostname = ns.getHostname(), portNum = 1; - const argParser = new ArgParser('botnet-manager.js', 'Connect & manage a network of devices to launch distributed attacks.', [ - new ArgParser('copy', 'Copy file & dependencies to swarm nodes', [ + const argParser = new ArgParser(ns, 'botnet-manager.js', 'Connect & manage a network of devices to launch distributed attacks.', [ + new ArgParser(ns, 'copy', 'Copy file & dependencies to swarm nodes', [ {name: 'file', desc: 'File to copy', default: false}, {name: 'manager', desc: 'Copy to manager node', flags: ['-m', '--manager'], default: false}, {name: 'noDeps', desc: 'Skip copying dependencies', flags: ['-d', '--no-deps'], default: false}, {name: 'workers', desc: 'Copy to worker nodes', flags: ['-w', '--workers'], default: false}, ]), - new ArgParser('join', 'Connect device as a worker node to the swarm', [ + new ArgParser(ns, 'join', 'Connect device as a worker node to the swarm', [ {name: 'device', desc: 'Device to connect, defaults to the current machine', optional: true, default: hostname} ]), - new ArgParser('kill', 'Kill any scripts running on worker nodes'), - new ArgParser('leave', 'Disconnect worker node from swarm', [ + new ArgParser(ns, 'kill', 'Kill any scripts running on worker nodes'), + new ArgParser(ns, 'leave', 'Disconnect worker node from swarm', [ {name: 'device', desc: 'Device to disconnect, defaults to the current machine', optional: true, default: hostname} ]), - new ArgParser('run', 'Copy & run script on all worker nodes', [ + new ArgParser(ns, 'run', 'Copy & run script on all worker nodes', [ {name: 'script', desc: 'Script to copy & execute', type: 'string'}, {name: 'args', desc: 'Arguments for script. Forward the current target with: {{TARGET}}', optional: true, extras: true}, ]), - new ArgParser('start', 'Start this device as the swarm manager'), + new ArgParser(ns, 'start', 'Start this device as the swarm manager'), {name: 'silent', desc: 'Suppress program output', flags: ['-s', '--silent'], default: false}, ]); const args = argParser.parse(ns.args); diff --git a/scripts/lib/arg-parser2.js b/scripts/lib/arg-parser2.js index 854800d..a6dfaca 100644 --- a/scripts/lib/arg-parser2.js +++ b/scripts/lib/arg-parser2.js @@ -8,7 +8,8 @@ export class ArgParser { * @param argList {(ArgParser || {name: string, desc: string, flags: string[], optional: boolean, default: boolean})[]} - Array of CLI arguments * @param examples {string[]} - Additional examples to display */ - constructor(name, desc, argList = [], examples = []) { + constructor(ns, name, desc, argList = [], examples = []) { + this.ns = ns; this.name = name; this.desc = desc; @@ -27,13 +28,12 @@ export class ArgParser { `--help ${this.commands.length ? '[COMMAND]' : ''}` ].filter(e => !!e); } - /** * Parse an array into an arguments dictionary using the configuration. * @param args {string[]} - Array of arguments to be parsed * @returns {object} - Dictionary of arguments with defaults applied */ - parse(args) { + parse(args = this.ns.args) { // Parse arguments let extras = [], parsed = {...this.defaults}, queue = [...args]; while(queue.length) { @@ -51,7 +51,7 @@ export class ArgParser { extras.push(arg); continue; } - const value = argDef.default === false ? true : argDef.default === true ? false : argDef.default || queue.splice(queue.findIndex(q => q[0] != '-'), 1)[0]; + const value = argDef.default === false ? true : argDef.default === true ? false : queue.splice(queue.findIndex(q => q[0] != '-'), 1)[0] || argDef.default; if(value == null) parsed['_error'] = `Option missing value: ${arg.name}`; parsed[argDef.name] = value; } else { // Command @@ -114,6 +114,6 @@ export class ArgParser { if(this.commands.length) msg += '\n\nCommands:\n\t' + this.commands .map(command => `${command.name}${spacer(command.name)}${command.desc}`) .join('\n\t'); - return `${msg}\n\n`; + this.ns.tprint(`${msg}\n\n`); } } diff --git a/scripts/server-manager.js b/scripts/server-manager.js new file mode 100644 index 0000000..7b0f50a --- /dev/null +++ b/scripts/server-manager.js @@ -0,0 +1,67 @@ +import {ArgParser} from '/scripts/lib/arg-parser2'; +import {Logger} from '/scripts/lib/logger'; + +/** + * Automate the buying & upgrading of servers. + * @param ns {NS} - BitBurner API + */ +export async function main(ns) { + // Setup + ns.disableLog('ALL'); + let servers = ns.getPurchasedServers(); + const logger = new Logger(ns, [ + () => `Server Manager: ${servers.length}` + ]); + const argParser = new ArgParser(ns, 'server-manager.js', 'Automate the buying & upgrading of servers.', [ + {name: 'balance', desc: 'Prevent spending bellow point', flags: ['-b', '--balance'], default: 0}, + {name: 'limit', desc: 'Limit the number of servers that can be purchased, defaults to 25', flags: ['-l', '--limit'], default: 25}, + {name: 'ram', desc: 'Amount of RAM to purchase new servers with, defaults to 8 GB', flags: ['-r', '--ram'], default: 8}, + {name: 'sleep', desc: 'Amount of time to wait between purchases, defaults to 1 (second)', flags: ['-s', '--sleep'], default: 1} + ]); + const args = argParser.parse(); + const serverPrefix = 'botnet_' + const maxRam = ns.getPurchasedServerMaxRam(); + const minRamCost = ns.getPurchasedServerCost(args['ram']); + + // Help + if(args['help'] || args['_error']) + return argParser.help(args['help'] ? null : args['_error'], args['_command']); + + // Run + while(true) { + servers = ns.getPurchasedServers(); + const balance = ns.getServerMoneyAvailable('home'); + let targ + // Purchase new server if we can afford it + if(servers.length < args['limit'] && balance - minRamCost > args['balance']) { + logger.log(`Buying server (${args['ram']} GB): ${minRamCost.toLocaleString('en-US', {style: 'currency', currency: 'USD'})}`); + ns.purchaseServer(`${serverPrefix}${servers.length}`, args['ram']); + } else { // Check for upgrades + const upgrades = servers.map(server => { + // Calculate next RAM upgrades (must be a power of two: 2, 4, 8, 16, 32...) + let ram = Math.pow(2, Math.log2(ns.getServerRam(server)[0]) + 1); + if(ram > maxRam) ram = null; + return { + server, + ram, + cost: ram ? ns.getPurchasedServerCost(ram) : null + } + }); + upgrades.sort((a, b) => { // Sort by price + if(a.cost < b.cost) return 1; + if(a.cost < b.cost) return -1; + return 0; + }); + + // Do the cheapest upgrade if we can afford it + const upgrade = upgrades[0]; + if(upgrade && !!upgrade.ram && balance - upgrade.cost > args['balance']) { + logger.log(`Upgrading ${upgrade.server}: ${upgrade.ram} GB/${upgrade.cost.toLocaleString('en-US', {style: 'currency', currency: 'USD'})}`); + ns.killall(upgrade.server); + ns.deleteServer(upgrade.server); + ns.purchaseServer(upgrade.server, upgrade.ram); + } + } + await ns.sleep(args['sleep'] * 1000); + } +}