Explore, puis auto weaken/grow/hack, puis re depuis home

Bonjour Monde !

Il s'agit de mon premier guide, soyez indulgents. :)

Je vous propose un petit ensemble de 5 scripts NS1, permettant de faire un tour d'horizon des fonctionnalités offertes par le jeu :

resetgetroot.script - permet de remettre à zéro les hacktools en cours

explore.script - permet de faire un tour d'horizon des serveurs connectés

connection.script - infecte chaque serveur connecté pour y déployer hacktool.script

hacktool.script - déployé sur chaque serveur distant pour auto weaken/grow/hack

connectionfromhome.script - lance autant de hacktool.script sur les serveurs connectés que possible, en fonction de la RAM disponible sur home

Je décrirai en détail chacun des scripts dans chaque section de ce guide.

Resetgetroot.script

Deux paramètres optionnels peuvent être fournis :

run resetgetroot.script [hostname] [spawn][string] hostname- par défaut, tiendra compte du serveur actuel ; si renseigné, débutera par le serveur nommé

[bool] spawn- par défaut à zéro, spawnera 'explore.script' ; toute valeur non-nulle annule ce lancement automatique

Ce script prévient de son démarrage par un message "Start." dans la console, puis tente de cibler le serveur :

Si un fichier "NOMSERVEUR.txt" existe

> Le supprime et met fin aux 'hacktool.script' de la cible

> Scanne et parcoure les voisinsLorsque le ciblage est terminé, un message "Done." de fin de script est affiché, puis le script 'explore.script' est invoqué sous condition.

//resetgetroot.script tprint('Start.') infect(args[0], args[0]) tprint('Done.') if (!args[1]) { var scriptname = 'explore.script' tprint('spawn(' + scriptname + ')') spawn(scriptname) } function infect(target, chemin) { print('>infect(' + target + ')') var filegetroot = target + '.txt' if (!target || fileExists(filegetroot, 'home')) { if (!!target && target != 'home') { tprint('infect(' + target + ')') rm(filegetroot, 'home') while (getServerMaxMoney(target) && !getServerMoneyAvailable(target)) sleep(1000) scriptKill('hacktool.script', target) // Terminer les scripts qui restent // (si nécessaire) rm('hacktool.script', target) } var voisins = scan(target) print('voisins ' + target + ': ' + voisins.length + '.') for (var j = 0; j < voisins.length; j++) infect(voisins[j], chemin + '>' + voisins[j]) } else print(target + ': no ' + filegetroot) print('<infect(' + target + ')') }Mise à jour 16/01/2022 : retrait d'un tprint inutile, et ajout d'un tprint prévenant du spawn suivant.

Explore.script

Deux paramètres optionnels peuvent être fournis :

run explore.script [hostname] [spawn][string] hostname- par défaut, tiendra compte du serveur actuel ; si renseigné, débutera par le serveur nommé

[bool] spawn- par défaut à zéro, spawnera 'connection.script' ; toute valeur non-nulle annule ce lancement automatique

Ce script prévient de son démarrage par un message "Start." dans la console, puis tente de cibler le serveur :

Si un fichier "NOMSERVEUR.txt" n'existe pas

> Récupère les informations utiles du serveur et les ajoute dans un fichier "NOMSERVEUR.txt"

> Scanne et parcoure les voisinsLorsque le ciblage est terminé, la liste des informations sur les serveurs trouvés est écrite dans un fichier récapitulatif "srvrs.txt", un message "Done." de fin de script est affiché, puis le script 'connection.script' est invoqué sous condition.

//explore.script tprint('Start.') var srvs = infect(args[0], args[0], []) write('srvs.txt', JSON.stringify(srvs), 'w') // Réinitialisation tprint('Done.') if (!args[1]) { var scriptname = 'connection.script' tprint('spawn(' + scriptname + ')') spawn(scriptname) } function infect(target, chemin, srvs) { print('>infect(' + target + ')') var filegetroot = target + '.txt' if (!target || !fileExists(filegetroot, 'home')) { if (!!target) { var server = { "hostname": '', "maxMoney": 0, "minSecurity": 0, "serverNumPortsRequired": 0, "serverRequiredHackingLevel": 0, "threads": 0, "chemin": '', "getMoney": 0, "setServer": function (target, parents) { this.hostname = target this.maxMoney = getServerMaxMoney(target) this.minSecurity = getServerMinSecurityLevel(target) this.serverNumPortsRequired = getServerNumPortsRequired(target) this.serverRequiredHackingLevel = getServerRequiredHackingLevel(target) this.threads = parseInt((getServerMaxRam(target) - getServerUsedRam(target)) / getScriptRam('hacktool.script')) this.chemin = parents this.getMoney = getServerMoneyAvailable(target) return this } } var srv = server.setServer(target, chemin) var strsrv = JSON.stringify(srv) tprint(target + ': ' + strsrv) write(filegetroot, strsrv, "w") srvs.push(srv) } var voisins = scan(target) print('voisins ' + target + ': ' + voisins.length + '.') for (var j = 0; j < voisins.length; j++) srvs = infect(voisins[j], chemin + '>' + voisins[j], srvs) } print('<infect(' + target + ')') return srvs }

Mise à jour du 16/01/2022 : Ajout d'un tprint prévenant du spawn suivant.

Connection.script

Deux paramètres optionnels peuvent être fournis :

run connection.script [hostname] [spawn][string] hostname- par défaut, tiendra compte du serveur actuel ; si renseigné, débutera par le serveur nommé

[bool] spawn- par défaut à zéro, spawnera 'connectionfromhome.script' ; toute valeur non-nulle annule ce lancement automatique

Ce script prévient de son démarrage par un message "Start." dans la console, puis tente de cibler le serveur :

Si un fichier "NOMSERVEUR.txt" existe et que le serveur n'est pas réputé connecté

> Marque le serveur comme connecté, puis tente de prendre le root dessus

>> Si le serveur n'est pas actuellement rooté, liste les ports disponibles (brutessh, ftpcrack, ...) avant de tenter le nuke

>> Si le serveur est rooté, envoie le fichier 'hacktool.script' sur le serveur, et l'exécute avec le plus de threads possibles

> Scanne et parcoure les voisinsLorsque le ciblage est terminé, un message "Done." de fin de script est affiché, puis le script 'connectionfromhome.script' est invoqué sous condition.

//connection.script tprint('Start.') infect(args[0], args[0]) tprint('Done.') if (!args[1]) { var scriptname = 'connectionfromhome.script' tprint('spawn(' + scriptname + ')') spawn(scriptname) } function infect(target, chemin) { print('>infect(' + target + ')') var filegetroot = target + '.txt' var srv if (!target || (fileExists(filegetroot) && !(srv = JSON.parse(read(filegetroot))).isConnected)) { if (!!target) { srv.isConnected = true; write(filegetroot, JSON.stringify(srv), "w") getroot(srv) } var voisins = scan(target) print('voisins ' + target + ': ' + voisins.length + '.') for (var j = 0; j < voisins.length; j++) infect(voisins[j], chemin + '>' + voisins[j]) } print('<infect(' + target + ')') } function getroot(srv) { print('>getroot(' + srv.hostname + ')') var isRoot = hasRootAccess(srv.hostname) print('root ' + srv.hostname + ': ' + isRoot) if (!isRoot) { print('rooting ' + srv.hostname) var nukeDone = 0 if (fileExists("BruteSSH.exe", "home")) { brutessh(srv.hostname); nukeDone++ } if (fileExists("FTPCrack.exe", "home")) { ftpcrack(srv.hostname); nukeDone++ } if (fileExists("relaySMTP.exe", "home")) { relaysmtp(srv.hostname); nukeDone++ } if (fileExists("HTTPWorm.exe", "home")) { httpworm(srv.hostname); nukeDone++ } if (fileExists("SQLInject.exe", "home")) { sqlinject(srv.hostname); nukeDone++ } // Get root access to target server var nukeRequirement = srv.serverNumPortsRequired if (nukeRequirement <= nukeDone) { nuke(srv.hostname) tprint(srv.hostname + ' nukeed: ' + nukeRequirement + '.') } else tprint(srv.hostname + ' NOT nukeed:' + nukeDone + '/' + nukeRequirement) isRoot = hasRootAccess(srv.hostname) print('root ' + srv.hostname + ': ' + isRoot) if (isRoot) print(srv.hostname + ' rooted.') else print('!!!' + srv.hostname + ' NOT rooted.') } if (isRoot && srv.hostname != 'home') sendhacktool(srv) print('<getroot(' + srv.hostname + ')') } function sendhacktool(srv) { print('>sendhacktool(' + srv.hostname + ')') var filename = 'hacktool.script' if (!!srv.hostname) scp(filename, 'home', srv.hostname) print(srv.hostname + ' vidange:' + scriptKill(filename, srv.hostname)) sleep(1000) // Temps de mise à feu de scriptKill if (srv.threads > 0) print('exec(' + filename + ', ' + srv.hostname + ', ' + srv.threads + ', ' + srv.hostname + ')=' + exec(filename, srv.hostname, srv.threads, JSON.stringify(srv))) else tprint('!!!' + srv.hostname + ' NOT targeted. [srv.threads=' + srv.threads + ']') print('<sendhacktool(' + srv.hostname + ')') }Mise à jour du 16/01/2022 : Retrait d'un tprint inutile, et ajout d'un tprint prévenant du spawn suivant.

Hacktool.script

Un paramètre doit être fourni :

run connection.script SERVEUR[string] SERVEUR- paramètre requis ; il s'agit des informations du serveur JSON.stringifiées, pour économiser des requêtes à certaines valeurs (getServerMaxMoney, getServerMinSecurity), récupérées au préalable par 'explore.script'

Les données du serveur sont reconstruites à partir de l'argument 1, une cible de quantité d'argent et de sécurité est initiée, puis la boucle démarre :

Tant que la sécurité est trop élevée, weaken

Quand la sécurité est suffisamment faible,

> Si l'argent est trop bas, grow

> Sinon, si le hackinglevel est suffisant, hack

> Sinon, rien

Refaire la boucle tant que le fichier 'NOMSERVEUR.txt' existe dans "home"Lorsque la boucle est finie, un message "NOMSERVEUR ended." est affiché.

//hacktool.script var srv = JSON.parse(args[0]) var moneyThresh = srv.maxMoney * (1 - 10 / 100) var securityThresh = srv.minSecurity + (0.1 + 0.01) * srv.threads var securityLevel = getServerSecurityLevel(srv.hostname) var moneyLevel = getServerMoneyAvailable(srv.hostname) tprint(srv.hostname + '[' + srv.threads + '] joined: $' + moneyLevel + '/' + srv.maxMoney + '|' + securityLevel + '/' + srv.minSecurity + '.') do { // If the server's security level is above our threshold, weaken it while ((securityLevel = getServerSecurityLevel(srv.hostname)) > securityThresh) { print(srv.hostname + ' ' + securityLevel + '>' + securityThresh + ' [weaken]:' + weaken(srv.hostname, { threads: srv.threads })) } // If the server's money is less than our threshold, grow it if (!moneyThresh || (moneyLevel = getServerMoneyAvailable(srv.hostname)) < moneyThresh) { print(srv.hostname + ' ' + moneyLevel + '<' + moneyThresh + ' [grow]:' + grow(srv.hostname, { threads: srv.threads })) } // Otherwise, hack it else if (getHackingLevel() >= srv.serverRequiredHackingLevel) { print(srv.hostname + ' [hack]:' + hack(srv.hostname, { threads: srv.threads })) } else print(srv.hostname + ': despair.') //print(srv.hostname + ' [done]') //if (peek(1) != peek(2) && getServerMoneyAvailable(srv.hostname) <= 0) //writePort(20, srv.hostname) } while (fileExists(srv.hostname + '.txt', 'home') || getServerMoneyAvailable(srv.hostname) <= 0)//peek(1) == peek(2) || getServerMoneyAvailable(srv.hostname) <= 0) tprint(srv.hostname + ' ended.')

Connectionfromhome.script

Un paramètre optionnel peut être fourni :

run connectionfromhome.script [hostname][string] hostname- si renseigné, permet d'indiquer le nom d'un serveur à cibler en particulier

Ce script prévient de son démarrage par un message "Start." dans la console, puis tente de mettre fin à toutes les instances de hacktool.script éventuellement en cours sur le serveur (en considérant que leur nombre débute à zéro, et que toutes les instances sont nommées par incrément de 1).

Lorsque toutes les instances détectées sont fermées (cela peut prendre jusqu'à 1 minute pour 63 instances, et moins de quelques secondes pour le premier lancement) :

La liste des serveurs disponibles dans 'srvs.txt' (générée par 'explore.script') est filtrée

> Si un nom de serveur a été fourni en entrée, il est le seul conservé

> Sinon, seuls les serveurs étant accessibles au niveau de hacking du personnage ET dont les ports sont accessibles ET qui ont de l'argent sont conservés

Le(s) serveur(s) sont priorisés par quantité d'argent croissante

Un calcul est fait avec la quantité de RAM disponible sur Home, divisée par le coût de lancement de 'hacktool.script', cela donne le nombre de lancements parallèles possibles (threads) ; cette valeur est ensuite répartie équitablement entre toutes les entrées dans la liste des serveurs filtrés

Une copie du fichier 'hacktool.script' préfixée d'un incrément (débutant à zéro) est créée dans 'home', puis exécutée avec autant de threads que répartis

Lorsque le ciblage est terminé, un message "Done." de fin de script est affiché, et les niveaux de hacking devraient commencer à monter en flèche.

//connectionfromhome.script tprint('Start.') var filename = 'hacktool.script' var k = 0 while (scriptKill(k++ + filename, 'home')); var nukeDone = 0 if (fileExists("BruteSSH.exe", "home")) nukeDone++ if (fileExists("FTPCrack.exe", "home")) nukeDone++ if (fileExists("relaySMTP.exe", "home")) nukeDone++ if (fileExists("HTTPWorm.exe", "home")) nukeDone++ if (fileExists("SQLInject.exe", "home")) nukeDone++ var hackingLevel = getHackingLevel() var srvs = JSON.parse(read('srvs.txt')).filter(function (value) { if ((!args[0] || value.hostname == args[0]) && (value.serverRequiredHackingLevel <= hackingLevel && value.serverNumPortsRequired <= nukeDone && value.maxMoney > 0 && value.getMoney > 0)) return value }) srvs.sort(function (b, a) { return a.maxMoney - b.maxMoney // Moins efficace que 2 'if's et demie, // mais pas de beaucoup, et mieux maintenable }) var threadsDispos = parseInt((getServerMaxRam('home') - getServerUsedRam('home')) / getScriptRam(filename)) tprint('parseInt((' + getServerMaxRam('home') + '-' + getServerUsedRam('home') + ')/' + getScriptRam(filename) + ')' + '=' + threadsDispos) var threadsParSrv = Math.max(parseInt(threadsDispos / Math.max(srvs.length, 1)), 1) k = 0 while (srvs.length > 0) { // var threadsReDispos = Math.max(parseInt(((getServerMaxRam('home') - //getServerUsedRam('home')) / getScriptRam(filename)) / 2), 1) // tprint('parseInt(((' + getServerMaxRam('home') + '-' + getServerUsedRam('home') + ')/' + //getScriptRam(filename) + ')/2)' + '=' + threadsReDispos) var srv = srvs.pop() print('targetting ' + srv.hostname) srv.threads = threadsParSrv // threadsReDispos // write(k + filename, read(filename), 'w') print('run(' + k + filename + ', ' + srv.threads + ', ' + srv.hostname + ')=' + run(k + filename, srv.threads, JSON.stringify(srv))) k++ print(srv.hostname + ' targeted.') } tprint('Done.')Mise à jour du 16/01/2022 : cette section avait été oubliée précédemment, toutes mes excuses.

Comment On S'en Sert ?

Salut, et bravo d'avoir lu jusque-là !

La version la plus simple du mode d'emploi, c'est :

Récupérer les 5 fichiers précédents dans "home" (et de préférence bien garder leur nom, pour qu'ils puissent s'enchaîner proprement),

Puis de lancer simplement run resetgetroot.script depuis le serveur "home".

Les scripts s'enchaîneront pour explorer les serveurs alentours, s'y connecter, et lancer une connexion depuis "home".

J'ai Gagné X Niveaux/programmes/RAM, Je Fais Quoi Maintenant ?

Comme il n'existe pas de tâche proactive surveillant la disponibilité des niveaux, programmes et RAM, il faut manuellement (ré)exécuter run resetgetroot.script pour mettre à zéro les serveurs parcourus, les re-explorer, s'y connecter (cela contactera les nouveaux disponibles), et reprendra les connexions depuis "home".

Tout-ça, avec cette seule commande. (Et un-peu de patience, le temps que les enchaînements se fassent.)

Et La Suite ?

Voilà, pour les points d'amélioration :

Passer les scripts en NS2, cela devrait booster leur vitesse d'exécution, ainsi qu'aider pour d'autres points

Modifier certains paramètres de hacktool.script pour des peek(X), cela économisera du coût de script (mais nécessite le passage en NS2)

Revoir certains algorithmes de choix de cibles, notamment pour connectionfromhome.script, qui pourrait cibler plus de threads sur un serveur à forte valeur ajoutée, au-lieu de cibler tous équitablement

Ajouter un script de surveillance proactive pour la gestion des niveaux de hacking, programmes, RAM, ...

Mieux explorer les environs, pour éviter les appels à 'explore.script' (qui ne sont utiles que lors des remises à zéro du monde)

D'autres scripts pour tenir compte des autres stats (de combat, de marchés, de hacknodes, ...)

Si possible, trouver un moyen de scripter les backdoors !

N'hésitez pas à commenter ci-dessous, amusez-vous et bon jeu !

Mises à Jour

Le 16/01/2022 :

Mises à jour de hacktool.script et connection.script pour réduire le flot de messages dans la console.

Ajout d'un tprint informant du spawn suivant.

Ajout de la section "connectionfromhome.script" manquante.

Source: https://steamcommunity.com/sharedfiles/filedetails/?id=2716312876					

More Bitburner guilds