Added server-manager & did some small updates to botnet-manger

This commit is contained in:
Zakary Timson 2022-04-02 12:14:24 -04:00
parent f628a5f1d0
commit efd3d28bce
4 changed files with 123 additions and 16 deletions

View File

@ -15,6 +15,7 @@ These scripts are for playing the [open source](https://github.com/danielyxie/bi
- [miner.js](#minerjs) - [miner.js](#minerjs)
- [network-graph.js](#network-graphjs) - [network-graph.js](#network-graphjs)
- [rootkit.js](#rootkitjs) - [rootkit.js](#rootkitjs)
- [server-manager.js](#server-managerjs)
- [update.js](#updatejs) - [update.js](#updatejs)
## Quick Start ## Quick Start
@ -49,7 +50,7 @@ Learn more about the [availible scripts](#scripts) bellow or pass the `--help` f
## Scripts ## Scripts
### [botnet-manager.js (WIP)](./scripts/botnet-manager.js) ### [botnet-manager.js (WIP)](./scripts/botnet-manager.js)
**RAM:** ?.?? GB **RAM:** 7.15 GB
Connect & manage a network of devices to launch distributed attacks. 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"]. Running script with 1 thread(s), pid 1 and args: ["--help"].
/scripts/botnet-manager.js: /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) ### [connect.js](./scripts/connect.js)
@ -230,11 +248,11 @@ Options:
``` ```
### [rootkit.js](./scripts/rootkit.js) ### [rootkit.js](./scripts/rootkit.js)
**RAM:** 4.80 GB - 4.95 GB <small>(depending on un-commented programs)</small> **RAM:** 5.05 GB <small>(Can be reduced to 4.80 GB)</small>
Automatically gain root on a target machine. A file can also be uploaded & executed.
Programs can be commented out to lower the cost of running. 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 [home ~/]> run scripts/rootkit.js --help
Running script with 1 thread(s), pid 1 and args: ["--help"]. Running script with 1 thread(s), pid 1 and args: ["--help"].
@ -255,6 +273,28 @@ Options:
-h --help Display this help message -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) ### [update.js](./scripts/update.js)
**RAM:** 2.65 GB **RAM:** 2.65 GB

View File

@ -125,25 +125,25 @@ export async function main(ns) {
// Setup // Setup
ns.disableLog('ALL'); ns.disableLog('ALL');
const hostname = ns.getHostname(), portNum = 1; const hostname = ns.getHostname(), portNum = 1;
const argParser = new ArgParser('botnet-manager.js', 'Connect & manage a network of devices to launch distributed attacks.', [ const argParser = new ArgParser(ns, 'botnet-manager.js', 'Connect & manage a network of devices to launch distributed attacks.', [
new ArgParser('copy', 'Copy file & dependencies to swarm nodes', [ new ArgParser(ns, 'copy', 'Copy file & dependencies to swarm nodes', [
{name: 'file', desc: 'File to copy', default: false}, {name: 'file', desc: 'File to copy', default: false},
{name: 'manager', desc: 'Copy to manager node', flags: ['-m', '--manager'], 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: 'noDeps', desc: 'Skip copying dependencies', flags: ['-d', '--no-deps'], default: false},
{name: 'workers', desc: 'Copy to worker nodes', flags: ['-w', '--workers'], 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} {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(ns, 'kill', 'Kill any scripts running on worker nodes'),
new ArgParser('leave', 'Disconnect worker node from swarm', [ new ArgParser(ns, 'leave', 'Disconnect worker node from swarm', [
{name: 'device', desc: 'Device to disconnect, defaults to the current machine', optional: true, default: hostname} {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: 'script', desc: 'Script to copy & execute', type: 'string'},
{name: 'args', desc: 'Arguments for script. Forward the current target with: {{TARGET}}', optional: true, extras: true}, {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}, {name: 'silent', desc: 'Suppress program output', flags: ['-s', '--silent'], default: false},
]); ]);
const args = argParser.parse(ns.args); const args = argParser.parse(ns.args);

View File

@ -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 argList {(ArgParser || {name: string, desc: string, flags: string[], optional: boolean, default: boolean})[]} - Array of CLI arguments
* @param examples {string[]} - Additional examples to display * @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.name = name;
this.desc = desc; this.desc = desc;
@ -27,13 +28,12 @@ export class ArgParser {
`--help ${this.commands.length ? '[COMMAND]' : ''}` `--help ${this.commands.length ? '[COMMAND]' : ''}`
].filter(e => !!e); ].filter(e => !!e);
} }
/** /**
* Parse an array into an arguments dictionary using the configuration. * Parse an array into an arguments dictionary using the configuration.
* @param args {string[]} - Array of arguments to be parsed * @param args {string[]} - Array of arguments to be parsed
* @returns {object} - Dictionary of arguments with defaults applied * @returns {object} - Dictionary of arguments with defaults applied
*/ */
parse(args) { parse(args = this.ns.args) {
// Parse arguments // Parse arguments
let extras = [], parsed = {...this.defaults}, queue = [...args]; let extras = [], parsed = {...this.defaults}, queue = [...args];
while(queue.length) { while(queue.length) {
@ -51,7 +51,7 @@ export class ArgParser {
extras.push(arg); extras.push(arg);
continue; 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}`; if(value == null) parsed['_error'] = `Option missing value: ${arg.name}`;
parsed[argDef.name] = value; parsed[argDef.name] = value;
} else { // Command } else { // Command
@ -114,6 +114,6 @@ export class ArgParser {
if(this.commands.length) msg += '\n\nCommands:\n\t' + this.commands if(this.commands.length) msg += '\n\nCommands:\n\t' + this.commands
.map(command => `${command.name}${spacer(command.name)}${command.desc}`) .map(command => `${command.name}${spacer(command.name)}${command.desc}`)
.join('\n\t'); .join('\n\t');
return `${msg}\n\n`; this.ns.tprint(`${msg}\n\n`);
} }
} }

67
scripts/server-manager.js Normal file
View File

@ -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);
}
}