Created
May 16, 2025 15:57
-
-
Save m-sterling/840a05dcfc3efce879da40da5e6e236d to your computer and use it in GitHub Desktop.
Morgan's Bitburner scripts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // for direct use with spreader.js | |
| // source: https://github.com/bitburner-official/bitburner-scripts/blob/master/basic_hack.js | |
| /** @param {NS} ns */ | |
| export async function main(ns) { | |
| const hostname = ns.self().server | |
| while (true) { | |
| if (ns.getServerSecurityLevel(hostname) > ns.getServerMinSecurityLevel(hostname)) { | |
| await ns.weaken(hostname); | |
| } else if (ns.getServerMoneyAvailable(hostname) < ns.getServerMaxMoney(hostname)) { | |
| await ns.grow(hostname); | |
| } else { | |
| await ns.hack(hostname); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // crawls the entire network and hacks all servers that it can | |
| // protip: if you have enough port-hacking tools, you can nuke a server regardless of your level | |
| // however, you can't hack/grow/weaken/backdoor it or run scripts on it until you hit the req'd level | |
| /** @param {NS} ns */ | |
| export async function main(ns: NS) { | |
| const start = new Date() | |
| const args = ns.flags([['v', false], ['vv', false], ['vvv', false]]) | |
| if (args.vvv) { | |
| args.vv = true | |
| } | |
| if (args.vv) { | |
| args.v = true | |
| } | |
| let servers: string[] = [] | |
| let searched: string[] = [] | |
| function scan(target: string) { | |
| for (let serverName of ns.scan(target)) { | |
| if (servers.includes(serverName) || searched.includes(serverName)) | |
| continue | |
| searched.push(serverName) | |
| const server = ns.getServer(serverName) | |
| if (!server.hasAdminRights) { | |
| servers.push(serverName) | |
| } | |
| scan(serverName) | |
| } | |
| } | |
| scan("") | |
| ns.tprintf("Attempting to hack %d servers...", servers.length) | |
| let failures = 0 | |
| let successes = 0 | |
| let lowestHackingLevelNeeded = Number.MAX_SAFE_INTEGER | |
| let lowestHackingLevelServers = 0 | |
| let lowestOpenPortsNeeded = 5 | |
| let lowestOpenPortsServers = 0 | |
| servers.forEach(serverName => { | |
| let server: Server = ns.getServer(serverName) | |
| try { | |
| ns.brutessh(serverName) | |
| } catch (_) {} | |
| try { | |
| ns.ftpcrack(serverName) | |
| } catch (_) {} | |
| try { | |
| ns.httpworm(serverName) | |
| } catch (_) {} | |
| try { | |
| ns.sqlinject(serverName) | |
| } catch (_) {} | |
| try { | |
| ns.relaysmtp(serverName) | |
| } catch (_) {} | |
| if (server.numOpenPortsRequired! > server.openPortCount!) { | |
| failures++ | |
| ns.tprintf('Nuking %s failed: not enough ports open', serverName) | |
| if (server.numOpenPortsRequired! < lowestOpenPortsNeeded) { | |
| lowestOpenPortsNeeded = server.numOpenPortsRequired! | |
| lowestOpenPortsServers = 0 | |
| } | |
| lowestOpenPortsServers++ | |
| if (args.v) { | |
| ns.tprintf(' Have: %d', server.openPortCount!) | |
| ns.tprintf(' Need: %d', server.numOpenPortsRequired!) | |
| if (args.vv) { | |
| // ns.tprintf(' SSH: %s', server.sshPortOpen ? "true" : "false") | |
| // ns.tprintf(' FTP: %s', server.ftpPortOpen ? "true" : "false") | |
| // ns.tprintf(' HTTP: %s', server.httpPortOpen ? "true" : "false") | |
| // ns.tprintf(' SQL: %s', server.sqlPortOpen ? "true" : "false") | |
| // ns.tprintf(' SMTP: %s', server.smtpPortOpen ? "true" : "false") | |
| if (args.vvv) { | |
| ns.tprintf(' Hacking level needed: %d', server.requiredHackingSkill!) | |
| } | |
| } | |
| } | |
| } else if (ns.nuke(serverName)) { | |
| successes++ | |
| ns.tprintf('Nuking %s succeeded!', serverName) | |
| } else { | |
| failures++ | |
| ns.tprintf("Nuking %s failed: hacking level too low", serverName) | |
| if (server.requiredHackingSkill! < lowestHackingLevelNeeded) { | |
| lowestHackingLevelNeeded = server.requiredHackingSkill! | |
| lowestHackingLevelServers = 0 | |
| } | |
| lowestHackingLevelServers++ | |
| if (args.v) { | |
| ns.tprintf(' Have: %d', ns.getHackingLevel()) | |
| ns.tprintf(' Need: %d', server.requiredHackingSkill!) | |
| if (args.vvv) { | |
| ns.tprintf(' Ports opened: %d', server.openPortCount!) | |
| ns.tprintf(' Ports needed: %d', server.numOpenPortsRequired!) | |
| } | |
| } | |
| } | |
| }) | |
| ns.tprintf('Successes: %d', successes) | |
| ns.tprintf('Failures: %d', failures) | |
| if (args.v && failures > 0) { | |
| if (lowestHackingLevelNeeded == Number.MAX_SAFE_INTEGER) { | |
| lowestHackingLevelNeeded = ns.getHackingLevel() | |
| } | |
| ns.tprintf('Hacking level needed: %d/%d (for %d server%s)', ns.getHackingLevel(), lowestHackingLevelNeeded, lowestHackingLevelServers, lowestHackingLevelServers == 1 ? '' : 's') | |
| ns.tprintf('Open ports needed: %d/%d (for %d server%s)', [ns.fileExists('BruteSSH.exe', 'home'), ns.fileExists('FTPCrack.exe', 'home'), ns.fileExists('relaySMTP.exe', 'home'), ns.fileExists('HTTPWorm.exe', 'home'), ns.fileExists('SQLInject.exe', 'home')].filter(e => e).length, lowestOpenPortsNeeded, lowestOpenPortsServers, lowestOpenPortsServers == 1 ? '' : 's') | |
| } | |
| ns.toast(`${ns.self().filename} completed in ${(new Date()).getTime() - start.getTime()}ms`) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // for messing around with things | |
| /** @param {NS} ns */ | |
| export async function main(ns) { | |
| ns.ramOverride(ns.getServer(ns.self().server).maxRam - ns.getServer(ns.self().server).ramUsed) | |
| ns.tprint(eval(ns.args.join(" ") || "'Hello world'") || '') | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // list all servers and their features, with optional filtering | |
| // also used in spreader.js | |
| /** @param {NS} ns */ | |
| export async function main(ns) { | |
| const start = new Date() | |
| const flags = ns.flags([['help', false], ['verbose', false], ['nohacked', false], ['nounhacked', false], ['files', false], ['plain', false]]) | |
| if (flags.help) { | |
| ns.tprintf("Usage: run %s [--verbose] [--nounhacked] [--nohacked] [--plain]", ns.self().filename) | |
| ns.tprintf(" --verbose: Includes system information for servers") | |
| ns.tprintf(" --nounhacked: Hides unhacked servers") | |
| ns.tprintf(" --nohacked: Hides hacked servers") | |
| ns.tprintf(" --files: Show the files present on the servers") | |
| ns.tprintf(" --plain: Outputs only the server names, nothing else") | |
| return | |
| } | |
| let servers = {} | |
| function scan(target, route) { | |
| for (let serverName of ns.scan(target)) { | |
| if (Object.keys(servers).includes(serverName)) | |
| continue | |
| let server = ns.getServer(serverName) | |
| if (server.backdoorInstalled) | |
| route = [] | |
| let curRoute = [...route, serverName] | |
| servers[serverName] = { | |
| hacked: server.hasAdminRights, | |
| route: curRoute.join(' \u2192 '), // → | |
| files: ns.ls(serverName) | |
| } | |
| scan(serverName, curRoute) | |
| } | |
| } | |
| scan("", []) | |
| if (!flags.plain) { | |
| if (!flags.nohacked) { | |
| ns.tprintf('=== HACKED SERVERS ===') | |
| Object.keys(servers).filter(serverName => servers[serverName].hacked).sort().forEach(serverName => { | |
| let server = ns.getServer(serverName) | |
| ns.tprintf('- %s (%s)', serverName, servers[serverName].route) | |
| if (flags.verbose) { | |
| ns.tprintf('\tBackdoored: %s (lv. %d/%d)', server.backdoorInstalled ? "true" : "false", ns.getHackingLevel(), server.requiredHackingSkill) | |
| ns.tprintf('\tRAM: %fGB/%fGB used', server.ramUsed, server.maxRam) | |
| ns.tprintf('\tCPU: %d core%s', server.cpuCores, server.cpuCores == 1 ? '' : 's') | |
| } | |
| if (flags.files) { | |
| ns.tprintf('\tFiles: "%s"', servers[serverName].files.join('", "')) | |
| } | |
| }) | |
| } | |
| if (!flags.nounhacked) { | |
| ns.tprintf('=== UNHACKED SERVERS ===') | |
| Object.keys(servers).filter(serverName => !servers[serverName].hacked).sort().forEach(serverName => { | |
| let server = ns.getServer(serverName) | |
| ns.tprintf('- %s (%s)', serverName, servers[serverName].route) | |
| if (flags.verbose) { | |
| ns.tprintf('\tHacking skill needed: %d', server.requiredHackingSkill ?? 0) | |
| ns.tprintf('\tPorts open: %d', server.openPortCount ?? 0) | |
| ns.tprintf('\tPorts needed: %d', server.numOpenPortsRequired ?? 0) | |
| } | |
| if (flags.files) { | |
| ns.tprintf('\tFiles: "%s"', servers[serverName].files.join('", "')) | |
| } | |
| }) | |
| } | |
| } else { | |
| let s = "" | |
| if (!flags.nohacked) { | |
| s += Object.keys(servers).filter(serverName => servers[serverName].hacked).sort().join("\n") | |
| } | |
| if (!flags.nounhacked) { | |
| s += Object.keys(servers).filter(serverName => !(servers[serverName].hacked)).sort().join("\n") | |
| } | |
| ns.print(s) | |
| } | |
| ns.toast(`${ns.self().filename} completed in ${(new Date()).getTime() - start.getTime()}ms`) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // script spreader | |
| // used to auto-execute a script on all of your hacked servers | |
| // to switch to a new script, --kill the first one before spreading the new script | |
| /** @param {NS} ns */ | |
| export async function main(ns) { | |
| const start = new Date() | |
| const flags = ns.flags([['kill', false], ['singlethreaded', false]]) | |
| if (ns.args.length == 0) { | |
| ns.tprintf("Usage: run %s [script name]", ns.self().scriptName) | |
| return | |
| } | |
| let fails = 0, empty = 0 | |
| const scriptName = ns.args[0] | |
| const servers = (await ns.getScriptLogs(await ns.run('list.js', undefined, '--plain', '--nounhacked'))).filter(line => !line.startsWith('scan:')).join('').split('\n') | |
| for (let serverName of servers) { | |
| let server = ns.getServer(serverName) | |
| if (flags.kill) { | |
| if (!await ns.scriptKill(scriptName, serverName)) { | |
| fails++ | |
| } | |
| } else { | |
| if (serverName !== 'home') { | |
| if (server.requiredHackingSkill <= ns.getHackingLevel()) { | |
| if (server.maxRam >= ns.getScriptRam(scriptName)) { | |
| await ns.scriptKill(scriptName, serverName) | |
| server = ns.getServer(serverName) | |
| await ns.scp(scriptName, serverName, 'home') | |
| await ns.exec(scriptName, serverName, {preventDuplicates: true, threads: flags.singlethreaded ? 1 : Math.floor((server.maxRam - server.ramUsed)/ns.getScriptRam(scriptName))}) | |
| } else { | |
| empty++ | |
| } | |
| } else { | |
| fails++ | |
| } | |
| } | |
| } | |
| } | |
| if (flags.kill) { | |
| ns.tprintf("Killed %s on %d servers", scriptName, servers.length - fails) | |
| if (fails != 0) { | |
| ns.tprintf("Script %s not running on %d servers", scriptName, fails) | |
| } | |
| } else { | |
| ns.tprintf("Copied and executed %s to %d servers", scriptName, servers.length - fails) | |
| if (fails != 0) { | |
| ns.tprintf("Failed to execute on %d servers due to insufficient hacking level", fails) | |
| } | |
| if (empty != 0) { | |
| ns.tprintf("Failed to execute on %d servers due to a lack of RAM", empty) | |
| } | |
| } | |
| ns.toast(`${ns.self().filename} completed in ${(new Date()).getTime() - start.getTime()}ms`) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment