Skip to content

Instantly share code, notes, and snippets.

@MolarFox
Last active September 8, 2024 14:30
Show Gist options
  • Select an option

  • Save MolarFox/87c2dd6a7337e307ae7c328aabb4fdbe to your computer and use it in GitHub Desktop.

Select an option

Save MolarFox/87c2dd6a7337e307ae7c328aabb4fdbe to your computer and use it in GitHub Desktop.
Bitburner Stuff
// Basic Autohack v1.0
// Basic first pass dingus script. Just grows, weakens, and hacks every loop
/** @param {NS} ns */
export async function main(ns) {
const args = arguments["0"]["args"];
let tgt = args[0]
while(true) {
await ns.grow(tgt);
await ns.weaken(tgt);
await ns.hack(tgt);
}
}
// Bounded Hack Autohack v1.1
// Aims to get money and security to certain levels before attempting any hacking
// By default - attempts to get to min security and max profit
/** @param {NS} ns */
export async function main(ns) {
let hack_count = 0
let hack_reporting_interval = 10
const args = arguments["0"]["args"];
const sv_max_money = await ns.getServerMaxMoney(tgt);
const sv_min_security = await ns.getServerMinSecurityLevel(tgt);
let tgt = args[0]
let min_profit = typeof(args[1]) == 'undefined' ? sv_max_money : args[1];
let max_sec = typeof(args[2]) == 'undefined' ? sv_min_security : args[2];
while(true) {
let current_money = await ns.getServerMoneyAvailable(tgt);
let current_sec = await ns.getServerSecurityLevel(tgt);
if (current_money < min_profit) {
await ns.grow(tgt);
continue;
}
if (current_sec > max_sec) { await ns.weaken(tgt) };
if (current_money >= min_profit && current_sec <= max_sec) {
await ns.hack(tgt);
hack_count++;
if (hack_count % hack_reporting_interval == 0) {
ns.alert(`Hacked ${tgt} ${hack_count} times`)
}
}
}
}
// Bubble Growth Autohack v1.0
// Aims to hack as often as possible, ensuring that money and sec are both improved since the last hack attempt
/** @param {NS} ns */
export async function main(ns) {
let hack_count = 0
let hack_reporting_interval = 10
const args = arguments["0"]["args"];
let tgt = args[0]
let last_profit = await ns.getServerMoneyAvailable(tgt);
let last_sec = await ns.getServerSecurityLevel(tgt);
const sv_max_money = await ns.getServerMaxMoney(tgt);
const sv_min_security = await ns.getServerMinSecurityLevel(tgt);
while(true) {
let current_money = await ns.getServerMoneyAvailable(tgt);
let current_sec = await ns.getServerSecurityLevel(tgt);
if (current_money < last_profit && current_money != sv_max_money) {
await ns.grow(tgt);
continue;
}
if (current_sec > last_sec && current_sec != sv_min_security) { await ns.weaken(tgt) };
if (current_money >= last_profit && current_sec <= last_sec) {
await ns.hack(tgt);
hack_count++;
if (hack_count % hack_reporting_interval == 0) {
ns.alert(`Attempted to hack ${tgt} ${hack_count} times`)
}
}
}
}
// autoroot v1.4
// Reads a CSV of enumerated hosts and attempts to backdoor all,
// Then use their collective compute to mine currency off all
export function autocomplete(data, _) {
return [...data.txts];
}
/** @param {NS} ns */
export async function main(ns) {
const args = arguments["0"]["args"];
const file_name = args[0];
// Increase static ram estimate to factor dynamic run calls later on
ns.ramOverride(2.0)
let player_level = await ns.getHackingLevel()
let sv_list = parseCsv(ns.read(file_name));
// Root every possible node
sv_list.map(((x) => {backdoorServer(ns, x, player_level)}));
ns.tprint("Finished running! Remember to update hosts CSV with nmap before rerunning")
}
/**
* @param {String} file_data
* @return {Array} Array of dicts containing info on each enumerated node
* */
function parseCsv(file_data) {
return file_data.split('\n').map((raw_row) => {
let row = raw_row.split(',');
let res = {};
res["name"] = row[0];
res["path"] = row[1];
res["root"] = (row[2] === 'true');
res["min_hack_level"] = parseInt(row[3]) || row[3];
res["max_profit"] = parseFloat(row[4]) || row[4];
res["max_ram"] = parseFloat(row[5]) || row[5];
return res;
}).slice(1); // Slice out the header row
}
/**
* @param {NS} ns
* @param {Object} node
* */
async function backdoorServer(ns, node, player_level) {
if (node.root) { return };
if (player_level < node.min_hack_level){ return };
ns.tprint(`Attempting to backdoor ${node.name}...`);
let name = node.name;
let ports_needed_count = ns.getServerNumPortsRequired(name);
let available_exploits = availableExploits(ns).map((x) => x.split('.')[0].toLowerCase());
if (ports_needed_count > available_exploits.length) {
ns.tprint(" [!] Not enough exploits available to enable backdoor! Skipping.");
return
}
available_exploits.length = ports_needed_count
for (const exploit of available_exploits) {
ns[exploit](name);
}
await ns.nuke(name);
await ns.tprint(`Successfully backdoored ${name}!`);
}
/**
* @param {NS} ns
* @return {Array<String>} List of available scripts
* */
function availableExploits(ns) {
let script_files = [
"BruteSSH.exe",
"FTPCrack.exe",
"HTTPWorm.exe",
"relaySMTP.exe",
"SQLInject.exe",
]
let res = [];
for (const f of script_files) {
if (ns.fileExists(f)) {
res.push(f)
}
}
return res
}
// nmap v1.3
// Enumerates all servers from the current one, and produces a CSV containing a list of all found
export function autocomplete(data, _) {
return [...data.txts];
}
/** @param {NS} ns */
export async function main(ns) {
const args = arguments["0"]["args"];
const header_row = "name,path,root,min_hack_level,max_profit,max_ram";
const file_name = args[0];
let nodes = await dfs(ns, ns.getHostname());
// Write to CSV file
ns.write(file_name, header_row, 'w');
for (let n in nodes) {
let line = csvRow(nodes[n]);
ns.write(file_name, line, 'a');
}
}
/**
* @param {NS} ns
* @param {String} root
* @return {Object} Dict: key<String> node name, val<Object> attributes describing a node
* */
async function dfs(ns, root) {
let to_visit = [root];
let visited = {};
visited[root] = await nodeData(ns, root, [root]);
while (to_visit.length > 0) {
let head = to_visit.shift();
// await ns.tprint(`At ${head} - ${to_visit}`);
let child_nodes = await ns.scan(head);
for (let n in child_nodes) {
let node = child_nodes[n];
if (node in visited) { continue };
to_visit.push(node);
visited[node] = await nodeData(ns, node, visited[head].path.concat(node));
}
}
return visited;
}
/**
* @param {NS} ns
* @param {String} name
* @param {Array<String>} path
* @return {Object} Contains attributes describing a node
* */
async function nodeData(ns, name, path) {
return {
name: name,
path: path,
root: await ns.hasRootAccess(name),
min_hack_level: await ns.getServerRequiredHackingLevel(name),
max_profit: await ns.getServerMaxMoney(name),
max_ram: await ns.getServerMaxRam(name),
};
}
/**
* @param {Object} node
* @return {String}
* */
function csvRow(node) {
// TODO: whatever make this dynamic later
return '\n' + [
node.name,
node.path.join('/'),
node.root,
node.min_hack_level,
node.max_profit,
node.max_ram,
].join(',');
}
// Auto Hack Orchestrator v1.2
// Reads a CSV of enumerated hosts and schedules all hosts to repeatedly hack one another
export function autocomplete(data, _) {
return [...data.txts, ...data.scripts];
}
/** @param {NS} ns */
export async function main(ns) {
const args = arguments["0"]["args"];
const nmap_file = args[0];
const hack_script = args[1];
const include_home = (typeof(args[2]) === 'undefined') ? false : Boolean(args[2]);
const player_level = await ns.getHackingLevel();
let sv_list = (
parseCsv(ns.read(nmap_file)) // All servers reachable from host
.filter((x) => x.root) // Which have been rooted
);
sv_list = (include_home) ? sv_list : sv_list.filter((x) => x.name != "home");
let allocated = allocateAndRun(ns, sv_list, player_level, hack_script);
ns.tprint(`Configured ${Object.keys(allocated).length} attacks!`)
}
/**
* @param {String} file_data
* @return {Array} Array of dicts containing info on each enumerated node
* */
function parseCsv(file_data) {
return file_data.split('\n').map((raw_row) => {
let row = raw_row.split(',');
let res = {};
res["name"] = row[0];
res["path"] = row[1];
res["root"] = (row[2] === 'true');
res["min_hack_level"] = parseInt(row[3]) || row[3];
res["max_profit"] = parseFloat(row[4]) || row[4];
res["max_ram"] = parseFloat(row[5]) || row[5];
return res;
}).slice(1); // Slice out the header row
}
/**
* @param {NS} ns
* @param {Array<Object>} nodes
* @param {Int} player_level
* @return {Object<String,Object>} Dict mapping each server to its target
* */
function allocateAndRun(ns, nodes, player_level, hack_script) {
const nodes_by_profit = (
nodes
.filter((x) => x.min_hack_level <= player_level) // Player can hack
.filter((x) => x.max_profit > 0) // Will yield hacking profits
.toSorted((a,b) => (a.max_profit - b.max_profit)) // Sorted by max profit (asc)
);
const nodes_by_ram = nodes.toSorted((a,b) => (a.max_ram - b.max_ram));
let res = {};
// ns.tprint(`--NODES BY RAM--\n${nodes_by_ram.map((x) => x.name)}\n\n--NODES BY PROFIT--\n${nodes_by_profit.map((x) => x.name)}\n\n`)
while (nodes_by_profit.length > 0) {
let attacker = nodes_by_ram.pop(); // Take strongest rooted server
let target = nodes_by_profit.at(-1).name == attacker.name ? nodes_by_profit.splice(-2, 1)[0] : nodes_by_profit.splice(-1, 1)[0]; // Take highest profit server
// Run attack
scheduleAttack(ns, attacker, target, hack_script);
res[attacker.name] = target;
}
return res;
}
/**
* @param {NS} ns
* @param {Object} node
* @param {Object} target
* @param {String} hack_script
*/
function scheduleAttack(ns, node, target, hack_script) {
const hack_thread_cost = ns.getScriptRam(hack_script);
const max_threads = Math.floor(node.max_ram / hack_thread_cost);
ns.tprint(`Attacking ${target.name} [max profit: ${target.max_profit}] from ${node.name} [ram: ${node.max_ram}]`)
ns.scp(hack_script, node.name);
ns.exec(hack_script, node.name, max_threads, target.name)
}
@MolarFox
Copy link
Author

MolarFox commented Sep 6, 2024

A bunch of random scripts I wrote to play Bitburner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment