diff --git a/colony.src b/colony.src deleted file mode 100644 index 48865b63c8346126836d38bf7d38860ce3ba407f..0000000000000000000000000000000000000000 --- a/colony.src +++ /dev/null @@ -1,93 +0,0 @@ -// Tool to send to rented servers the default binaries from computers -// Note that the utility methods to transfer a file only accepts complete path -// "connect" and "transfer" should be easy reusable for a code pulling tool (issue #7) - -imports = {} -imports.temp = {} - -imports.utils = {} -imports.utils.ParamLength = function(params) - if params == null then return 0 - return params.len -end function -imports.utils.GetParam = function(params, index) - if index < 0 or index >= imports.utils.ParamLength(params) then return null - return params[index] -end function -imports.utils.HasFlag = function(params, short, long) - if imports.utils.ParamLength(params) == 0 then return null - param = params[0] - return param == "-"+short or param == "-"+long -end function -imports.utils.GetProgName = function() - return program_path.split("/")[-1] -end function - -imports.remote = {} - -imports.remote.getService = function(port) - if port == 22 then return "ssh" - if port == 21 then return "ftp" - return null -end function -imports.remote.connect = function(shell, user, password, ip, port=null, service=null) - if not shell then shell = get_shell - if not port then port = 22 - if typeof(port) == "string" then port = port.to_int - if not service then - service = imports.remote.getService(port) - if not service then return null - end if - return shell.connect_service(ip, port, user, password, service) -end function -imports.remote.transfer = function(shell, origin, dest, upload=true) - if upload then - sourceShell = get_shell - targetShell = shell - else - sourceShell = shell - targetShell = get_shell - end if - if dest[dest.len-2] != "/" then dest = dest + "/" - fileName = origin[path.lastIndexOf("/")+1:] - destPath = dest+fileName - if targetShell.host_computer.File(destPath) != null then return destPath+" already exists" - return sourceShell.scp_upload(origin, dest, targetShell) -end function - -imports.file = {} - -imports.temp.AddCmd = function(arr, files) - for file in files - arr.push("/bin/"+file) - end for -end function -imports.temp.AddSoft = function(arr, files) - for file in files - arr.push("/usr/bin/"+file+".exe") - end for -end function - -imports.file.MISSING = [] -imports.temp.AddCmd(imports.file.MISSING,["airmon","aireplay","aircrack","nmap","smtp-user-list","decipher","scanlib","scanrouter"]) -imports.temp.AddSoft(imports.file.MISSING,["Map","Manual","AdminMonitor"]) - -imports.temp = null - -//command: colony -length = imports.utils.ParamLength(params) -if length < 3 or length > 5 or imports.utils.HasFlag(params, "h", "help") then exit("<b>Usage: "+imports.utils.GetProgName()+" [user] [password] [ip] [(opt) port] [(opt) service]</b>") -comp = get_shell.host_computer - -user = imports.utils.GetParam(params, 0) -password = imports.utils.GetParam(params, 1) -ip = imports.utils.GetParam(params, 2) -port = imports.utils.GetParam(params, 3) -service = imports.utils.GetParam(params, 4) - -remote = imports.remote.connect(get_shell, user, password, ip, port, service) -if not remote then exit("Can't connect to remote server") -for path in imports.file.MISSING - result = imports.remote.transfer(remote, path, path[:path.lastIndexOf("/")], true) - if result != 1 then print(result) -end for \ No newline at end of file diff --git a/example_scripts/xbuild.src b/example_scripts/xbuild.src deleted file mode 100644 index c7d5c8a3f9af522475db0411d54554bf8594233c..0000000000000000000000000000000000000000 --- a/example_scripts/xbuild.src +++ /dev/null @@ -1,288 +0,0 @@ -"#import includes/utils.inc.src" -"#import includes/file.inc.src" - -// To allow self-building : build it with build, then use it to build it's own source to include libraries -"#ifbuild" -if not globals.hasIndex("imports") then - imports = {} - imports.utils = {} - imports.file = {} - utils = imports.utils - file = imports.file - - utils.GetProgName = function() - // To make sure we notice it's not updated - return program_path.split("/")[-1] +" (by build)" - end function - utils.Print = function(reason) - print(imports.utils.GetProgName()+": "+reason) - end function - utils.Exit = function(reason) - exit(imports.utils.GetProgName()+": "+reason) - end function - utils.ParamLength = function(params) - length = 0 - for param in params - if param[0] != "-" then length = length + 1 - end for - return length - end function - utils.GetParam = function(params, index) - i = 0 - for param in params - if param[0] == "-" then continue - if (i == index) then return param - i = i+1 - end for - return null - end function - utils.HasFlag = function(params, short, long) - // Not critical for a self-build - return long != "help" - end function - utils.leftSlice = function(str,stop) - if stop == 0 then return "" - return str[:stop] - end function - file.NEW_LINE = char(10) - file.AbsolutePath = function(path, current) - if path[0] == "/" then return path - if current == null then current = get_shell.host_computer.current_path - path = current + "/" + path - return path - end function - file.getFiles = function(path, recursive) - return [get_shell.host_computer.File(path)] - end function - file.ReadAllLines = function(target) - utils.Print("Reading file '"+path+"'") - // Enough to self-build - if typeof(target) == "string" then - target = get_shell.host_computer.File(target) - end if - return target.content.split(file.NEW_LINE) - end function - file.GetDir = function(path) - if typeof(path) == "file" then path = path.path - return path[0:path.lastIndexOf("/")] - end function - file.GetName = function(path) - return path[path.lastIndexOf("/")+1:] - end function - file.FileNameNoExt = function(path) - index = path.lastIndexOf("/") - if index != null then path = path[index+1:] - index = path.indexOf(".") - if index != null then path = path[:index] - return path -end function -end if -"#endif" - -//command: xbuild -length = imports.utils.ParamLength(params) -if length < 2 or length > 4 or imports.utils.HasFlag(params, "h", "help") then exit("<b>Usage: "+imports.utils.GetProgName()+" [file] [build dir] [(opt) preproc dir] --save</b>") -comp = get_shell.host_computer - -// Return null for an empty String, returns the last character otherwise -// Used to identify Strings -GetLastChar = function(str) - if not str then return null - if str.len < 1 then return null - return str[str.len-1] -end function - -source = imports.utils.GetParam(params,0) -build = imports.utils.GetParam(params,1) -preproc = imports.utils.GetParam(params,2) -save = imports.utils.HasFlag(params,"s","save") -if not preproc then - preproc = comp.current_path -else - if GetLastChar(preproc) == "/" then preproc = preproc[0:preproc.len-1] - print(preproc) - preproc = imports.file.AbsolutePath(preproc) - print(preproc) -end if - -// A " character -QUOTE = """" - -// If a line is made of a String with the flag character, returns the text inside -StringInstruction = function(str) - if GetLastChar(str) != QUOTE then return null - if str[0] != QUOTE then return null - str = str[1:str.len-1] - if str.indexOf(QUOTE) != null then return null - str = str.trim() - if str[0] != "#" then return "" - return str[1:str.len] -end function - -// Remove the comment at the end of a line, and the extra spaces at the start and the end -// Shouldn't affect the result of the script, but reduce the total character count -WithoutComment = function(str) - Count = function(str, char) - count = 0 - for car in str - if car == char then count = count + 1 - end for - return count - end function - - COM = "//" - index = str.indexOf(COM) - if index == null then return str - result = imports.utils.leftSlice(str,index) - if Count(result, QUOTE) % 2 != 0 then - result = result + COM + WithoutComment(str[index+2:str.len]) - end if - return result.trim() -end function - -// List of already imported libraries to avoid duplicating the code -imported = [] -// If two imports are trying to import each other *before the other*, will make sure the script errors instead of going in an infinite loop -check = [] - -// Method called to read-copy a source file (either the original script or its libraries) -InsertCode = function(path, original=false) - IMPORT = "import " - IFBUILD = "ifbuild" - ENDIF = "endif" - - // Store the processed source for this specific file - content = "" - nextLine = false - skip = false - followImport = false - - for line in imports.file.ReadAllLines(path) - // Removes the extra space, the comment and AGAIN the extra space once the comment is removed - line = WithoutComment(line.trim()) - //if line == null or line.len == 0 then continue - if line.len == 0 then continue - isImport = false - - instruct = StringInstruction(line) - if instruct != null then - if instruct.len == 0 then continue - - // There's use of the "#command abc" syntax - line = null - isImport = false - for tag in [IMPORT, IFBUILD, ENDIF] - if instruct[0:tag.len] == tag then - if tag == IMPORT then - isImport = true - followImport = true - - // If currently in "skip mode", obviously nothing should change :D - if not skip then - importPath = imports.file.AbsolutePath(instruct[tag.len:], imports.file.GetDir(path)) - // If already imported, skip to save characters - if imported.indexOf(importPath) == null then - // If two imports tries to import each other, which one goes first? Nice paradox, right? - if check.indexOf(importPath) != null then exit("ERROR, cyclic import of "+importPath) - check.push(importPath) - // Recursive call - line = "imports.temp={}"+ imports.file.NEW_LINE + InsertCode(imports.file.AbsolutePath(importPath)) - imported.push(importPath) - end if - end if - else - skip = (tag == IFBUILD) - end if - break - end if - end for - // No valid command? Unused string then skip it - if line == null then continue - end if - - // followImport is memorized, isImport is reset after each line - if not isImport and followImport then - followImport = false - line = "imports.temp={}" + imports.file.NEW_LINE + line - end if - - // No writing in skip mode - if skip or line == null then continue - - // A new line char is not required for the first line - if nextLine then - content = content + imports.file.NEW_LINE - else - nextLine = true - end if - // FINALLY, we can add the preprocessed source :D - content = content + line - end for - - // Wrong src path? - if content == "" then imports.utils.Print("Unable to read " + (path) + " !") - return content -end function - - -// Oh yes, we prepared the processing of source files, but we didn't even load any file at the moment! -sourcePath = imports.file.AbsolutePath(source,preproc) -// If we pass a dir path, all files in this dir will be loaded -for sourceFile in imports.file.getFiles(sourcePath, false) - check = sourceFile.name.split(".") - found = false - // Useful when building a whole folder, but it's maybe a bit too intrusive? - for i in range(1, check.len-1) - if check[i] == "inc" or check[i] == "temp" then - found = true - print("Temporary or library file found, skipping "+sourceFile.name) - break - end if - end for - if found then continue - - // Imports are based on the file containing the currently read script - // In other words, an "import importing another import" is based on the path of the IMPORT, not the main script - sourceLoc = sourceFile.path[preproc.len+1:] - imported = [] - check = [] - content = InsertCode(sourceFile, true) - - // Adding the imports map if there's at least one import - if imported.len > 0 then content = "imports={}" + imports.file.NEW_LINE + content - // No need to call build if there's no source! - if content.len == 0 then exit("Empty source!") - - // Create a temp source file for build, then either delete it or store it as .temp.src - //targetLoc = sourceLoc[0:sourceLoc.lastIndexOf(".")] + ".temp" - targetLoc = imports.file.FileNameNoExt(sourceLoc) + ".temp" - targetPath = imports.file.AbsolutePath(targetLoc,preproc) - - // If there's already a temp file, delete it - targetFile = comp.File(targetPath) - if targetFile then targetFile.delete - comp.touch(imports.file.GetDir(targetPath),imports.file.GetName(targetPath)) - targetFile = comp.File(targetPath) - - // Build the preprocessed source - print("building "+content.len+" characters for "+sourceLoc) - targetFile.set_content(content) - - result = get_shell.build(targetPath, build) - - // If there's no need to save the temp file, delete the OLD saved file to avoid checking an outdated source - if save then - targetFile.move(imports.file.GetDir(targetPath),imports.file.GetName(targetPath)+".src") - else - targetFile.delete - old = comp.File(targetPath+".src") - if old then old.delete - end if - - // Pfew, we reached the end! - if result.len == 0 then - print("build successful.") - else - print(result) - end if -end for diff --git a/qtglogo.src b/qtglogo.src deleted file mode 100644 index 7b0d3b3ded5ca9d0f059c1445be6918feefd2b60..0000000000000000000000000000000000000000 --- a/qtglogo.src +++ /dev/null @@ -1,89 +0,0 @@ -"#import includes/ui.inc.src" - -"#ifbuild" -if not globals.hasIndex("imports") then - imports = {} - imports.ui = {} - - // Not regular spaces - imports.ui.SPACE = char(160) - - imports.ui.Repeat = function(char, len) - result = "" - for i in range(0,len-1) - result = result + char - end for - return result - end function - - imports.ui.Color = function(color, text) - return "<color="+color+">"+text+"</color>" - end function -end if -"#endif" - -R = @imports.ui.Repeat -J = function(text) - return imports.ui.Color("#f4ae34",text) -end function -B = function(text) - return imports.ui.Color("#1a508d",text) -end function -N = function(text) - return imports.ui.Color("#182d53",text) -end function - -// Bord droit -temp = "&%%%" -D = " "+temp -// Bord gauche -G = temp+"& " -// Taille totale -L = 80 -// Ligne vide -V = R(" ",L-G.len-D.len) - -// Haut du moniteur -print(B(R(" ", 6)+R("&", L-6-5)+R(" ", 5))) -print(B(" "+"&"+R("%", L-2-1)+" ")) -print(B("&"+R("%", 4)+R(" ", L-5-4)+R("%", 4))) - -// Dessus vide -for i in range(1,5) - print(B(G+V+D)) -end for - -// Pour simplifier un peu... -R4=R(" ",4) -R5=R(" ",5) -R17=R(" ",17) - -// Source : univscan.gs -print(B(G+R5+ J(",***,***,***,***, ") +" "+ R17 +" "+R5+ J("***,***,***,***,*") +D)) -print(B(G+R5+ J("*")+"%%%%%%%%%%%%%%"+J("** ") +" "+ R17 +" "+R5+ J("**")+"%%%%%%%%%%%%%"+J("**") +D)) -print(B(G+ J("******")+"%%%%%%%%%%%%%%"+J("*****,") +" "+ J("**************,**") +" "+ J("*******")+"%%%%%%%%%%%%%"+J("**") +D)) -print(B(G+ J("**")+"%%%%%"+J("*, **")+"%%%%"+J("*,") +" "+J("**")+"%%%%%%%%%%%%%"+J("**")+" "+ J("**")+"%%%%%"+J("**") +R(" ",13)+D)) -print(B(G+ J("*,")+"%%%%%"+J("*, **")+"%%%%"+J("*,") +" "+J("******,")+"%%%%"+J("***,**")+" "+ J("**")+"%%%%%"+J("****")+"%%%%"+J("**") +R5+D)) -print(B(G+ J("**")+"%%%%%"+J("*,******** **")+"%%%%"+J("*,") +" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+J("**")+"%%%%%"+J("****")+"%%%%"+J("*******")+D)) -print(B(G+J("**")+"%%%%%"+J("*,,*")+"%%%%"+J("** **")+"%%%%"+J("*,")+" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+J("**")+"%%%%%"+J("*****,**")+"%%%%%"+J("**")+D)) -print(B(G+J("**")+"%%%%%"+J("****")+"%%%%"+J("*****")+"%%%%"+J("*,")+" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+J("**")+"%%%%%"+J("*****,**")+"%%%%%"+J("**")+D)) -print(B(G+ J("*,*,*,")+"*%%%%%%%%%%%%%"+J("*,*,*,") +" "+R5+ J("*,")+"%%%%"+J("*,") +R4+" "+ J(",*,*,*,")+"%%%%%%%%%%%%%"+J(",*") +D)) -print(B(G+R5+ J("**")+"%%%%%%%%%%%%%"+J("*****,") +" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+R5+ J("**")+"%%%%%%%%%%%%%"+J("**") +D)) -print(B(G+R5+ J("****,**********")+"%%%%"+J("*,") +" "+R5+ J("********") +R4+" "+R5+ J("*******,*********") +D)) -print(B(G+R(" ",18)+ J("**####*,") +R(" ", 41)+D)) - -// Dessous vide -for i in range(1,4) - print(B(G+V+D)) -end for - -// Bas du moniteur -print(B("@"+R("%",L-1))) -print(B(R(" ",4)+"&"+R("%",L-5-2)+" ")) -print(R(" ",L)) - -// Support du moniteur -for i in range(1,2) - print(N(R(" ", 31)+R("&",L-31-29)+R(" ",29))) -end for -print(B(R(" ",17)+R("%",L-17-16)+R(" ",16))) \ No newline at end of file diff --git a/scripts/archives/README.md b/scripts/archives/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c78bd8733ba55a69807d861b2ba8602eb06b64e7 --- /dev/null +++ b/scripts/archives/README.md @@ -0,0 +1,26 @@ +0) Go into the folder in which you want to create the qtg repo +1) Copy tools/archive.src into CodeEditor, then as archive.src +2) Execute: +build archive.src /bin +- archive is now available on the system +You can delete archive.src +3) Copy archives/qtg.txt into Notepad, then as REPO_NAME.tar +- archive checks for the .tar extention! +4) Execute: +archive REPO_NAME +- The folder REPO_NAME is now created +You can delete REPO_NAME.tar +5) Go into the repo, then copy archives/libs.txt as (REPO_NAME/)libs.tar +6) Execute: +cd REPO_NAME +archive libs +- The libs are now available on the repo +You can delete libs.tar +7) Copy the libs folder into all folders to make sure the .gs scripts are able to find them +8) Execute: +build preprocess.src /bin +preprocess is now available on the system to process .gs files +9) Execute: +cd tools +preprocess archive.src +This way, you'll have an archive tool which use the libs from the archive :P \ No newline at end of file diff --git a/scripts/archives/libs.txt b/scripts/archives/libs.txt new file mode 100644 index 0000000000000000000000000000000000000000..109fec4719981d16beff649a247250ed7d4706b9 --- /dev/null +++ b/scripts/archives/libs.txt @@ -0,0 +1,1938 @@ +"#archive file.inc.src" +"#ifbuild" +if not globals.hasIndex("imports") then imports = {} +imports.temp = {} +"#endif" +imports.file = {} +"#ifbuild" +file = imports.file +"#endif" + +// Global variable to block load/save operation to avoid unwanted persistant modifications +imports.file.ENABLE_DISK = true + +// Constants +imports.file.NEW_LINE = char(10) +imports.file.NEW_LINE_CHAR = "\"+"n" +imports.file.BOLD = "<b>" +imports.file.BOLD_END = "</b>" + +// Those methods are only used when loading and will be erased by the preprocessor +imports.temp.AddCmd = function(arr, files) + for file in files + arr.push("/bin/"+file) + end for +end function +imports.temp.AddSoft = function(arr, files) + for file in files + arr.push("/usr/bin/"+file+".exe") + end for +end function + +// Generates more constants : the list of good/bad default commands +// Intended to be used when securing a server to know which files to lock/delete +imports.file.USELESS_SHARED = ["/etc/passwd","/server"] +imports.temp.AddCmd(imports.file.USELESS_SHARED,["build","whois","nslookup"]) +imports.temp.AddSoft(imports.file.USELESS_SHARED,["CodeEditor", "Mail"]) +imports.file.USELESS_PROXY = [] +imports.temp.AddCmd(imports.file.USELESS_PROXY,["cd","ls","pwd","ifconfig","iwconfig","iwlist","cat","rm","mv","cp","ftp","mkdir","rmdir","chmod","reboot","scanLan","sudo","useradd","userdel","touch","chown","chgrp","groupadd","groupdel","groups"]) +imports.temp.AddSoft(imports.file.USELESS_PROXY,["Notepad"]) +// Screen management "clear" +// File access "cd", "ls", "pwd", "cat" +// File edition "rm", "mv", "cp", "mkdir", "rmdir", "touch" +// WAN commands "ftp", "ssh" +imports.file.SAFE = [] +imports.temp.AddCmd(imports.file.SAFE,["clear"]) +imports.file.SSH = [] +imports.temp.AddCmd(imports.file.SSH,["ssh"]) +imports.file.ALLOWED_SHARED = [] +imports.temp.AddSoft(imports.file.ALLOWED_SHARED,["Terminal","FileExplorer"]) +imports.file.ALLOWED_SERVICE = [] +imports.temp.AddCmd(imports.file.ALLOWED_SERVICE,["cd","ls","pwd","cat","rm","mv","cp","mkdir","rmdir","touch","ftp"]) +imports.temp.AddSoft(imports.file.ALLOWED_SERVICE,["Notepad"]) +imports.file.MISSING = [] +imports.temp.AddCmd(imports.file.MISSING,["airmon","aireplay","aircrack","nmap","smtp-user-list","decipher","scanlib","scanrouter"]) +imports.temp.AddSoft(imports.file.MISSING,["Map","Manual","AdminMonitor"]) + +// Loads the existing file and save it with extra content +imports.file.append = function(content, path, name, separator=imports.file.NEW_LINE, origin=null) + data = imports.file.load(path, name, origin) + if data then + if separator != null then content = separator + content + content = data + content + end if + imports.file.save(content, path, name, origin) +end function + +// Write the specified content to the disk +imports.file.save = function(content, path, name, origin=null) + if not imports.file.ENABLE_DISK then return + comp = imports.file.GetOrigin(origin) + if name[0] == "/" then + path = "" + else + path = imports.file.AbsolutePath(path) + end if + data = name.split("/") + if data.len > 1 then + for i in range(0, data.len-2) + name = data[i] + if name == "" then continue + comp.create_folder(path, name) + path = path +"/"+ name + end for + end if + name = data[data.len-1] + + path = imports.file.PatchPath(path, origin) + file = comp.File(path+name) + if not file then + comp.touch(path, name) + file = comp.File(path+name) + end if + if not file then print("Could not create " + path + name) + if imports.file.FileAccess(file,"w") then file.set_content(content) +end function + +// Load the content of a file, or NULL if the file is not available +imports.file.load = function(path, name, origin=null) + if not imports.file.ENABLE_DISK then return null + path = imports.file.AbsolutePath(path) + path = imports.file.PatchPath(path, origin) + file = path+name + file = imports.file.GetOrigin(origin).File(file) + if not file or file.is_binary or not imports.file.FileAccess(file,"r") then return null + return file.content +end function + +// For remote files, files intended to be written in the user folders should not be written to the server's users! +imports.file.PatchPath = function(path, origin=null) + if path == null then path = "" + if path.len == 0 or path[-1:] != "/" then path = path + "/" + if origin == null then return path + + path = path[1:] + isUser = imports.utils.starts_with(path, "home/") + isRoot = imports.utils.starts_with(path, "root/") + + // Strips the user-part of the path : /root/XXX => /home/XXX ; /home/USER/XXX => /home/XXX ; /home/XXX => /home/XXX + if isUser or isRoot then + path = path[path.indexOf("/")+1:] // Removes /root/ or /home/ + + // Special case: skipping if home without a user + if isUser and imports.utils.char_count(path, "/") != 1 then path = path[path.indexOf("/")+1:] // Removes the username + + path = "home/"+path + end if + + return "/server/remote/"+path +end function + +// Allows to dynamically handle files on a remote shell (local machine by default) +imports.file.GetOrigin = function(origin) + if origin == null then origin = get_shell + if typeof(origin) == "shell" then origin = origin.host_computer + if typeof(origin) != "computer" then origin = null + return origin +end function + +// If the path is a relative path, append the current_path to it in order to generate a unique file location +imports.file.AbsolutePath = function(path, current=null, origin=null) + if not path then + path = "" + else if path[0] == "/" then + return path + end if + + if current == null then current = imports.file.GetOrigin(origin).current_path + if path then current = current + "/" + path + return current +end function + +// If the path is the one of a file, loads this unique file into an array +// If the path is the one of a directory, loads all the contained files into said array +imports.file.getFiles = function(path, recursive, origin=null) + result = [] + imports.file._getFiles(result, imports.file.GetOrigin(origin).File(path), recursive) + return result +end function +imports.file._getFiles = function(result, file, recursive) + if not file.is_folder then + result.push(file) + return + end if + for child in file.get_files + result.push(child) + end for + if recursive then + for dir in file.get_folders + imports.file._getFiles(result, dir, recursive) + end for + end if +end function + +// Sanity checks a file for allowed permission, return false if one perm is missing + print an error message +imports.file.FileAccess = function(file, perms, shout=true) + if not file then return false + for i in range(0,perms.len-1) + perm = perms[i] + if file.has_permission(perm) then continue + if shout then imports.utils.Print("Error: can't use ('"+perm+"') contents of '"+file.path+"'") + return false + end for + return true +end function + +// Tries deleting a file, but checks that you have the required permissions first (returns false if unallowed) +imports.file.Delete = function(file) + if not imports.file.FileAccess(file) then return false + file.delete() + return true +end function +// Removes the file's name from the path +imports.file.GetDir = function(path) + if typeof(path) == "file" then path = path.path + return path[0:path.lastIndexOf("/")] +end function +// Determines the filename from a String path +imports.file.GetName = function(path) + if typeof(path) == "file" then path = path.path + return path[path.lastIndexOf("/")+1:] +end function + +// Checks that a file is a folder in which files can be added +imports.file.WritableFolder = function(folder) + if not imports.file.FileAccess(folder,"w") then return false + return folder.is_folder +end function + +// Tries to read a file, it it's possible returns all its lines in an array +// Returns an empty array if the file can't be read +imports.file.ReadAllLines = function(file, origin=null) + if typeof(file) == "string" then + index = file.lastIndexOf("/") + path = file[:index] + name = file[index+1:] + content = imports.file.load(path, name, origin) + if content == null then return [] + else + if not file then return [] + if not imports.file.FileAccess(file,"r") then return [] + if file.is_binary then return [] + content = file.content + end if + return content.split(imports.file.NEW_LINE) +end function + +// Creates an object X of version Y in a dir PATH/X/X.Y.ext +imports.file.VersionedFilePath = function(path, filename) + parts = filename.split(".") + name = parts[0] + version = [] + ext = null + if parts.len > 1 then + ext = parts[parts.len-1] + if parts.len > 2 then + for i in Range(1,parts.len-2) + version.push(parts[i]) + end for + end if + end if + return imports.file.VersionedFilePath(path, name, version, ext) +end function +imports.file.VersionedFilePath = function(path, name, version, ext=null) + version = imports.file._DottedString(version) + path = path+name+"/"+version+"/"+name+"."+version + if ext != null then path = path +"."+ imports.file._DottedString(ext) + return path +end function +imports.file._DottedString = function(arr) + if typeof(arr) == "string" then return arr + result = "" + next = false + for item in arr + if next then + result = result + "." + else + next = true + end if + result = result + item + end for + return result +end function + +// Get the file name from a path and remove double extensions +// "Scripts/preprocessor.gs.src" => "preprocessor" +imports.file.FileNameNoExt = function(path) + index = path.lastIndexOf("/") + if index != null then path = path[index+1:] + index = path.indexOf(".") + if index != null then path = path[:index] + return path +end function + +// Generates a String with random characters +// Perfect for a temp file! +imports.file.random = function(len) + chars = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"] + result = "" + for i in range(1,len) + result = result + chars[floor(rnd()*chars.len)] + end for + return result +end function + +// Countermethod of imports.utils.IncludeLib +// Deletes an auto-downloaded lib file +imports.file.RemoveLib = function(includeData) + if typeof(includeData) != "list" then return false + if includeData.len != 2 then return false + path = includeData[1] + if typeof(path) != "string" then return false + if path.len == 0 then return false + return imports.file.Delete(get_shell.host_computer.File(path)) +end function + +"#archive filereaper.inc.src" +"#import libs/utils.src" +"#import libs/file.src" + +"#ifbuild" +if not globals.hasIndex("imports") then imports = {} +imports.temp = {} +"#endif" +imports.filereaper = {} +"#ifbuild" +filereaper = imports.filereaper +"#endif" + +// Missing files are NULL +// Files with not enough access rights are FALSE + +// Part 1 : utility methods + +// FileReaper utility methods to load a child from a File object +imports.filereaper.FindFile = function(origin, children) + if origin == null then return null + // May be available through another user + if not imports.file.FileAccess(origin, "r") then return false + for child in children + if typeof(origin) != "file" then return origin + origin = imports.filereaper._FindFile(origin, child) + end for + return origin +end function +imports.filereaper._FindFile = function(origin, child) + found = null + for file in origin.get_files() + if file.name == child then + found = file + break + end if + end for + if found == null then + for file in origin.get_folders() + if file.name == child then + found = file + break + end if + end for + end if + if found != null then + // May be available through another user + if not imports.file.FileAccess(found, "r") then return false + if not found.is_binary then return found + end if + return null +end function + +// Call either onFoundFile or onMissingFile according to the result of FindFile +imports.filereaper.HandleFile = function(origin, children, onFoundFile, onMissingFile, pars) + file = imports.filereaper.FindFile(origin, children) + if file == false then return + if file == null then + if @onMissingFile != null then onMissingFile(pars) + return + end if + pars.push(file) + if @onFoundFile != null then onFoundFile(pars) +end function + +// Part 2 : file reading + +// Read the lines of creditential files +imports.filereaper.ReadCredsFile = function(file) + creds = [] + for line in imports.file.ReadAllLines(file) + if line.len == 0 then continue + creds.push(line) + end for + return creds +end function +imports.filereaper.UsePasswdFile = function(pars) + state = pars[0] + file = pars[1] + imports.filereaper.LoadPasswdList([state, imports.filereaper.ReadCredsFile(file)]) +end function +imports.filereaper.UseAccFile = function(pars) + state = pars[0] + user = pars[1] + isBank = pars[2] + file = pars[3] + imports.filereaper.LoadAccList([state,user,isBank,imports.filereaper.ReadCredsFile(file)]) +end function + +// Data handling from Filereaper (pars is shorthand for "params") +// Thoses methods should be overriden by the calling scripts as necessary + +imports.filereaper.LoadUserList = function(pars) + state = pars[0] + users = pars[1] + for user in users + imports.filereaper.AddUser([state, user]) + end for +end function + +imports.filereaper.LoadPasswdList = function(pars) + state = pars[0] + creds = pars[1] + + for cred in creds + imports.filereaper.AddPasswd([state,cred]) + end for +end function + +imports.filereaper.LoadAccList = function(pars) + state = pars[0] + user = pars[1] + isBank = pars[2] + creds = pars[3] + for cred in creds + imports.filereaper.LoadAcc([state,user,isBank,cred]) + end for +end function + +imports.temp.X = function(pars) + imports.utils.Print("Error, calling a FileReaper default method without overriding it!") +end function + +// state = pars[0] +// shell = pars[1] +imports.filereaper.UseShell = @imports.temp.X + +// state = pars[0] +// users = pars[1] +imports.filereaper.AddUser = @imports.temp.X + +// state = pars[0] +imports.filereaper.MissingUserList = @imports.temp.X + +// state = pars[0] +// cred = pars[1] +imports.filereaper.AddPasswd = @imports.temp.X + +// state = pars[0] +imports.filereaper.MissingPasswdList = @imports.temp.X + +// state = pars[0] +// user = pars[1] +// isBank = pars[2] +// cred = pars[3] +imports.filereaper.LoadAcc = @imports.temp.X + +// state = pars[0] +// user = pars[1] +// isBank = pars[2] +imports.filereaper.MissingAcc = @imports.temp.X + +// Part 4 : using the exploits + +// "state" would be an object memorizing the state of the process +// when a script doesn't have one, NULL can be passed as long the script-specific methods accept it + +imports.filereaper.exploitShell = function(pars) + imports.filereaper.UseShell(pars) + pars[1] = pars[1].host_computer + imports.filereaper.exploitComp(pars) +end function +imports.filereaper.exploitComp = function(pars) + state = pars[0] + comp = pars[1] + ACC_OK = @imports.filereaper.UseAccFile + ACC_FAIL = @imports.filereaper.MissingAcc + imports.filereaper.HandleFile(comp.File("/etc/passwd"), [], @imports.filereaper.UsePasswdFile, @imports.filereaper.MissingPasswdList, [state]) + imports.filereaper.HandleFile(comp.File("/root/Config/Bank.txt"), [], @ACC_OK, @ACC_FAIL, [state, "root", true]) + imports.filereaper.HandleFile(comp.File("/root/Config/Mail.txt"), [], @ACC_OK, @ACC_FAIL, [state, "root", false]) + imports.filereaper.exploitFile(pars, comp.File("/home/"), false) +end function +imports.filereaper.exploitFile = function(pars, file, targetRoot=true) + state = pars[0] + if file == null or file == false then return file + if targetRoot and file.path != "/" then + if imports.filereaper.exploitFile(pars, file.parent, targetRoot) == true then return true + end if + if not imports.file.FileAccess(file, "r") then return false + + ACC_OK = @imports.filereaper.UseAccFile + ACC_FAIL = @imports.filereaper.MissingAcc + PASS_OK = @imports.filereaper.UsePasswdFile + PASS_FAIL = @imports.filereaper.MissingPasswdList + + if file.path == "/" then + imports.filereaper.HandleFile(file, ["etc","passwd"], @PASS_OK, @PASS_FAIL, [state]) + imports.filereaper.HandleFile(file, ["root","Config","Bank.txt"], @ACC_OK, @ACC_FAIL, [state, "root", true]) + imports.filereaper.HandleFile(file, ["root","Config","Mail.txt"], @ACC_OK, @ACC_FAIL, [state, "root", false]) + + home = imports.filereaper._FindFile(file, ["home"]) + imports.filereaper.HandleFile(home, [], null, @imports.filereaper.MissingUserList, [state]) + if typeof(home) == "file" then imports.filereaper.exploitFile(pars, home, false) + return true + end if + + if imports.utils.starts_with(file.path, "/etc/") then + pasd = null + if file.path == "/etc/" then pasd = file + if file.path == "/etc/passwd" then pasd = imports.filereaper._FindFile(file, ["passwd"]) + imports.filereaper.HandleFile(pasd, [], @PASS_OK, @PASS_FAIL, [state, pasd]) + end if + + if imports.utils.starts_with(file.path, "/home/") then + count = imports.utils.char_count(file.path,"/") + if count == 2 then + for folder in file.getFolders() + imports.filereaper.exploitFile(pars, folder, targetRoot) + end for + else if count == 3 then + imports.filereaper.AddUser(file.name) + end if + else if imports.utils.starts_with(file.path, "/root/") then + count = imports.utils.char_count(file.path,"/")+1 + else + count = 0 //or return + end if + + if count == 4 and file.name == "Config" then + imports.filereaper.HandleFile(file, ["Bank.txt"], @ACC_OK, @ACC_FAIL, [state, file.parent.name, true]) + imports.filereaper.HandleFile(file, ["Mail.txt"], @ACC_OK, @ACC_FAIL, [state, file.parent.name, false]) + else if count == 5 and file.parent.name == "Config" and (file.name == "Bank.txt" or file.name == "Mail.txt") then + imports.filereaper.HandleFile(file, [], @ACC_OK, @ACC_FAIL, [state, file.parent.parent.name, file.name == "Bank.txt"]) + end if +end function + +"#archive passwords.inc.src" +"#import libs/utils.inc.src" +"#import libs/file.inc.src" + +"#ifbuild" +if not globals.hasIndex("imports") then imports = {} +imports.temp = {} +"#endif" +imports.passwords = {} +"#ifbuild" +passwords = imports.passwords +"#endif" + +// Load a password file into a map +imports.passwords.load = function(path, name, origin=null) + result = {} + // 'save (data, "/", FULL_PATH)' works, so load should work too, right? + if path == null then path = "" + if path.len > 0 and path[-1:] == "/" and name.len > 0 and name[0] == "/" then path = imports.utils.rightSlice(path,1) + for line in imports.file.ReadAllLines(path+name, origin) + line = line.split(":"); + result[line[0]] = line[1] + end for + return result +end function + +// Saves a password map into a file +imports.passwords.save = function(data, path, name, origin=null) + imports.file.save(imports.passwords.Export(data), path, name, origin) +end function + +imports.passwords.Export = function(data) + content = [] + for entry in data + content.push(entry.key+":"+entry.value) + end for + return imports.utils.PrintList(content, imports.file.NEW_LINE) +end function + +// Add a new user-hash line into a password map +imports.passwords.AddUser = function(pass, line) + if typeof(line) == "string" then line = line.split(":") + index = line[0] + if imports.utils.SafeMapAccess(pass, index) == line[1] then return false + pass[index] = line[1] + return true +end function + +"#archive qtglogo.inc.src" +"#import libs/ui.inc.src" + +printLogo = function() + R = @imports.ui.Repeat + J = function(text) + return imports.ui.Color("#f4ae34",text) + end function + B = function(text) + return imports.ui.Color("#1a508d",text) + end function + N = function(text) + return imports.ui.Color("#182d53",text) + end function + + // Bord droit + temp = "&%%%" + D = " "+temp + // Bord gauche + G = temp+"& " + // Taille totale + L = 80 + // Ligne vide + V = R(" ",L-G.len-D.len) + + // Haut du moniteur + print(B(R(" ", 6)+R("&", L-6-5)+R(" ", 5))) + print(B(" "+"&"+R("%", L-2-1)+" ")) + print(B("&"+R("%", 4)+R(" ", L-5-4)+R("%", 4))) + + // Dessus vide + for i in range(1,5) + print(B(G+V+D)) + end for + + // Pour simplifier un peu... + R4=R(" ",4) + R5=R(" ",5) + R17=R(" ",17) + + // Source : univscan.gs + print(B(G+R5+ J(",***,***,***,***, ") +" "+ R17 +" "+R5+ J("***,***,***,***,*") +D)) + print(B(G+R5+ J("*")+"%%%%%%%%%%%%%%"+J("** ") +" "+ R17 +" "+R5+ J("**")+"%%%%%%%%%%%%%"+J("**") +D)) + print(B(G+ J("******")+"%%%%%%%%%%%%%%"+J("*****,") +" "+ J("**************,**") +" "+ J("*******")+"%%%%%%%%%%%%%"+J("**") +D)) + print(B(G+ J("**")+"%%%%%"+J("*, **")+"%%%%"+J("*,") +" "+J("**")+"%%%%%%%%%%%%%"+J("**")+" "+ J("**")+"%%%%%"+J("**") +R(" ",13)+D)) + print(B(G+ J("*,")+"%%%%%"+J("*, **")+"%%%%"+J("*,") +" "+J("******,")+"%%%%"+J("***,**")+" "+ J("**")+"%%%%%"+J("****")+"%%%%"+J("**") +R5+D)) + print(B(G+ J("**")+"%%%%%"+J("*,******** **")+"%%%%"+J("*,") +" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+J("**")+"%%%%%"+J("****")+"%%%%"+J("*******")+D)) + print(B(G+J("**")+"%%%%%"+J("*,,*")+"%%%%"+J("** **")+"%%%%"+J("*,")+" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+J("**")+"%%%%%"+J("*****,**")+"%%%%%"+J("**")+D)) + print(B(G+J("**")+"%%%%%"+J("****")+"%%%%"+J("*****")+"%%%%"+J("*,")+" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+J("**")+"%%%%%"+J("*****,**")+"%%%%%"+J("**")+D)) + print(B(G+ J("*,*,*,")+"*%%%%%%%%%%%%%"+J("*,*,*,") +" "+R5+ J("*,")+"%%%%"+J("*,") +R4+" "+ J(",*,*,*,")+"%%%%%%%%%%%%%"+J(",*") +D)) + print(B(G+R5+ J("**")+"%%%%%%%%%%%%%"+J("*****,") +" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+R5+ J("**")+"%%%%%%%%%%%%%"+J("**") +D)) + print(B(G+R5+ J("****,**********")+"%%%%"+J("*,") +" "+R5+ J("********") +R4+" "+R5+ J("*******,*********") +D)) + print(B(G+R(" ",18)+ J("**####*,") +R(" ", 41)+D)) + + // Dessous vide + for i in range(1,4) + print(B(G+V+D)) + end for + + // Bas du moniteur + print(B("@"+R("%",L-1))) + print(B(R(" ",4)+"&"+R("%",L-5-2)+" ")) + print(R(" ",L)) + + // Support du moniteur + for i in range(1,2) + print(N(R(" ", 31)+R("&",L-31-29)+R(" ",29))) + end for + print(B(R(" ",17)+R("%",L-17-16)+R(" ",16))) +end function + +"#archive remote.inc.src" +"#import libs/file.inc.src" + +"#ifbuild" +if not globals.hasIndex("imports") then imports = {} +imports.temp = {} +"#endif" +imports.remote = {} +"#ifbuild" +remote = imports.remote +"#endif" + +imports.remote.cache = {} +imports.remote.LoadFromCache = function(key, shell, user, pass, ip) + if imports.remote.cache.hasIndex(key) then return imports.remote.cache[key] + result = imports.remote.connect(shell, user, pass, ip) + imports.remote.cache[key] = result + return result +end function + +imports.remote.servers = {} +imports.remote.servers.FILES = function() + return imports.remote.LoadFromCache("files", get_shell, "root", "Helby", "220.47.69.119") +end function +imports.remote.servers.PROXY = function() + return imports.remote.LoadFromCache("proxy", get_shell, "root", "Helby", "220.47.69.119") +end function +imports.remote.servers.TEST = function() + return imports.remote.LoadFromCache("test", @imports.remote.servers.PROXY, "root", "Helby", "220.47.69.119") +end function + +imports.remote.LAN = "0.0.0.0" +imports.remote.LOCALHOST = "127.0.0.1" + +// Find the router for the network containing the device +imports.remote.getRouter = function(ip) + ip = imports.remote.directIP(ip) + if not ip then return null + if is_lan_ip(ip) then return get_router() + if not is_valid_ip(ip) then return null + return get_router(ip) +end function + +// Return the lan ip if available or the wan IP +// Special cases : invalid ip (or offline) = NULL +// 127.0.0.1 is this computer +// 0.0.0.0 is the lan ip for the router of this network +imports.remote.directIP = function(ip) + if not get_shell.host_computer.is_network_active then return null + if ip == imports.remote.LOCALHOST then return get_shell.host_computer.lan_ip + if is_lan_ip(ip) then return ip + if ip == imports.remote.LAN then return get_router().local_ip() + if not is_valid_ip(ip) then return null + return ip +end function + +// Returns the default shell service for a given port +imports.remote.getService = function(port) + if port == 22 then return "ssh" + if port == 21 then return "ftp" + return null +end function + +// Connects a given shell to a new shell +// If port is unspecified, use the default ssh port +// If service is unspecified, use the default service for the port +imports.remote.connect = function(shell, user, password, ip, port=null, service=null) + if not port then port = 22 + if typeof(port) == "string" then port = port.to_int + if not service then + service = imports.remote.getService(port) + if not service then return null + end if + return shell.connect_service(ip, port, user, password, service) +end function + +// Every truple of user-pass-ip, chains shells together +// (Intended to be used with data from Map.conf) +imports.remote.map = function(proxies) + shell = get_shell + for proxy in proxies + if shell == null then return null + shell = imports.remote.connect(shell, proxy[0], proxy[1], proxy[2]) + end for + return shell +end function + + +// Checks if a given file already exists at the destination +// If not, said file is uploaded +// imports.remote.download = function(shell, origin, dest, anon=false) +// return imports.remote.transfer(shell, get_shell, origin, dest, anon) +// end function +// imports.remote.upload = function(shell, origin, dest) +// return imports.remote.transfer(get_shell, shell, origin, dest, anon) +// end function +// imports.remote.transfer = function(sourceShell, targetShell, origin, dest, anon=false) +// if anon then +// print("Les transferts anonymes font reset les harddrives suite à un bug") +// print("Lien de l'issue : https://greytracker.org/bugzilla/show_bug.cgi?id=398") +// print("Le mode anonyme est désactivé") +// if not imports.utils.UserPrompt("Acceptez-vous de transférer non-anonymement?") then exit() +// anon = false +// end if + +// if dest[dest.len-1] != "/" then dest = dest + "/" +// origin = imports.file.AbsolutePath(origin, null, sourceShell) + +// comp = sourceShell.host_computer +// src = comp.File(origin) +// if src == null then +// print(origin+" doesn't exist on source server") +// return null +// end if + +// fileName = origin[origin.lastIndexOf("/")+1:] +// destPath = dest+fileName +// if targetShell.host_computer.File(destPath) != null then +// print(destPath+" already exists on target server") +// return null +// end if + +// temp = null +// if anon then +// comp.create_folder("/", "server") +// comp.create_folder("/server/", "temp") +// while true +// Random name until finding an unused one +// fileName = imports.file.random(16) +// if comp.File("/server/temp/"+fileName) != null then continue +// if targetShell.host_computer.File(dest+fileName) != null then continue +// break +// end while + +// DANGER: cette ligne fait remplacer votre harddrive par celui du serveur!? +// src.copy("/server/temp/", fileName) +// temp = comp.File("/server/temp/"+fileName) +// origin = temp.path +// end if + +// result = sourceShell.scp(origin, dest, targetShell) +// if temp != null then temp.delete() +// return targetShell.host_computer.File(destPath) +// end function + +// Downloads a file with scp if it doesn't already exist +// Can also use a different name than the original file : if said name is blank, a random name will be generated +imports.remote.download = function(shell, origin, dest, destName=null) + + // TODO : remove this limiter when the GH issue gets fixed + if destName != null then + print("Les téléchargements renommés font reset les harddrives suite à un bug") + print("Lien de l'issue : https://greytracker.org/bugzilla/show_bug.cgi?id=398") + print("Le renommage est désactivé") + if not imports.utils.UserPrompt("Acceptez-vous de transférer avec le nom d'origine?") then exit() + destName = null + end if + // TODO: temporary limiter ends here + + temp = imports.remote.PreTransfer(origin, dest, shell, get_shell) + origin = temp[0] + dest = temp[1] + + if destName != null then + server = shell.host_computer + if not imports.remote.CheckTempFolder(server) then return "unable to write in /server/temp/" + + src = server.File(origin) + if src == null then return origin+" doesn't exist on source server" + + destName = imports.remote.RandomName(server, get_shell.host_computer, dest, destName) + + // DANGER: cette ligne fait remplacer votre harddrive par celui du serveur!? + src.copy("/server/temp/", destName) + origin = "/server/temp/"+destName + end if + + result = imports.remote.transfer(shell, get_shell, origin, dest) + + if destName != null then src.delete() + + return result +end function + +// Upload a file with scp if it doesn't already exist +// Can also use a different name than the original file : if said name is blank, a random name will be generated +imports.remote.upload = function(shell, origin, dest, destName=null) + + // TODO : remove this limiter when the GH issue gets fixed + if destName != null then + print("Les téléchargements renommés font reset les harddrives suite à un bug") + print("Lien de l'issue : https://greytracker.org/bugzilla/show_bug.cgi?id=398") + print("Le renommage est désactivé") + if not imports.utils.UserPrompt("Acceptez-vous de transférer avec le nom d'origine?") then exit() + destName = null + end if + // TODO: temporary limiter ends here + + temp = imports.remote.PreTransfer(origin, dest, get_shell, shell) + origin = temp[0] + dest = temp[1] + + transferDest = dest + + if destName != null then + server = shell.host_computer + if not imports.remote.CheckTempFolder(server) then return "unable to write in /server/temp/" + + if dest[dest.len-1] != "/" then dest = dest + "/" + // The destination file doesn't need to be available in temp folder + // Also, in this case the server is ALSO the target + destName = imports.remote.RandomName(null, server, "", destName) + + src = server.File(dest+destName) + if src != null then return dest+destName+" already exists on target server" + + // The temporary folder doesn't need to be available in the target folder + folderName = imports.remote.RandomName(server, null, dest, "") + // Creates a temporary folder which will receive the file, no matter what its name is + server.create_folder("/server/temp/", folderName) + transferDest = "/server/temp/"+folderName + end if + + result = imports.remote.transfer(get_shell, shell, origin, transferDest) + + if destName != null then + // DANGER: cette ligne fait remplacer votre harddrive par celui du serveur!? + if result then result.move(dest,destName) + // Delete the temporary folder + server.File(transferDest).delete() + end if + + return result +end function + +// Run a scp command after performing some sanity checks +// SHOULD NOT BE USED DIRECTLY, use the upload and download methods +// Returns : the new file, or NULL +imports.remote.transfer = function(sourceShell, targetShell, origin, dest) + src = sourceShell.host_computer.File(origin) + if src == null then return origin+" doesn't exist on source server" + + fileName = origin[origin.lastIndexOf("/")+1:] + + destPath = dest+fileName + comp = targetShell.host_computer + + if comp.File(destPath) != null then return destPath+" already exists on target server" + + result = sourceShell.scp(origin, dest, targetShell) + if result != true then return result + return comp.File(destPath) +end function + +imports.remote.PreTransfer = function(origin, dest, originShell, destShell) + if dest[dest.len-1] != "/" then dest = dest + "/" + origin = imports.file.AbsolutePath(origin, null, originShell) + dest = imports.file.AbsolutePath(dest, null, destShell) + return [origin, dest] +end function + +// Returns false if /server/temp/ is not usable +imports.remote.CheckTempFolder = function(comp) + folder = comp.File("/server/temp") + if folder != null then + return imports.file.WritableFolder(folder) + end if + folder = comp.File("/server/") + if folder != null then + if not imports.file.WritableFolder(folder) then return false + comp.create_folder("/server/", "temp") + return true + end if + folder = comp.File("/") + if not imports.file.WritableFolder(folder) then return false + comp.create_folder("/", "server") + comp.create_folder("/server/", "temp") + return true +end function + +// Generates a random name not-already-used by a file +imports.remote.RandomName = function(serverComp, targetComp, destPath, name) + if name != "" then return name + while true + name = imports.file.random(16) + if serverComp != null and serverComp.File("/server/temp/"+name) != null then continue + if targetComp != null and targetComp.File(destPath+name) != null then continue + return name + end while +end function + +"#archive ui.inc.src" +"#import libs/utils.inc.src" +"#import libs/file.inc.src" + +"#ifbuild" +if not globals.hasIndex("imports") then imports = {} +imports.temp = {} +"#endif" +imports.ui = {} +"#ifbuild" +ui = imports.ui +"#endif" + +// Changes a two-dimensional array into format_column styled text +imports.ui.FormatMatrix = function(matrix, padding=null) + if padding == null then padding = imports.ui.PADDING + text = "" + + nextLine = false + for line in matrix + if nextLine then text = text + imports.file.NEW_LINE else nextLine = true + nextCell = false + text = text + imports.utils.PrintList(line, padding) + end for + + return text +end function + +// Not regular spaces +imports.ui.SPACE = char(160) +imports.ui.PADDING = imports.ui.SPACE+imports.ui.SPACE + +// Changes a character +imports.ui.ReplacePos = function(text, pos, char) + return imports.utils.leftSlice(cell,pos) + char + imports.utils.rightSlice(cell,pos+1) +end function + +// Changes a two-dimensional array into the DATA from format_column +// Spaces are treated as normal text data, space padding is only inserted between the cells of the matrix +imports.ui.FormattedCols = function(matrix) + indexes = [] + + for line in matrix + indexData = [];indexes.push(indexData) + for i in range(0,line.len-1) + cell = line[i] + if cell == null then cell = "" + if typeof(cell) == "number" then cell = cell.str + if typeof(cell) != "string" then cell = "" + index = [];indexData.push(index) + for j in range(0,cell.len-1) + if cell[j] != " " then continue + index.push(j) + cell = imports.ui.ReplacePos(cell, j, "@") + end for + line[i] = cell + end for + end for + + data = format_columns(imports.ui.FormatMatrix(matrix, " ")).split(imports.file.NEW_LINE) + matrix = [] + + for line in data + cells = [];matrix.push(cells) + lastCut = 0 + inCell = true + for i in range(0,line.len-1) + char = line[i] + if char == imports.ui.SPACE then + inCell = false + continue + end if + if inCell then continue + cell = line[lastCut:i-imports.ui.PADDING.len] + lastCut = i + cells.push(cell) + inCell = true + end for + cells.push(line[lastCut:]) + end for + + for pos in range(0,matrix.len-1) + line = matrix[pos] + indexData = indexes[pos] + for i in range(0,line.len-1) + cell = line[i] + index = indexData[i] + for j in index + cell = imports.ui.ReplacePos(cell, j, " ") + end for + line[i] = cell + end for + end for + + return matrix +end function + +// Repeats a given character several times +imports.ui.Repeat = function(char, len) + result = "" + for i in range(0,len-1) + result = result + char + end for + return result +end function + +// Changes a text into terminal-colored text data +imports.ui.Color = function(color, text) + return "<color="+color+">"+text+"</color>" +end function + +imports.ui.BOLD = "<b>" +imports.ui.BOLD_END = "</b>" + +// Changes a text into terminal-bolded text data +imports.ui.Bold = function(text) + return imports.ui.BOLD+text+imports.ui.BOLD_END +end function + +"#archive utils.inc.src" +// Only used for ONE method, choice left to the main script +//"#import libs/dict.inc.src" +//"#import libs/remote.inc.src" + +"#ifbuild" +if not globals.hasIndex("imports") then imports = {} +imports.temp = {} +"#endif" +imports.utils = {} +"#ifbuild" +utils = imports.utils +"#endif" + +imports.utils.DynLibPath = function(libName) + data = imports.utils._DynLibPath("/lib", libName) + if data then return data + data = imports.utils._DynLibPath(get_shell.host_computer.current_path, libName) + if data then return data + return imports.utils._DynLibPath(imports.utils.ParentPath(), libName) +end function +imports.utils._DynLibPath = function(path, libName) + path = path + "/" + libName + lib = include_lib(path) + if not lib then return null + return [lib, path] +end function + +imports.utils.IncludeLib = function(libName, mandatory=true, shellCall=false) + // Support for simpler scripts not intended for autodownloading + legacyMode = (shellCall == false) + if legacyMode then shellCall = null + result = imports.utils._IncludeLib(libName, mandatory, shellCall) + if legacyMode then return result[0] + return result +end function +imports.utils._IncludeLib = function(libName, mandatory, shellCall) + lib = imports.utils.DynLibPath(libName)[0] + NULL = null + if lib or not mandatory then return [lib, NULL] + MSG = "Can't find " + libName + " library in the /lib path or the current folder" + if @shellCall == null then exit("Error: "+MSG) + print("Launching auto-download : "+MSG) + remote = imports.utils.IsImported("remote") + if not remote then exit("Unable to auto-download, remote.inc library is missing!") + libFile = remote.download(shellCall(), "/server/install/lib/"+libName, imports.utils.ParentPath(), "") + path = libFile.path + lib = include_lib(path) + return [lib, path] +end function + +imports.utils.ParentPath = function() + return get_shell.host_computer.File(program_path).parent.path +end function + +imports.utils.GetProgName = function() + return program_path.split("/")[-1] +end function +imports.utils.IsRoot = function() + return active_user == "root" +end function + +imports.utils.Print = function(reason) + print(imports.utils.GetProgName()+": "+reason) +end function +imports.utils.Debug = function(reason) + // print(imports.utils.GetProgName()+" [DEBUG] : "+reason) +end function +imports.utils.Exit = function(reason) + exit(imports.utils.GetProgName()+": "+reason) +end function + +imports.utils.ParamLength = function(params) + length = 0 + for param in params + if param[0] != "-" then length = length + 1 + end for + return length +end function +imports.utils.GetParam = function(params, index) + i = 0 + for param in params + if param[0] == "-" then continue + if (i == index) then return param + i = i+1 + end for + return null +end function +imports.utils.HasFlag = function(params, short, long) + for param in params + if param[0:1] == "--" then + if slice(param,2) == long then return true + else if param[0] == "-" then + if slice(param,1) == short then return true + end if + end for + return false +end function + +imports.utils.SafeMapAccess = function(map, index, defaultValue=null) + if index == null then + imports.utils.Print("WARNING: Called SafeMapAccess with a null index") + return defaultValue + end if + if not map.hasIndex(index) then return defaultValue + return map[index] +end function +imports.utils.FirstMapWrite = function(map, index, value) + if index == null then imports.utils.Exit("ERROR: Tried to call FirstMapWrite with a null index") + if not map.hasIndex(index) then map[index] = value + return map[index] +end function +imports.utils.PrintList = function(list, separator=imports.file.NEW_LINE) + result = "" + nextLine = false + for item in list + if nextLine then result = result + separator else nextLine = true + result = result + item + end for + return result +end function + +imports.utils.Pause = function() + user_input("Press ENTER to continue") +end function +imports.utils.UserPrompt = function(question) + while true + answer = lower(user_input(question + " (y/n)")); + if answer == "y" then + return true + else if answer == "n" then + return false + else + print("Only 'y' and 'n' are allowed") + end if + end while +end function +imports.utils.Choice = function(choices, reason=null) + len = choices.len + if len < 2 then return len-1 + if reason != null then print("Please choose "+reason) + while true + for index in range(0,len-1) + print(index+1 + ":" + choices[index]) + end for + input = user_input("Enter the number to select then press ENTER: ") + input = input.trim().to_int - 1 + if input >= 0 and input < len then return input + print("Not a recognized selection") + end while + return -1 // Should never happen +end function + +imports.utils.HASH_SIZE = 32 +imports.utils.GetSafePassword = function(userPass, cryptools, prompt=true) + if userPass.indexOf(":") != null then + data = userPass.split(":") + username = data[0] + password = data[1] + else + username = "" + password = userPass + end if + + if cryptools and password.len == imports.utils.HASH_SIZE then password = imports.utils._decipher(username, password, cryptools, prompt) + + return [username,password] +end function +imports.utils._decipher = function(user, hash, cryptools, prompt=true) + dict = imports.utils.IsImported("dict") + + if dict then + password = dict.decrypt(hash, user, null) // No cryptool + if not imports.utils.is_empty(password) then return password + end if + + if imports.utils.is_empty(user) then return hash + + print("Decipher required for "+hash) + if prompt and not imports.utils.UserPrompt("Do you want to decipher the password of "+user+"?") then + print("Cancelled deciphering of "+user+":"+hash) + return "" + end if + + password = cryptools.decipher(user, hash) + if dict and not imports.utils.is_empty(password) then dict.addPass(hash, password) + return password +end function +imports.utils.IsImported = function(name) + if not globals.hasIndex("imports") then return null + if not imports.hasIndex(name) then return null + return imports[name] +end function + +imports.utils.char_count = function(str, char) + if str == null then return 0 + count = 0 + for car in str + if car == char then count = count + 1 + end for + return count +end function +imports.utils.starts_with = function(str, part) + if str == null then return false + if part == null then return false + if str.len < part.len then return false + return str[:part.len] == part +end function +imports.utils.is_empty = function(str) + if str == null then return true + return str.len == 0 +end function +imports.utils.slice = function(str,start,stop) + if start == stop then return "" + return str[start:stop] +end function +imports.utils.leftSlice = function(str,stop) + return imports.utils.slice(str, 0, stop) +end function +imports.utils.rightSlice = function(str,start) + return imports.utils.slice(str, start, str.len) +end function + +imports.utils.SelfDestruct = function(prompt=true) + if prompt and not imports.utils.UserPrompt("Do you wish to delete the binary file from this program?") then return + get_shell.host_computer.File(program_path).delete +end function + +"#archive versioning.inc.src" +"#import libs/utils.inc.src" + +"#ifbuild" +if not globals.hasIndex("imports") then imports = {} +imports.temp = {} +"#endif" +imports.versioning = {} +"#ifbuild" +versioning = imports.versioning +"#endif" + +// Constants returned when comparing +imports.versioning.HIGHER = 1 +imports.versioning.EQUALS = 0 +imports.versioning.LOWER = -1 + +// Make sure a number is an int +imports.versioning.to_number = function(number) + if typeof(number) == "number" then return number + number = number.to_int + if typeof(number) == "string" then return null + return number +end function + +// Convert a version string into a number array +imports.versioning.read = function(version) + if typeof(version) == "number" then + data = [version] + else + data = version.split(".") + end if + + len = data.len + if len == 0 then return null + + deleting = true + for i in range(len-1, 0) + item = imports.versioning.to_number(data[i]) + if item == null or item < 0 then + imports.utils.Print(version+" is not a valid version format") + return null + end if + // Don't count trailing zeroes + if deleting and item == 0 and i > 0 then + data.remove(i) + continue + end if + deleting = false + data[i] = item + end for + + return data +end function + +// Checks which of two version strings is the latest +imports.versioning.compare = function(verA, verB) + verA = imports.versioning.read(verA) + verB = imports.versioning.read(verB) + if not verA and not verB then return imports.versioning.EQUALS + if not verB then return imports.versioning.HIGHER + if not verA then return imports.versioning.LOWER + + // By default, assume A being the longer version number (we'll handle exact equality later) + result = 1 + // If A is inferior, reverts the planned "A is higher" result + if verA.len < verB.len then + result = -1 + // Permute the two arrays + temp = verA + verA = verB + verB = temp + end if + // From now on verA is the longest (or equal sized...) + + for i in range(0, verB.len-1) + if verA[i] == verB[i] then continue + // If A is inferior, revert the planned result + if verA[i] < verB[i] then result = 0 - result + return result + end for + + // In case of draw, the longuest is the greater + if verA.len == verB.len then result = 0 + return result +end function + +"#archive models/jsonparser.gs" +// JSON (JavaScript Object Notation) is a common format for exchanging data +// between different computers or programs. See: https://json.org/ +// The data types in JSON are number, string, object, and array, which +// correspond very neatly to MiniScript's number, string, map, and list. +// +// This module provides code to read and write data in JSON format, as well +// as a couple of utility functions for escaping/unescaping strings and +// converting numbers to/from hexadecimal. + +// Changes by Tom de QTG to adapt the parser to GreyScript + +// parse: convert a JSON string into a MiniScript value (which could +// include a list or map of other values). This is the main entry point +// for reading JSON data and converting it to native form. +// Example: parse("42") // returns 42 +parse = function(jsonString) + p = new Parser + return p.parse(jsonString) +end function + +// toJSON: convert a MiniScript value to its JSON representation. +// Example: toJSON(42) // returns "42" +// +// Parameters: +// value: MiniScript value to convert +// compact: if true, omit all unnecessary whitespace +// indent: amount to indent if multiple lines are needed +toJSON = function(value, compact=false, indent=0) + if typeof(@value) == "function" then return """<function>""" + if value == null then return "null" + if typeof(value) == "number" then return str(value) + if typeof(value) == "string" then return """" + escape(value) + """" + if typeof(value) == "list" then return _listToJSON(value, compact, indent) + if typeof(value) == "map" then return _mapToJSON(value, compact, indent) + //To Implem + if typeof(value) == "router" then return _routerToJSON(value, compact, indent) + if typeof(value) == "computer" then return _computerToJSON(value, compact, indent) + if typeof(value) == "port" then return _portToJSON(value, compact, indent) + if typeof(value) == "file" then return _fileToJSON(value, compact, indent) +end function + +// hexToInt: convert a string containing a hexadecimal number. +// Supports both uppercase and lowercase for digits A-F. +// Example: hexToInt("002A") // returns 42 +hexToInt = function(s) + result = 0 + for c in s + result = result * 16 + _hexDigitMap[c] + end for + return result +end function + +// escape: find certain characters (tab, newline, etc.) in the given string, +// and represent them with backslash sequences. +// Example: escape(char(c)) // returns "\t" +escape = function(s) + for entry in {"\":"\\", """":"\""", char(8):"\b", char(9):"\t", char(10):"\"+"n", char(12):"\f", char(13):"\r"} + s = s.replace(entry.key, entry.value) + end for + return s +end function + +// unescape: replace backslash sequences in the given string. +// Example: unescape("\t") // returns char(9) +unescape = function(s) + result = [] + i = 0 + maxi = s.len + while i < maxi + di = 1 + if s[i] == "\" then + di = 2 + c = s[i+1] + if c == "b" then + result.push(char(8)) + else if c == "t" then + result.push(char(9)) + else if c == "n" then + result.push(char(10)) + else if c == "f" then + result.push(char(12)) + else if c == "r" then + result.push(char(13)) + else if c == "u" then + // Unicode code point (must always be 4 digits) + hex = s[i+2:i+6] + result.push(char(hexToInt(hex))) + di = 6 + else + result.push(c) + end if + else + result.push(s[i]) + end if + i = i + di + end while + return result.join("") +end function + +//---------------------------------------------------------------------- +// Stuff below is internal implementation; +// most users don't need to poke around here. + +// Parsing JSON + +Parser = {} +Parser.source = "" +Parser._sourceLen = 0 +Parser._p = 0 // index of next character to consume in source + +Parser.init = function(source) + self.source = source + self._sourceLen = source.len +end function + +Parser.parse = function(source=null) + if source != null then + self.init(source) + end if + self._p = 0 + return self._parseElement +end function + +whitespace = " " + char(9) + char(10) + char(13) +Parser._skipWhitespace = function() + while self._p < self._sourceLen + c = self.source[self._p] + if whitespace.indexOf(c) == null then break + self._p = self._p + 1 + end while +end function + +Parser._parseElement = function() + return self._parseValue // for now! +end function + +Parser._parseValue = function() + self._skipWhitespace + c = self.source[self._p] + if c == """" then return self._parseString + if "0123456789-.".indexOf(c) != null then return self._parseNumber + if c == "[" then return self._parseList + if c == "{" then return self._parseMap + if c == "t" and self.source[self._p:self._p+4] == "true" then + self._p = self._p + 4 + return true + end if + if c == "f" and self.source[self._p:self._p+5] == "false" then + self._p = self._p + 5 + return false + end if + if c == "n" and self.source[self._p:self._p+4] == "null" then + self._p = self._p + 4 + return null + end if +end function + +Parser._parseList = function() + self._p = self._p + 1 // skip "[" + self._skipWhitespace + result = [] + while self._p < self._sourceLen + c = self.source[self._p] + if c == "]" then break + result.push(self._parseElement) + self._skipWhitespace + // after an element, we should have either a comma or a ']' + c = self.source[self._p] + if c == "," then + self._p = self._p + 1 + self._skipWhitespace + end if + end while + self._p = self._p + 1 + return result +end function + +Parser._parseMap = function() + self._p = self._p + 1 // skip "{" + self._skipWhitespace + result = {} + while self._p < self._sourceLen + // grab the key (must be a string) + c = self.source[self._p] + if c == "}" then + break + end if + if c != """" then + print("JSON error: object member key must be a string literal") // ToDo: better error handling! + print("Error at position " + self._p + ": " + self.source[self._p-60 : self._p+60]) + return null + end if + key = self._parseString + self._skipWhitespace + + // next token must be a colon + if self.source[self._p] != ":" then + print("JSON error: colon expected") + print("Error at position " + self._p + ": " + self.source[self._p-60 : self._p+60]) + return null + end if + self._p = self._p + 1 + self._skipWhitespace + + // grab the value (could be anything) + value = self._parseElement + result[key] = value + self._skipWhitespace + + // after a a key/value pair, we should have either a comma or a '}' + c = self.source[self._p] + if c == "," then + self._p = self._p + 1 + self._skipWhitespace + end if + end while + self._p = self._p + 1 + return result +end function + +// Get a string literal from the source. Advance to the next +// character after the closing quote. +Parser._parseString = function() + self._p = self._p + 1 + startPos = self._p + anyEscape = false + while self._p < self._sourceLen + c = self.source[self._p] + self._p = self._p + 1 + if c == """" then break + if c == "\" then + anyEscape = true + self._p = self._p + 1 + end if + end while + result = self.source[startPos : self._p-1] + if result == null then result = "" + if anyEscape then result = unescape(result) + return result +end function + +// Get a numeric literal from the source. Advance to the next +// character after the number. +Parser._parseNumber = function() + startPos = self._p + while self._p < self._sourceLen + c = self.source[self._p] + // Note that we are rather permissive here, consuming things like + // 1-2e5+4E7, which is not valid JSON. But we're not trying to be + // a JSON validator; we're just trying to grok valid JSON as quickly + // as we can. + if "0123456789+-.eE".indexOf(c) == null then break + self._p = self._p + 1 + end while + // In original source, operation was + //result = val(self.source[startPos : self._p]) + // However, it had the side-effect of using the "val" variable from the calling script! + result = self.source[startPos : self._p].val + return result +end function + +// Generating JSON + +_listToJSON = function(lst, compact, indent) + ws = (_eol + " "*(indent+1)) * (not compact) + parts = ["[", ws] + first = true + for item in lst + if not first then + parts.push(",") + parts.push(ws) + end if + parts.push(toJSON(item, compact, indent+1)) + first = false + end for + if not compact then parts.push(_eol + " " * indent) + parts.push("]") + return join(parts, "") +end function + +_mapToJSON = function(lst, compact, indent) + ws = (_eol + " "*(indent+1)) * (not compact) + parts = ["{", ws] + first = true + for kv in lst + if not first then + parts.push(",") + parts.push(ws) + end if + parts.push(toJSON(str(kv.key))) + parts.push(":") + if not compact then parts.push(" ") + parts.push(toJSON(@kv.value, compact, indent+1)) + first = false + end for + if not compact then parts.push(_eol + " " * indent) + parts.push("}") + return join(parts, "") +end function + +_routerToJSON = function(router, compact, indent) + return "Not implemented yet." +end function + +_computerToJSON = function(computer, compact, indent) + return "Not implemented yet." +end function + +_portToJSON = function(port, compact, indent) + return "Not implemented yet." +end function + +_fileToJSON = function(file, compact, indent) + return "Not implemented yet." +end function + +// General utility data structures + +_eol = char(10) +_hexDigitMap = {} +for i in range(0,15) + if i < 10 then + _hexDigitMap[str(i)] = i + else + _hexDigitMap[char(55+i)] = i // (lowercase hex digit) + _hexDigitMap[char(87+i)] = i // (uppercase hex digit) + end if +end for + +"#UnitTests (run when you load & run this script directly)." +if locals == globals then + + errorCount = 0 + assertEqual = function(actual, expected) + if actual != expected then + print("Unit test failure: expected " + expected + ", got " + actual) + outer.errorCount = errorCount + 1 + end if + end function + assertEqualEither = function(actual, expected, expected2) + if actual != expected and actual != expected2 then + print("Unit test failure: expected " + expected + ", got " + actual) + outer.errorCount = errorCount + 1 + end if + end function + + p = new Parser + p.init(" true ") + assertEqual(p.parse, "true") + + assertEqual(parse("-123.45"), -123.45) + assertEqual(parse(char(13) + "42"), 42) + assertEqual(parse(".5"), 0.5) + + assertEqual(parse("""\tHello, \""Bob\""."""), char(9) + "Hello, ""Bob"".") + assertEqual(parse("""\u002F"""), "/") + + assertEqual(parse("[1, 2 , 3]"), [1, 2, 3]) + assertEqual(parse("[ ""hey"", true, [0]]"), ["hey", true, [0]]) + + assertEqual(parse("{""hey"": ""ho"", ""9"" : 81}"), {"hey":"ho", "9":81}) + + // And here's a longer example... remember, quotes doubled only + // to make them valid MiniScript string literals... + data = parse("{""widget"": {" + " ""debug"": ""on""," + " ""window"": {" + " ""title"": ""Sample Konfabulator Widget""," + " ""name"": ""main_window""," + " ""visible"": false," + " ""width"": 500," + " ""height"": 300," + " ""left"": -123.456," + " ""top"": 234.567," + " }," + " ""image"": { " + " ""src"": ""Images\\Sun.png""," + " ""name"": ""sun1""," + " ""hOffset"": 250," + " ""vOffset"": 250," + " ""alignment"": ""center""" + " }," + " ""text"": {" + " ""data"": ""Click Here""," + " ""size"": 36," + " ""style"": ""bold""," + " ""name"": ""text1""," + " ""hOffset"": 250," + " ""vOffset"": 100," + " ""alignment"": ""center""," + " ""onMouseUp"": ""sun1.opacity = (sun1.opacity / 100) * 90;""" + " }}}") + assertEqual(data.widget.debug, "on") + assertEqual(data.widget.window.width, 500) + assertEqual(data.widget.image.src, "Images\Sun.png") + assertEqual(data.widget.text.size, 36) + + ObjectTest = {} + ObjectTest.paramNumber = 42 + ObjectTest.paramString = "Potatoe" + ObjectTest.paramList = [1, 2, 3] + ObjectTest.paramMap = {"one":1, "two":2} + ObjectTest.function1 = function () + return "I am a function" + end function + assertEqual(toJSON(42), "42") + assertEqual(toJSON(char(9)), """\t""") + assertEqual(toJSON([1, 2, 3], true), "[1,2,3]") + assertEqual(toJSON(ObjectTest, true), "{""paramNumber"":42,""paramString"":""Potatoe"",""paramList"":[1,2,3],""paramMap"":{""one"":1,""two"":2},""function1"":""<function>""}") + // Maps are a bit tricky to unit-test, since the order in which the keys appear + // is undefined. But here we go: + assertEqualEither(toJSON({"one":1, "two":2}, true), "{""one"":1,""two"":2}", "{""two"":2,""one"":1}") + + if errorCount == 0 then + print("All tests passed. Huzzah!") + else + print(errorCount + " error" + "s" * (errorCount!=1) + " found.") + end if + +end if + +"#archive models/utils.gs" +// Check mx +metaxploit = include_lib("/lib/metaxploit.so") +if not metaxploit then + currentPath = get_shell.host_computer.current_path + metaxploit = include_lib(currentPath + "/metaxploit.so") +end if +if not metaxploit then exit("Error: Can't find metaxploit library in the /lib path or the current folder") + +crypto = include_lib("/lib/crypto.so") +if not crypto then + currentPath = get_shell.host_computer.current_path + crypto = include_lib(currentPath + "/crypto.so") +end if +if not crypto then exit("Error: Can't find crypto.so library in the /lib path or the current folder") + +// Get file on the local computer +// string filePath +// string fileName +// @return File|null +getFile = function(filePath, fileName) + myshell = get_shell + file = myshell.host_computer.File(filePath + fileName) + return file +end function + +decipherUserPassword = function(userPass) + if userPass.len != 2 then exit("decipher: wrong syntax") + password = crypto.decipher(userPass[0], userPass[1]) + return password +end function + +// Get distant lib +// string address +// Port port +// @return metaLib|null +getLib = function(address, port) + res = null + net_session = metaxploit.net_use( address, port.port_number ) + if net_session then + res = net_session.dump_lib + end if + return res +end function + +getRouter = function(address) + res = null + net_session = metaxploit.net_use(address) + if net_session then + res = net_session.dump_lib + end if + return res +end function + +"#UnitTests" +myshell = get_shell +libDirectory = myshell.host_computer.File("/lib/") + +for file in libDirectory.get_files + lib = metaxploit.load(file.path) + print (format_columns(lib.lib_name + " " + lib.version)) +end for + +"#archive models/vuln.gs" +//Defining classes +//Vulnerability +Vulnerability = {} +// Attributes +Vulnerability.portNumber = "" +Vulnerability.portStatus = "" +Vulnerability.portProtocol = "" +Vulnerability.libName = "" +Vulnerability.libVersion = "" +Vulnerability.LanIpAddress = "" +Vulnerability.ExternalIpAddress = "" +Vulnerability.vulnMemoryAddress = "" +Vulnerability.vulnType = "" //Buffer overflow +Vulnerability.vulnMethod = "" // copy string +Vulnerability.vulnUnsecValue = "" +Vulnerability.vulnOption = "" +Vulnerability.vulnConditions = [] +// Methods +Vulnerability._toString = function () + res = self.LanIpAddress + ":" + self.portNumber + ":" + self.portProtocol + ":" + self.libVersion + ":" + self.vulnMemoryAddress + ":" + self.vulnType + ":" + self.vulnMethod + ":" + self.vulnUnsecValue + ":" + self.vulnOption + conditionIndex = 0 + for cond in self.vulnConditions + conditionIndex = conditionIndex + 1 + res = res + char(10) + "Condition "+ conditionIndex +": " + cond + end for + return res +end function + +Vulnerability._getFilePath = function () + return globals.vulnerabilitiesDirectoryName + self.ExternalIpAddress + "/" +end function + +Vulnerability._toFile = function () + myshell = get_shell + + fileName = self.libName + "_" + self.libVersion.replace(".","_") + myshell.host_computer.touch(self._getFilePath, fileName) + + vulnerabilityFile = myshell.host_computer.File(self._getFilePath + fileName) + vulnerabilityFile.set_content(vulnerabilityFile.content + char(10) + self._toString) + return vulnerabilityFile +end function + +Vulnerability._fromFile = function () + //ToDo +end function + +Vulnerability._setExternalIpAddress = function(ipAddress) + self.vulnConditions = [] + self.ExternalIpAddress = ipAddress + myshell = get_shell + myshell.host_computer.create_folder( globals.vulnerabilitiesDirectoryName, self.ExternalIpAddress) +end function + +Vulnerability._setLibName = function(libName) + self.libName = libName +end function + +Vulnerability._setPortInfos = function(port) + if (is_valid_ip(self.ExternalIpAddress) == false) then + exit("<color=#FF0000FF>External Ip Address should be set before port.</color>") + end if + isLanIp = is_lan_ip(self.ExternalIpAddress) + if (port != null and port != "router") then + self.portNumber = port.port_number + serviceInfos = globals.router.port_info(port).split(" ") + self.portProtocol = serviceInfos[0] + self.libVersion = serviceInfos[1] + self.LanIpAddress = port.get_lan_ip + self.portStatus = "open" + if(port.is_closed and not isLanIp) then + self.portStatus = "closed" + end if + else if (port == "router") then + routerLib = getRouter(self.ExternalIpAddress) + self.portNumber = 0 + serviceInfos = routerLib.lib_name + self.portProtocol = "Kernel" + self.libVersion = routerLib.version + self.LanIpAddress = globals.router.local_ip + self.portStatus = "N/A" + end if +end function + +Vulnerability._setVuln = function(memAddress, vulnText) + self.vulnMemoryAddress = memAddress + //print("Debug: text: " + vulnText) + vulnTextLines = vulnText.split("###") + //print("Debug: textafter split: " + vulnTextLines) + for line in vulnTextLines + if line.indexOf("Unsafe check") == 0 then + //print("Debug: lineToPush1: " + line) + self._parseVulnDesc(line) + else if line.indexOf("* ") == 0 then + lineToPush = line.remove("* ").remove(".") + //print("Debug: lineToPush2: " + lineToPush) + self.vulnConditions.push(lineToPush) + else + //print("unused line: " + line) + end if + end for +end function + +//private +Vulnerability._parseVulnDesc = function(vulnDesc) + vulnDesc = vulnDesc.remove("Unsafe check: ") + vulnDescArray = vulnDesc.split(". ") + self.vulnType = vulnDescArray[1].remove(".") + lastSpaceIndex = vulnDescArray[0].lastIndexOf(" ") + self.vulnMethod = vulnDescArray[0][0:lastSpaceIndex] + self.vulnUnsecValue = slice(vulnDescArray[0],lastSpaceIndex+1).remove("<b>").remove("</b>") +end function + +//END classes definitions diff --git a/scripts/archives/qtg.txt b/scripts/archives/qtg.txt new file mode 100644 index 0000000000000000000000000000000000000000..c0242a02bb17288dea10e75e1f1f668ed3f424bc --- /dev/null +++ b/scripts/archives/qtg.txt @@ -0,0 +1,1125 @@ +"#archive preprocess.src" +if params.len < 1 or params[0] == "-h" or params[0] == "--help" then exit("<b>Usage: "+program_path.split("/")[-1]+" [file to preprocess]</b>") + +fileName = params[0] + +alreadyImportedFiles = [] + +process = function(fileToPreProcess, preProcessedFile) + skip = false + fileLines = fileToPreProcess.content.split(char(10)) + for line in fileLines + if line.indexOf("""#import") == 0 then + fileToImportName = line.split(" ")[1].remove("""") + if (alreadyImportedFiles.indexOf(fileToImportName) == null) then + alreadyImportedFiles.push(fileToImportName) + fileToImport = myshell.host_computer.File(fileToImportName) + importedFile = process(fileToImport, preProcessedFile) + else + print("Skipping " + fileToImportName + ": already imported") + end if + else if (line.indexOf("""#UnitTests") == 0) then + // break not working here "Compiler Error: 'else' skips expected 'break'" - bugged I think + skip = true + else + if (skip == false) then + preProcessedFile.set_content(preProcessedFile.content + "\n" + line) + end if + end if + end for + return preProcessedFile +end function + +myshell = get_shell +mycomputer = myshell.host_computer +fileToPreProcess = mycomputer.File(fileName) +preProcessedFileName = fileName.split(".")[0] + "_pp.src" + +touched = mycomputer.touch(mycomputer.current_path,preProcessedFileName) +if touched != 1 then + if touched == "The file already exists" then + preProcessedFile = mycomputer.File(preProcessedFileName) + preProcessedFile.set_content("") + else + exit("failed to touch: " + touched) + end if +else + preProcessedFile = mycomputer.File(preProcessedFileName) +end if + +process(fileToPreProcess, preProcessedFile) + +buildRes = myshell.build(mycomputer.current_path + "/" + preProcessedFileName, mycomputer.current_path) +//preProcessedFile.delete +print("Executable ready: " + preProcessedFileName.remove(".src")) + +"#archive attack/autoexploit.gs" +// @author: Tom de Qu'est-ce que tu GEEKes ? +// This script takes a vulnerability json file as input. +// Gives obtained objects / accesses gained trying to exploit it. + +"#import libs/models/vuln.gs" +"#import libs/models/jsonparser.gs" +"#import libs/models/utils.gs" + +globals.vulnerabilitiesDirectoryName = "/home/" + active_user + "/vulnerabilities/" + +if params.len < 1 or params[0] == "-h" or params[0] == "--help" then exit("<b>Usage: "+program_path.split("/")[-1]+"public_IP_address</b>") + +ipVulnDirectory = "/home/" + active_user + "/vulnerabilities/" + params[0] + "/" + +myshell = get_shell +computer = myshell.host_computer +vulnDirectory = computer.File(ipVulnDirectory) +if not vulnDirectory then exit("Error:IP Vulnerabilities not listed") +vulnFiles = vulnDirectory.get_files + +getLib = function (file) + if file.name.indexOf("kernel") > 0 then + net_session = metaxploit.net_use(vuln.ExternalIpAddress) + else + net_session = metaxploit.net_use(vuln.ExternalIpAddress, vuln.portNumber) + end if + + if not net_session then exit("Error: can't connect to net session") + + lib = net_session.dump_lib + + return lib +end function + +checkChoice = function(choice, max) + choice = choice.to_int + if typeof(choice) != "number" then exit("Should be a number. " + typeof(choice) + " provided.") end if + if choice >= max then exit ("Should be < " + max) + if choice < 0 then exit ("Should be > " + 0) + return choice +end function + +libsToAttack = [] +count = 0 +for file in vulnFiles + if file.name.indexOf("json") == null then + libsToAttack.push(file.name.split(".so")[0]) + print(count + ". " + libsToAttack[count]) + count = count + 1 + end if +end for + +choice = user_input("Which one do you want to try? >", false) +choice = checkChoice(choice, count) + +libToAttack = libsToAttack[choice] + +print("Attacking " + libToAttack + char(10)) + +vulnsAvailable = [] + +vulnCount = 0 +for file in vulnFiles + if file.name.indexOf(libToAttack) != 0 then + continue + end if + + if file.name.indexOf("json") > 0 then + vuln = parse(file.content) + vulnsAvailable.push(vuln) + lib = getLib(file) + print(vulnCount + ". " + vulnsAvailable[vulnCount].vulnUnsecValue) + vulnCount = vulnCount + 1 + end if +end for + +choice = user_input("Which one do you want to try? >", false) +choice = checkChoice(choice, vulnCount) +targetVuln = vulnsAvailable[choice] + +print(char(10) + "Attacking " + targetVuln.libName +":" + targetVuln.libVersion + " at memory address: <b>" + targetVuln.vulnMemoryAddress + "</b> with value <b>" + targetVuln.vulnUnsecValue + "</b>") +res = lib.overflow(targetVuln.vulnMemoryAddress, targetVuln.vulnUnsecValue) +print("Object obtained: " + typeof(res)) + +if (typeof(res) == "null") then + choice = user_input("Do you want to try with a payload ? Type the payload you want, 'no' otherwise. >", false) + if (choice == "no") then + exit("Try again with a different attack !") + else + res = lib.overflow(targetVuln.vulnMemoryAddress, targetVuln.vulnUnsecValue, choice) + print("Object obtained: " + typeof(res)) + end if +end if + +if (typeof(res) == "null") then + exit ("Attack failed !") +end if + +// auto attacks ! + +typeObject = typeof(res) +if(typeObject == "computer") then + homeFolder = res.File("/home") + if not homeFolder then exit("Error: /home folder not found") + userFolders = homeFolder.get_folders + found = false + for userFolder in userFolders + bankFile = res.File("/home/" + userFolder.name + "/Config/Bank.txt") + if not bankFile then continue + if not bankFile.has_permission("r") then exit("Error: can't read file contents. Permission denied") + userPass = bankFile.content.split(":") + print("Deciphering bank password for user: " + userFolder.name) + password = decipherUserPassword(userPass) + if not password then + print("Nothing found...") + else + print("Bank account: " + userPass[0] +"\nBank Password: " + password) + found = true + end if + + mailFile = res.File("/home/" + userFolder.name + "/Config/Mail.txt") + if not mailFile then continue + if not mailFile.has_permission("r") then exit("Error: can't read file contents. Permission deniend") + userPass = mailFile.content.split(":") + print("Deciphering mail password for user: " + userFolder.name) + password = decipherUserPassword(userPass) + if not password then + print("Nothing found...") + else + print("Mail account: " + userPass[0] +"\nMail Password: " + password) + found = true + end if + + end for +if not found then print("No files found") +end if + +if(typeObject == "shell") then + res.start_terminal +end if + +if(typeObject == "number") then + print("Number result obtained: " + res) +end if + +if(typeObject == "file") then + if (res.is_folder) then + print("File owner: " + res.owner) + print(res.permissions + " " + res.name) + files = res.get_files + for file in files + print(" " + file.permissions + " " + file.name) + end for + else + print("File owner: " + res.owner) + print(res.permissions + " " + res.name) + end if +end if + +"#archive attack/hackport.gs" +"#import filereaper.src" + +// Data handling from Filereaper (pars is shorthand for "params") +filereaper.UseShell = function(pars) + //state = pars[0] + shell = pars[1] + + // Hackport specific handling : global variable + if globals.shell != false then return + + globals.shell = shell +end function + +filereaper.AddPasswd = function(pars) + //state = pars[0] + creds = pars[1] + + // Hackport specific handling : global variable + if globals.pass != false then return + + data = creds.split(":") + if data[0] != "root" then return + globals.pass = GetPassword(data) +end function +// Filereaper link ends here + +if params.len != 2 or params[0] == "-h" or params[0] == "--help" then exit("<b>Usage: "+program_path.split("/")[-1]+" [ip_address] [port]</b>") +cryptools = include_lib("/lib/crypto.so") +if not cryptools then exit("Error: Missing crypto library") +metaxploit = include_lib("/lib/metaxploit.so") +if not metaxploit then + currentPath = get_shell.host_computer.current_path + metaxploit = include_lib(currentPath + "/metaxploit.so") +end if +if not metaxploit then exit("Error: Can't find metaxploit library in the /lib path or the current folder") +address = params[0] +port = params[1].to_int +net_session = metaxploit.net_use(address, port) +if not net_session then exit("Error: can't connect to net session") +metaLib = net_session.dump_lib + +GetPassword = function(userPass) + if userPass.len != 2 then exit("decipher: " + file.path + " wrong syntax") + print("retrieving password for user " +userPass[0] ) + password = cryptools.decipher(userPass[0], userPass[1]) + return password +end function + +state = null // No state object in hackport +shell = false +pass = false + +print("scanning lib") +memories = metaxploit.scan(metaLib) +for mem_addr in memories + print("scanning adress " + mem_addr) + vuln_strings = metaxploit.scan_address(metaLib, mem_addr) + if vuln_strings then + vuln_string = vuln_strings.split("Unsafe check: ") + for str in vuln_string + if str == vuln_string[0] then continue + if pass and shell then continue + string = str[str.indexOf("<b>")+3:str.indexOf("</b>")] + result = metaLib.overflow(mem_addr, string) + if not result then + print("Error: attack didn't work") + continue + end if + type = typeof(result) + if type == "shell" then + filereaper.exploitShell([state, result]) + //shell = result + else if type == "computer" then + filereaper.exploitComp([state, result]) + else if type == "file" then + filereaper.exploitFile([state], result) + end if + + // Handled by FileReaper + // file = vuln_computer.File("/etc/passwd") + // if file == null or not file.has_permission("r") then + // reason = "failed. Can't access to file" + // if file != null then reason = reason + " contents. Permission denied" + // print(reason) + // else + // print("got passwd file") + // pass_content = file.content.split("\"+"n") + // pass = GetPassword(pass_content[0].split(":")) + // end if + end for + else + print("failed to get vulnerabilities") + end if +end for + +if pass == false then + print("root pass not found") +else + print("root pass is: "+ pass) +end if +if shell == false then + print("shell not found") +else + if pass == false and not imports.utils.UserPrompt("launch shell with no root pass?") then return + print("launching shell") + shell.start_terminal +end if + +"#archive attack/univscan.gs" +// @author: Tom de Qu'est-ce que tu GEEKes ? +// This script takes an address as input and scans all ports available to find vulnerabilities +// Collect inputs and handling options +if params.len < 1 or params[0] == "-h" or params[0] == "--help" then exit("<b>Usage: "+program_path.split("/")[-1]+" [ip_address]</b>") + +//print("<color=#f4ae34>QTG ORANGE</color>") +//print("<color=#1a508d>QTG BLUE</color>") +//print("<color=#182d53>QTG DARK BLUE</color>") + +print(char(10)) +print("UnivScan By:"+ char(10)) +"#import libs/qtglogo.inc.src" +printLogo() +//print("<color=#1a508d> &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& </color>") +//print("<color=#1a508d> &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% </color>") +//print("<color=#1a508d>&%%%% %%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>,***,***,***,***, ***,***,***,***,*</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>*</color>%%%%%%%%%%%%%%<color=#f4ae34>**</color> <color=#f4ae34>**</color>%%%%%%%%%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>******</color>%%%%%%%%%%%%%%<color=#f4ae34>*****, **************,** *******</color>%%%%%%%%%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>*, **</color>%%%%%%%%%%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>*,</color>%%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>*, ******,</color>%%%%<color=#f4ae34>***,** **</color>%%%%%<color=#f4ae34>****</color>%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>*,******** **</color>%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>****</color>%%%%<color=#f4ae34>*******</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>*,,*</color>%%%%<color=#f4ae34>** **</color>%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>*****,**</color>%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>****</color>%%%%<color=#f4ae34>*****</color>%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>*****,**</color>%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>*,*,*,</color>*%%%%%%%%%%%%%<color=#f4ae34>*,*,*, *,</color>%%%%<color=#f4ae34>*, ,*,*,*,</color>%%%%%%%%%%%%%<color=#f4ae34>,*</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%%%%%%%%%<color=#f4ae34>*****, **</color>%%%%<color=#f4ae34>** **</color>%%%%%%%%%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>****,**********</color>%%%%<color=#f4ae34>*, ******** *******,*********</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**####*,</color> &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</color>") +//print("<color=#1a508d> &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%& </color>") +//print(" ") +//print("<color=#182d53> &&&&&&&&&&&&&&&&&&&&& </color>") +//print("<color=#182d53> &&&&&&&&&&&&&&&&&&&&& </color>") +//print("<color=#1a508d> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% </color>") + +ipAddress = params[0] + +globals.vulnerabilitiesDirectoryName = "/home/" + active_user + "/vulnerabilities/" +myshell = get_shell +myshell.host_computer.create_folder( "/home/" + active_user, "vulnerabilities") + +"#import libs/models/jsonparser.gs" +"#import libs/models/vuln.gs" +"#import libs/models/utils.gs" + +//Defining functions + +// nmap +// string ipAddress +// @return Port[] +nmap = function(ipAddress) + isLanIp = is_lan_ip( ipAddress ) + if isLanIp then + globals.router = get_router; + else + globals.router = get_router( ipAddress ) + end if + + if globals.router == null then exit("nmap: ip address not found") + + isRouterIp = globals.router.local_ip == ipAddress + ports = null + + if not isLanIp or isRouterIp then + ports = globals.router.used_ports + else + ports = globals.router.device_ports(ipAddress) + end if + + return ports +end function +// END functions definitions + +// finding vulnerabilities for each port +ports = nmap(ipAddress) +print(char(10) + "<color=#FF0000FF>SCANNING ALL PORTS: " + ipAddress + "</color>") +vulnerabilitiesArray = [] +scannedLibs = [] +// little hack to scan the router with the other libs +ports.push("router") +for port in ports + if port == "router" then + lib = getRouter(ipAddress) + else + lib = getLib(ipAddress, port) + end if + libId = lib.lib_name + "_" + lib.version + + existingVulnerabilityFile = getFile(globals.vulnerabilitiesDirectoryName, libId) + if (existingVulnerabilityFile != null) then + print("Vulnerability file '" + libId + "' already existing, skipping") + continue + end if + + if (scannedLibs.indexOf(libId) != null) then + continue + else + scannedLibs.push(libId) + end if + print("Scanning lib " + libId) + scanResults = metaxploit.scan(lib) + // example with port 25, usefull to debug + //scanResults = ["0x19189A45", "0x1C021A4C", "0x5D601DE4"] + vulnerabilitiesMap = {} + for address in scanResults + vulnerabilitiesMap[address] = metaxploit.scan_address(lib, address) + end for + for vulnerabilityByAddr in vulnerabilitiesMap + addressForThoseVulnerabilitys = vulnerabilityByAddr.key + vulnerabilitiesLines = vulnerabilityByAddr.value.split("\"+"n") + vulnerabilityIndex = 0 + vulnerabilitiesToParse = [] + currentVulnerabilityLines = "" + for vulnerabilityLine in vulnerabilitiesLines + if vulnerabilityLine.indexOf("Unsafe check") == 0 then + if vulnerabilityIndex > 0 then + previousVulnerabilityLine = currentVulnerabilityLines + vulnerabilitiesToParse.push(previousVulnerabilityLine) + end if + vulnerabilityIndex = vulnerabilityIndex + 1 + currentVulnerabilityLines = vulnerabilityLine + "###" + else if vulnerabilityLine.indexOf("* ") == 0 then + currentVulnerabilityLines = currentVulnerabilityLines + vulnerabilityLine + "###" + else + //print("unused line: " + line) + end if + end for// split vulnerabilities + vulnerabilitiesToParse.push(currentVulnerabilityLines) + //print("DEBUG To Parse: " + vulnerabilitiesToParse) + //print("DEBUG addr: " + addressForThoseVulnerabilitys) + for vulnerability in vulnerabilitiesToParse + vuln = new Vulnerability + vuln._setExternalIpAddress(ipAddress) + vuln._setLibName(lib.lib_name) + vuln._setPortInfos(port) + vuln._setVuln(addressForThoseVulnerabilitys, vulnerability) + vulnerabilitiesArray.push(vuln) + end for + + end for +end for + +for vulnerability in vulnerabilitiesArray + vulnerabilityFile = vulnerability._toFile +end for + +for vulnerability in vulnerabilitiesArray + myshell = get_shell + filePath = vulnerability._getFilePath + fileName = vulnerability.libName + "_" + vulnerability.libVersion + "_" + md5(vulnerability.vulnUnsecValue) + ".json" + myshell.host_computer.touch(filePath, fileName) + + vulnerabilityFile = myshell.host_computer.File(filePath + fileName) + vulnerabilityFile.set_content("") + vulnerabilityFile.set_content(vulnerabilityFile.content + char(10) + toJSON(vulnerability)) +end for + +print("Vulnerabilities files stored in: " + globals.vulnerabilitiesDirectoryName) + +"#archive tools/airbreaker.gs" +"#import libs/utils.inc.src" + +// Automates as most as possible the wifi cracking process +// Requirements : crypto.so + +imports.network = {} + +// Is it REALLY useful to call network_devices() for that one? +imports.network.getNetDevices = function() + return ["wlan0"] +end function + +imports.network.getWifi = function(device) + result = [] + for network in get_shell.host_computer.wifi_networks(device) + data = network.split(" ") + data[1] = imports.network.airpower(data[1]) + result.push(data) + end for + return result +end function + +// Formula is provided by GHTools, sorry! +imports.network.airpower = function(strength) + return floor(300000/(strength.remove("%").to_int)+1) //calculating the acks needed +end function + +// command: airbreaker +cryptools = imports.utils.IncludeLib("crypto.so") +comp = get_shell.host_computer + +devices = imports.network.getNetDevices() +if devices.len == 0 then imports.utils.Exit("No devices found") +device = devices[imports.utils.Choice(devices)] + +if not cryptools.airmon("start", device) then imports.utils.Exit("Can't activate monitor mode on "+device) + +networks = imports.network.getWifi(device) + +choice = [] +for item in networks + choice.push(item[2]) +end for +network = networks[imports.utils.Choice(choice, "a wifi network")] + +bssid = network[0] +required = network[1] +essid = network[2] + +if required < 0 then + print("Please enter the number of ACKs you want to generate") + required = user_prompt().to_int + if typeof(required) == "string" or required < 0 then exit("Error: invalid number") +end if +print("Generating <color=white>"+required+"</color> ACKs, please wait") +cryptools.aireplay(bssid,essid,required) + +cryptools.airmon("stop", device) + +path = get_shell.host_computer.current_path+"/file.cap" +wait(1) +file = comp.File(path) +if not file then imports.utils.Exit("Couldn't find file, expected "+path) + +password = cryptools.aircrack(path) +if not comp.connect_wifi(device, bssid, essid, password) then imports.utils.Exit("Couldn't connect !?") + +print("Connected to " + essid + ", password : "+password) +file.delete() + +"#archive tools/archive.src" +"#import includes/utils.inc.src" +"#import includes/file.inc.src" + +// Used by passing the path of the (txt) archive, then the path of all the files to add +// More information at https://usine.solution-libre.fr/qtg/grey-hack/-/issues/6 + +"#ifbuild" +imports = {} + +// The methods here are "good enough" to work in those cases +// For example, the ParamLength normally discards flag-style args +// But I don't want to give you all my tricks... yet, at least ;) +imports.utils = {} +imports.utils.ParamLength = function(params) + if params == null then return 0 + return params.len +end function +imports.utils.GetParam = function(params, index) + if index < 0 or index >= imports.utils.ParamLength(params) then return null + return params[index] +end function +imports.utils.HasFlag = function(params, short, long) + if imports.utils.ParamLength(params) == 0 then return null + param = params[0] + return param == "-"+short or param == "-"+long +end function +// Dynamically getting the name of the command is left as an exercise to the reader :) +imports.utils.GetProgName = function() + return program_path.split("/")[-1] +end function +imports.utils.Print = function(reason) + print(imports.utils.GetProgName()+": "+reason) +end function + +imports.file = {} +imports.file.NEW_LINE = char(10) +// Disclaimer : brand new method created for this script, may not handle special cases +imports.file.AbsolutePath = function(path) + if path[0] != "/" then path = get_shell.host_computer.current_path + "/" + path + return path +end function +// Should return [] for unavailable files (binary or no read perms) +imports.file.ReadAllLines = function(file) + if typeof(file) == "string" then + file = get_shell.host_computer.File(file) + end if + if not imports.file.FileAccess(file,"r") then return [] + if file.is_binary then return [] + return file.content.split(imports.file.NEW_LINE) +end function +imports.file.FileAccess = function(file, perm) + if not file then return false + if file.has_permission(perm) then return true + imports.utils.Print("Error: can't use ('"+perm+"') contents of '"+file.path+"'") + return false +end function +imports.file.save = function(content, path, name) + data = name.split("/") + if data.len > 1 then + for index in range(0, data.len-2) + name = data[index] + comp.create_folder(path, name) + path = path +"/"+ name + end for + end if + name = data[data.len-1] + comp.touch(path, name) + comp.File(path+"/"+name).set_content(content) +end function +"#endif" + +// To avoid bruning our eyes with escaping +QUOTE = """" + +// Metadatas are encoded as 'unused' strings +// Extracted straight from my preprocessor as that's too specific for an include IMHO +GetLastChar = function(str) + if not str then return null + if str.len < 1 then return null + return str[str.len-1] +end function +// Returns the text in the 'unused' string or NULL if not a standalone string +StringInstruction = function(str) + if str == null then return null + str = str.trim() + if GetLastChar(str) != QUOTE then return null + if str[0] != QUOTE then return null + str = str[1:str.len-1] + if str.indexOf(QUOTE) != null then return null + str = str.trim() + if str[0] != "#" then return "" + return str[1:str.len] +end function + +// To identify archived data +TAG = "#archive " + +ArchiveName = function(str) + str = StringInstruction(str) + if str == null then return null + if str.len < TAG.len then return + if str[0:TAG.len-1] != TAG[1:] then return null + return str[TAG.len-1:] +end function + +// command: archive +length = imports.utils.ParamLength(params) +if length == 0 or imports.utils.HasFlag(params, "h", "help") then exit("<b>Usage: "+imports.utils.GetProgName()+" [file to compress/decompress] [...file paths]</b>") +comp = get_shell.host_computer + +mainPath = imports.file.AbsolutePath(imports.utils.GetParam(params, 0) + ".tar") +mainFile = comp.File(mainPath) + +temp = mainPath.lastIndexOf("/") +path = mainPath[:temp] +name = mainPath[temp+1:] + +if mainFile == null then + imports.utils.Print("Combining files") + + // Creating the file + comp.touch(path, name) + mainFile = comp.File(mainPath) + + // Flag to avoid a new line on the first line + nextLine = false + content = "" + + // Read all files in order and add them + for i in range(1,length-1) + path = imports.file.AbsolutePath(imports.utils.GetParam(params, i)) + // Get the name of the file + name = path[path.lastIndexOf("/")+1:] + + lines = imports.file.ReadAllLines(path) + // Sanity checking the file is left as an exercise to the reader :) + if lines.len == 0 then + imports.utils.Print("Can't read file "+i+" ("+name+")") + continue + end if + + if nextLine then + content = content + imports.file.NEW_LINE + else + nextLine = true + end if + + // add "#archive filename.ext" then the file + content = content + QUOTE+TAG+name+QUOTE + for line in lines + content = content + imports.file.NEW_LINE + line + end for + end for + + mainFile.set_content(content) + print("Archive is now available") +else + print("Unarchiving") + + // Using the archive name as a new folder + if temp > 1 then name = name[:name.lastIndexOf(".")] + comp.create_folder(path, name) + path = path + "/" + name + + lines = imports.file.ReadAllLines(mainPath) + if ArchiveName(lines[0]) == null then exit("Not a valid archive file") + + currentName = null + content = "" + nextLine = false + + for line in lines + temp = ArchiveName(line) + // New file + if temp != null then + if currentName != null then imports.file.save(content, path, currentName) + + currentName = temp + content = "" + nextLine = false + continue + end if + + if nextLine then + content = content + imports.file.NEW_LINE + else + nextLine = true + end if + + content = content + line + + end for + + imports.file.save(content, path, currentName) + print("Unarchiving completed") +end if + +"#archive tools/breakhash.src" +"#import libs/utils.inc.src" + +//command: breakhash +length = imports.utils.ParamLength(params) +if length < 2 or length > 4 or imports.utils.HasFlag(params, "h", "help") then exit("<b>Usage: "+imports.utils.GetProgName()+" [hash] [max length] [(opt) min length] [(opt) char set] --numerals --uppercase --lowercase") + +hash = imports.utils.GetParam(params, 0) + +maxLen = imports.utils.GetParam(params, 1).to_int +minLen = imports.utils.GetParam(params, 2) +if minLen then + minLen = minLen.to_int +else + minLen = 0 +end if +if maxLen < 0 or minLen < 0 then imports.utils.Exit("Lengths must not be negative!") + +possibilities = imports.utils.GetParam(params, 3) +if possibilities then + possibilities = possibilities.values +else + possibilities = [] +end if + +ASCII = function(min, max) + for i in range(min, max) + possibilities.push(char(i)) + end for +end function + +if imports.utils.HasFlag(params, "l", "lowercase") then ASCII(97,122) +if imports.utils.HasFlag(params, "u", "uppercase") then ASCII(65,90) +if imports.utils.HasFlag(params, "n", "numerals") then ASCII(48,57) +if possibilities.len == 0 then imports.utils.Exit("You must specify at least one set of characters!") + +Increment = function(arr, max, index) + value = arr[index]+1 + if value < max then + arr[index] = value + return true + end if + if index == 0 then return false + arr[index] = 0 + return Increment(arr, max, index-1) +end function + +for length in range(minLen,maxLen) + indexes = [] + for i in range(0, length-1) + indexes.push(0) + end for + + loop = true + while loop + try = "" + for index in indexes + try = try + possibilities[index] + end for + + if hash == md5(try) then imports.utils.Exit("Bruteforced:"+try) + loop = Increment(indexes, possibilities.len, indexes.len-1) + end while + print("Tried all combinations of "+length+" characters") + imports.utils.Pause() +end for + +imports.utils.Exit("Not found under those parameters!") + +"#archive tools/colony.gs" +"#import libs/utils.inc.src" +"#import libs/file.inc.src" +"#import libs/remote.inc.src" + +// Tool to send to rented servers the default binaries from computers +// Note that the utility methods to transfer a file only accepts complete path +// "connect" and "transfer" should be easy reusable for a code pulling tool (issue #7) + +//command: colony +length = imports.utils.ParamLength(params) +if length < 3 or length > 5 or imports.utils.HasFlag(params, "h", "help") then exit("<b>Usage: "+imports.utils.GetProgName()+" [user] [password] [ip] [(opt) port] [(opt) service]</b>") +comp = get_shell.host_computer + +user = imports.utils.GetParam(params, 0) +password = imports.utils.GetParam(params, 1) +ip = imports.utils.GetParam(params, 2) +port = imports.utils.GetParam(params, 3) +service = imports.utils.GetParam(params, 4) + +remote = imports.remote.connect(get_shell, user, password, ip, port, service) +if not remote then exit("Can't connect to remote server") +for path in imports.file.MISSING + result = imports.remote.upload(remote, path, path[:path.lastIndexOf("/")]) + if typeof(result) == "string" then print(result) else print("Sent to "+result.path) +end for + +"#archive tools/decipher2.src" +cryptools = include_lib("/lib/crypto.so") +if not cryptools then exit("Error: Missing crypto library") + +GetPassword = function(userPass) + // First modification: remove the hardcoded reference to a file + if userPass.len != 2 then exit("decipher: wrong syntax") + password = cryptools.decipher(userPass[0], userPass[1]) + return password +end function + +if params.len != 1 or params[0] == "-h" or params[0] == "--help" then exit(command_info("decipher_usage")) + +origFile = params[0] +file = get_shell.host_computer.File(origFile) +// Second modification: treat a non-file parameter as a value to decrypt +if not file then + if origFile.indexOf(":") == null then exit("decipher: can't find " + origFile) + lines = [origFile] +else + if not file.has_permission("r") then exit("can't read file. Permission denied") + if file.content.len == 0 then exit("decipher: no users found") + lines = file.content.split("\n") +end if + +// Third modification: instead of selecting one of the lines, decrypt them all +for line in lines + userPass = line.split(":") + print("Selected user: " + userPass[0] + "\nDeciphering...") + password = GetPassword(userPass) + + if not password then + print("Can't find password :(") + else + print("password found! => " + password) + end if +end for + +"#archive tools/scanlib2.src" +//command scanlib +if params.len != 1 or params[0] == "-h" or params[0] == "--help" then exit(command_info("scanlib_usage")) +metaxploit = include_lib("/lib/metaxploit.so") +if not metaxploit then exit("Error: Missing metaxploit library") +libFile = get_shell.host_computer.File(params[0]) +// First modification : remote scanning +if not libFile then + metaLib = null + if params[0].indexOf(":") != null then + data = params[0].split(":") + metaLib = metaxploit.net_use(data[0], data[1].to_int).dump_lib + end if + if not metaLib then exit("can't find library: " + params[0]) +else + metaLib = metaxploit.load(libFile.path) +end if +print("Scanning memory address...") +listMem = metaxploit.scan(metaLib) +// Second modification : looping in order to reuse the results from the scan+exit on input +while true + print("0: EXIT") + index = 1 + for itemMem in listMem + print(index +": [" + itemMem + "]") + index = index + 1 + end for + if listMem.len == 0 then exit("Scan completed: No issues detected.") + + print("Scan completed: detected issues in " + listMem.len + " memory zones.") + option = "" + inputOk = false + while( not inputOk ) + option = user_input("Select memory index: ").to_int + if typeof(option) != "number" or (option < 1 or option > listMem.len) then + // Third modification : exit on input + if option == 0 then exit() + print("Invalid input. Type a valid number") + else + inputOk = true + end if + end while + print("Scanning for vulnerabilities at memory zone: " + listMem[option - 1]) + print(metaxploit.scan_address(metaLib, listMem[option - 1])) +end while + +"#archive tools/setup.gs" +"#import libs/utils.inc.src" + +// Can create two limited users : ssh and ftp (when optional passwords are provided) +// Make sure to have created the custom remote and members accounts before that +// For the exact effects on permissions, see https://usine.solution-libre.fr/qtg/grey-hack/-/issues/9 +// Will clear the log file and all /Config/ folders as an additional security in case the server got misused before +// !!! This program will self-delete after use !!! +// Note : chmodding takes a bit of time for unknown reasons (and GH doesn't show prints while running) +// Expect ONE MINUTE or so until the single print statement shows up + +imports.temp = {} +imports.file = {} + +imports.temp.AddCmd = function(arr, files) + for file in files + arr.push("/bin/"+file) + end for +end function +imports.temp.AddSoft = function(arr, files) + for file in files + arr.push("/usr/bin/"+file+".exe") + end for +end function + +// #2.6: If "destructive security" is desired, delete /etc/passwd and the services in /server/ (to prevent a shutdown) +//imports.file.USELESS = ["/etc/passwd","/server"] +imports.file.USELESS = [] +// #2.3: Nslookup, whois, Mail.exe aren't useful on a server, maaaybe on a dedicated proxy... delete it +// #2.4: At the time of writing, there's no obvious benefit with not deleting CodeEditor.exe and build +// #2.5: Are members allowed the use this server as a last-point proxy to reach a ftp? If not, delete the ftp command +imports.temp.AddCmd(imports.file.USELESS,["build","whois","nslookup","ftp"]) +imports.temp.AddSoft(imports.file.USELESS,["CodeEditor", "Mail"]) + +// #1.3: Give execution rights to everyone for "/bin/clear" +imports.file.SAFE = [] +imports.temp.AddCmd(imports.file.SAFE,["clear"]) + +// #3.3: Set group for "/bin/ssh" as "ssh" and give it group-level execution rights +imports.file.SSH = [] +imports.temp.AddCmd(imports.file.SSH,["ssh"]) +// Nothing. +imports.file.FTP = [] + +// #3.4: Set group "members" and give group-level execution rights for... +imports.file.ALLOWED = [] +imports.temp.AddCmd(imports.file.ALLOWED,["cd","ls","pwd","cat","rm","mv","cp","mkdir","rmdir","touch"]) +imports.temp.AddSoft(imports.file.ALLOWED,["Terminal","FileExplorer","Notepad"]) + +imports.temp = null + +//command: setup +if not imports.utils.IsRoot() then imports.utils.Exit("Must be root.") + +length = imports.utils.ParamLength(params) +if length > 2 or imports.utils.HasFlag(params, "h", "help") then exit("<b>Usage: "+imports.utils.GetProgName()+" [(opt) ssh password] [(opt) ftp password]</b>") +comp = get_shell.host_computer + +sshPass = imports.utils.GetParam(params, 0) +ftpPass = imports.utils.GetParam(params, 1) + +// Utility method : only delete the files, not the directories +// (Can be used on a file too) +WipeDir = function(path) + dir = comp.File(path) + if not dir then return + if path[path.len-1] == "/" then + for file in dir.get_files // NOT THE FOLDERS!!!! + file.delete + end for + else + dir.delete + end if +end function +// Utility method : delete all elements in the dir, then delete the dir itself +FullWipe = function(file) + if not file then return + for child in file.get_files + child.delete() + end for + for child in file.get_folders + FullWipe(child) + end for + file.delete() +end function + +// #0.1: users able to bounce through ssh +SSH_GROUP = "ssh" +// #0.2: users able to access the /Public/Downloads/ folder +FTP_GROUP = "ftp" +// #0.3: users connected to manipulate non-public files (subgroup) +MAIN_GROUP = "home" +// #0.4: users with a private space (inherits files group) +USER_GROUP = "members" + +// #1.1 By default, removing all perms for everyone on everything +main = comp.File("/") +for mod in ["u-rwx", "g-rwx", "o-rwx"] + main.chmod(mod,1) +end for +// #1.2 Give read access to everyone in / +main.chmod("o+r",0) + +NewLimitedUser = function(user, pass, grp) + if not comp.create_user(user, pass) then comp.change_password(user, pass) + comp.create_group(user, grp) + + // #2.1: Delete the home folder of (...) + "ssh"/"ftp"-only users + dir = comp.File("/home/"+user+"/") + if not dir then return + dir.delete() + end if +end function +// #1.4 Create the groups and add them to users accordingly +if sshPass then NewLimitedUser("proxy", sshPass, SSH_GROUP) +if ftpPass then NewLimitedUser("files", ftpPass, FTP_GROUP) + +SetRead = function(path, group) + file = comp.File(path) + if not file then return + recur = 0 + file.set_group(group,recur) + file.chmod("g+r",recur) +end function +// #3.1 Set group for /home/ as "files" and give it group-level read +SetRead("/home/", MAIN_GROUP) +// #1.5 Set group for /Public/ as "ftp" and give it group-level read +SetRead("/Public/", FTP_GROUP) + +// #1.6 Set group for /Public/Downloads/ as "ftp" and give it (recursive) group-level read-write +ftpDir = comp.File("/Public/Downloads/") +if ftpDir then + ftpDir.set_group(FTP_GROUP,1) + ftpDir.chmod("g+rw", 1) +end if + +users = [] +for user in comp.File("/home/").get_folders + if user.name == "guest" then + // #2.1: Delete the home folder of guest + (...) users + FullWipe(user) + else + // #2.2 Give (recursive) !user-level! read-write for child folders of /home/ + users = users.push(user.path) + user.chmod("u+rw",1) + end if +end for + +for path in imports.file.USELESS + WipeDir(path) +end for + +// #2.2: It would be a good idea to delete/reset the /Config/ folder for all users, just in case. (...) +users = users.push("/root") +for user in users + WipeDir(user+"/Config/") +end for + +// The 15 following lines are applying the suggestions listed at the "imports.file." part +for path in imports.file.SAFE + file = comp.File(path) + file.chmod("o+x",1) +end for + +Safe = function(group, paths) + for path in paths + file = comp.File(path) + recur=1 + file.chmod("g+x",recur) + file.set_group(group,recur) + end for +end function +Safe(USER_GROUP, imports.file.ALLOWED) +Safe(SSH_GROUP, imports.file.SSH) +Safe(FTP_GROUP, imports.file.FTP) // Normally no-op + +imports.utils.SelfDestruct() + +// #2.2: It would be a good idea to delete/reset (...), just in case. and the log file too. +WipeDir("/var/system.log") +comp.touch("/var/", "system.log") + +print("Setup is finished") diff --git a/airbreaker.src b/scripts/attack/airbreaker.src similarity index 62% rename from airbreaker.src rename to scripts/attack/airbreaker.src index ac83e5d34cee06312bcb123348a8a432cf230454..0319f78f165c4514e5049ea780e9c9723addf003 100644 --- a/airbreaker.src +++ b/scripts/attack/airbreaker.src @@ -1,46 +1,8 @@ -"#import utils.inc.src" +"#import libs/utils.inc.src" // Automates as most as possible the wifi cracking process // Requirements : crypto.so -"#ifbuild" -if not globals.hasIndex("imports") then - imports = {} - - imports.utils = {} - - imports.utils.IncludeLib = function(libName, mandatory) - lib = include_lib("/lib/" + libName) - if not lib then - currentPath = get_shell.host_computer.current_path - lib = include_lib(currentPath + "/" + libName) - end if - if mandatory and not lib then exit("Error: Can't find " + libName + " library in the /lib path or the current folder") - return lib - end function - - imports.utils.Exit = function(reason) - exit(reason) - end function - - imports.utils.Choice = function(choices, reason) - len = choices.len - if len < 2 then return len-1 - if not reason then print("Please choose "+reason) - while true - for index in range(0,len-1) - print(index+1 + ":" + choices[index]) - end for - input = user_input("Enter the number to select then press ENTER: ") - input = input.trim().to_int - 1 - if input >= 0 and input < len then return input - print("Not a recognized selection") - end while - return -1 // Should never happen - end function -end if -"#endif" - imports.network = {} // Is it REALLY useful to call network_devices() for that one? @@ -96,6 +58,7 @@ cryptools.aireplay(bssid,essid,required) cryptools.airmon("stop", device) path = get_shell.host_computer.current_path+"/file.cap" +wait(1) file = comp.File(path) if not file then imports.utils.Exit("Couldn't find file, expected "+path) @@ -103,4 +66,4 @@ password = cryptools.aircrack(path) if not comp.connect_wifi(device, bssid, essid, password) then imports.utils.Exit("Couldn't connect !?") print("Connected to " + essid + ", password : "+password) -file.delete() \ No newline at end of file +file.delete() diff --git a/scripts/attack/autoexploit.gs b/scripts/attack/autoexploit.gs index 889ccafc8bf3d85743b368874a24d2f09bfbb028..2881f77eb784a18921a94caf4741cc90afcecab6 100644 --- a/scripts/attack/autoexploit.gs +++ b/scripts/attack/autoexploit.gs @@ -2,9 +2,9 @@ // This script takes a vulnerability json file as input. // Gives obtained objects / accesses gained trying to exploit it. -"#import vuln.gs" -"#import jsonparser.gs" -"#import tools.gs" +"#import libs/models/vuln.gs" +"#import libs/models/jsonparser.gs" +"#import libs/models/utils.gs" globals.vulnerabilitiesDirectoryName = "/home/" + active_user + "/vulnerabilities/" diff --git a/scripts/attack/hackport.gs b/scripts/attack/hackport.gs new file mode 100644 index 0000000000000000000000000000000000000000..b6eea45201d984fd175499e6f3c2c70cb627a150 --- /dev/null +++ b/scripts/attack/hackport.gs @@ -0,0 +1,107 @@ +"#import filereaper.src" + +// Data handling from Filereaper (pars is shorthand for "params") +filereaper.UseShell = function(pars) + //state = pars[0] + shell = pars[1] + + // Hackport specific handling : global variable + if globals.shell != false then return + + globals.shell = shell +end function + +filereaper.AddPasswd = function(pars) + //state = pars[0] + creds = pars[1] + + // Hackport specific handling : global variable + if globals.pass != false then return + + data = creds.split(":") + if data[0] != "root" then return + globals.pass = GetPassword(data) +end function +// Filereaper link ends here + +if params.len != 2 or params[0] == "-h" or params[0] == "--help" then exit("<b>Usage: "+program_path.split("/")[-1]+" [ip_address] [port]</b>") +cryptools = include_lib("/lib/crypto.so") +if not cryptools then exit("Error: Missing crypto library") +metaxploit = include_lib("/lib/metaxploit.so") +if not metaxploit then + currentPath = get_shell.host_computer.current_path + metaxploit = include_lib(currentPath + "/metaxploit.so") +end if +if not metaxploit then exit("Error: Can't find metaxploit library in the /lib path or the current folder") +address = params[0] +port = params[1].to_int +net_session = metaxploit.net_use(address, port) +if not net_session then exit("Error: can't connect to net session") +metaLib = net_session.dump_lib + +GetPassword = function(userPass) + if userPass.len != 2 then exit("decipher: " + file.path + " wrong syntax") + print("retrieving password for user " +userPass[0] ) + password = cryptools.decipher(userPass[0], userPass[1]) + return password +end function + +state = null // No state object in hackport +shell = false +pass = false + +print("scanning lib") +memories = metaxploit.scan(metaLib) +for mem_addr in memories + print("scanning adress " + mem_addr) + vuln_strings = metaxploit.scan_address(metaLib, mem_addr) + if vuln_strings then + vuln_string = vuln_strings.split("Unsafe check: ") + for str in vuln_string + if str == vuln_string[0] then continue + if pass and shell then continue + string = str[str.indexOf("<b>")+3:str.indexOf("</b>")] + result = metaLib.overflow(mem_addr, string) + if not result then + print("Error: attack didn't work") + continue + end if + type = typeof(result) + if type == "shell" then + filereaper.exploitShell([state, result]) + //shell = result + else if type == "computer" then + filereaper.exploitComp([state, result]) + else if type == "file" then + filereaper.exploitFile([state], result) + end if + + // Handled by FileReaper + // file = vuln_computer.File("/etc/passwd") + // if file == null or not file.has_permission("r") then + // reason = "failed. Can't access to file" + // if file != null then reason = reason + " contents. Permission denied" + // print(reason) + // else + // print("got passwd file") + // pass_content = file.content.split("\"+"n") + // pass = GetPassword(pass_content[0].split(":")) + // end if + end for + else + print("failed to get vulnerabilities") + end if +end for + +if pass == false then + print("root pass not found") +else + print("root pass is: "+ pass) +end if +if shell == false then + print("shell not found") +else + if pass == false and not imports.utils.UserPrompt("launch shell with no root pass?") then return + print("launching shell") + shell.start_terminal +end if diff --git a/scripts/attack/univscan.gs b/scripts/attack/univscan.gs index 7ba6e236cb374cb46c4adf5767bb5f71711431c4..fcb9f432f6bc4ce19ff43034668cf1be5a306517 100644 --- a/scripts/attack/univscan.gs +++ b/scripts/attack/univscan.gs @@ -9,36 +9,38 @@ if params.len < 1 or params[0] == "-h" or params[0] == "--help" then exit("<b>Us print(char(10)) print("UnivScan By:"+ char(10)) -print("<color=#1a508d> &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& </color>") -print("<color=#1a508d> &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% </color>") -print("<color=#1a508d>&%%%% %%%%</color>") -print("<color=#1a508d>&%%%& &%%%</color>") -print("<color=#1a508d>&%%%& &%%%</color>") -print("<color=#1a508d>&%%%& &%%%</color>") -print("<color=#1a508d>&%%%& &%%%</color>") -print("<color=#1a508d>&%%%& &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>,***,***,***,***, ***,***,***,***,*</color> &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>*</color>%%%%%%%%%%%%%%<color=#f4ae34>**</color> <color=#f4ae34>**</color>%%%%%%%%%%%%%<color=#f4ae34>**</color> &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>******</color>%%%%%%%%%%%%%%<color=#f4ae34>*****, **************,** *******</color>%%%%%%%%%%%%%<color=#f4ae34>**</color> &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>*, **</color>%%%%%%%%%%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>**</color> &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>*,</color>%%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>*, ******,</color>%%%%<color=#f4ae34>***,** **</color>%%%%%<color=#f4ae34>****</color>%%%%<color=#f4ae34>**</color> &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>*,******** **</color>%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>****</color>%%%%<color=#f4ae34>*******</color> &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>*,,*</color>%%%%<color=#f4ae34>** **</color>%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>*****,**</color>%%%%%<color=#f4ae34>**</color> &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>****</color>%%%%<color=#f4ae34>*****</color>%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>*****,**</color>%%%%%<color=#f4ae34>**</color> &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>*,*,*,</color>*%%%%%%%%%%%%%<color=#f4ae34>*,*,*, *,</color>%%%%<color=#f4ae34>*, ,*,*,*,</color>%%%%%%%%%%%%%<color=#f4ae34>,*</color> &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%%%%%%%%%<color=#f4ae34>*****, **</color>%%%%<color=#f4ae34>** **</color>%%%%%%%%%%%%%<color=#f4ae34>**</color> &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>****,**********</color>%%%%<color=#f4ae34>*, ******** *******,*********</color> &%%%</color>") -print("<color=#1a508d>&%%%& <color=#f4ae34>**####*,</color> &%%%</color>") -print("<color=#1a508d>&%%%& &%%%</color>") -print("<color=#1a508d>&%%%& &%%%</color>") -print("<color=#1a508d>&%%%& &%%%</color>") -print("<color=#1a508d>&%%%& &%%%</color>") -print("<color=#1a508d>@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</color>") -print("<color=#1a508d> &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%& </color>") -print(" ") -print("<color=#182d53> &&&&&&&&&&&&&&&&&&&&& </color>") -print("<color=#182d53> &&&&&&&&&&&&&&&&&&&&& </color>") -print("<color=#1a508d> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% </color>") +"#import libs/qtglogo.inc.src" +printLogo() +//print("<color=#1a508d> &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& </color>") +//print("<color=#1a508d> &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% </color>") +//print("<color=#1a508d>&%%%% %%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>,***,***,***,***, ***,***,***,***,*</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>*</color>%%%%%%%%%%%%%%<color=#f4ae34>**</color> <color=#f4ae34>**</color>%%%%%%%%%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>******</color>%%%%%%%%%%%%%%<color=#f4ae34>*****, **************,** *******</color>%%%%%%%%%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>*, **</color>%%%%%%%%%%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>*,</color>%%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>*, ******,</color>%%%%<color=#f4ae34>***,** **</color>%%%%%<color=#f4ae34>****</color>%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>*,******** **</color>%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>****</color>%%%%<color=#f4ae34>*******</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>*,,*</color>%%%%<color=#f4ae34>** **</color>%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>*****,**</color>%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%<color=#f4ae34>****</color>%%%%<color=#f4ae34>*****</color>%%%%<color=#f4ae34>*, **</color>%%%%<color=#f4ae34>** **</color>%%%%%<color=#f4ae34>*****,**</color>%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>*,*,*,</color>*%%%%%%%%%%%%%<color=#f4ae34>*,*,*, *,</color>%%%%<color=#f4ae34>*, ,*,*,*,</color>%%%%%%%%%%%%%<color=#f4ae34>,*</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**</color>%%%%%%%%%%%%%<color=#f4ae34>*****, **</color>%%%%<color=#f4ae34>** **</color>%%%%%%%%%%%%%<color=#f4ae34>**</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>****,**********</color>%%%%<color=#f4ae34>*, ******** *******,*********</color> &%%%</color>") +//print("<color=#1a508d>&%%%& <color=#f4ae34>**####*,</color> &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>&%%%& &%%%</color>") +//print("<color=#1a508d>@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%</color>") +//print("<color=#1a508d> &%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%& </color>") +//print(" ") +//print("<color=#182d53> &&&&&&&&&&&&&&&&&&&&& </color>") +//print("<color=#182d53> &&&&&&&&&&&&&&&&&&&&& </color>") +//print("<color=#1a508d> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% </color>") ipAddress = params[0] @@ -46,9 +48,9 @@ globals.vulnerabilitiesDirectoryName = "/home/" + active_user + "/vulnerabilitie myshell = get_shell myshell.host_computer.create_folder( "/home/" + active_user, "vulnerabilities") -"#import jsonparser.gs" -"#import vuln.gs" -"#import tools.gs" +"#import libs/models/jsonparser.gs" +"#import libs/models/vuln.gs" +"#import libs/models/utils.gs" //Defining functions @@ -62,18 +64,18 @@ nmap = function(ipAddress) else globals.router = get_router( ipAddress ) end if - + if globals.router == null then exit("nmap: ip address not found") - + isRouterIp = globals.router.local_ip == ipAddress ports = null - + if not isLanIp or isRouterIp then ports = globals.router.used_ports else - ports = globals.router.computer_ports(ipAddress) + ports = globals.router.device_ports(ipAddress) end if - + return ports end function // END functions definitions @@ -92,13 +94,13 @@ for port in ports lib = getLib(ipAddress, port) end if libId = lib.lib_name + "_" + lib.version - + existingVulnerabilityFile = getFile(globals.vulnerabilitiesDirectoryName, libId) if (existingVulnerabilityFile != null) then print("Vulnerability file '" + libId + "' already existing, skipping") continue end if - + if (scannedLibs.indexOf(libId) != null) then continue else @@ -143,7 +145,7 @@ for port in ports vuln._setVuln(addressForThoseVulnerabilitys, vulnerability) vulnerabilitiesArray.push(vuln) end for - + end for end for @@ -156,7 +158,7 @@ for vulnerability in vulnerabilitiesArray filePath = vulnerability._getFilePath fileName = vulnerability.libName + "_" + vulnerability.libVersion + "_" + md5(vulnerability.vulnUnsecValue) + ".json" myshell.host_computer.touch(filePath, fileName) - + vulnerabilityFile = myshell.host_computer.File(filePath + fileName) vulnerabilityFile.set_content("") vulnerabilityFile.set_content(vulnerabilityFile.content + char(10) + toJSON(vulnerability)) diff --git a/scripts/defense/backdoor.gs b/scripts/defense/backdoor.gs new file mode 100644 index 0000000000000000000000000000000000000000..1c1de3721b1b5c94aa2714cadd0d5b5159c2b239 --- /dev/null +++ b/scripts/defense/backdoor.gs @@ -0,0 +1,5 @@ +// Untested! +// This file has only been merged into master because it depended on the Repo Unification Process +// Which caused a lot of merge conflicts, so reducing merge requests made life easier for everybody at the time + +"#import libs/utils.inc.src" diff --git a/scripts/defense/colony.gs b/scripts/defense/colony.gs new file mode 100644 index 0000000000000000000000000000000000000000..1f6c022d724862e29015d4e83363f90533ba4f3a --- /dev/null +++ b/scripts/defense/colony.gs @@ -0,0 +1,25 @@ +"#import libs/utils.inc.src" +"#import libs/file.inc.src" +"#import libs/remote.inc.src" + +// Tool to send to rented servers the default binaries from computers +// Note that the utility methods to transfer a file only accepts complete path +// "connect" and "transfer" should be easy reusable for a code pulling tool (issue #7) + +//command: colony +length = imports.utils.ParamLength(params) +if length < 3 or length > 5 or imports.utils.HasFlag(params, "h", "help") then exit("<b>Usage: "+imports.utils.GetProgName()+" [user] [password] [ip] [(opt) port] [(opt) service]</b>") +comp = get_shell.host_computer + +user = imports.utils.GetParam(params, 0) +password = imports.utils.GetParam(params, 1) +ip = imports.utils.GetParam(params, 2) +port = imports.utils.GetParam(params, 3) +service = imports.utils.GetParam(params, 4) + +remote = imports.remote.connect(get_shell, user, password, ip, port, service) +if not remote then exit("Can't connect to remote server") +for path in imports.file.MISSING + result = imports.remote.upload(remote, path, path[:path.lastIndexOf("/")]) + if typeof(result) == "string" then print(result) else print("Sent to "+result.path) +end for diff --git a/scripts/defense/guestdo.gs b/scripts/defense/guestdo.gs new file mode 100644 index 0000000000000000000000000000000000000000..9478f641483db324ba00337d4e19e4f842089bd9 --- /dev/null +++ b/scripts/defense/guestdo.gs @@ -0,0 +1,38 @@ +// Untested! +// This file has only been merged into master because it depended on the Repo Unification Process +// Which caused a lot of merge conflicts, so reducing merge requests made life easier for everybody at the time + +"#import utils.inc.src" + +utils = imports.utils +exit = @utils.Exit + +// TODO: determine the exploit to use in current version (and the lib too) +MEM = "" +VAL = "" +if not MEM or not VAL then exit("No suitable guest exploit found yet!") + +metaxploit = utils.IncludeLib("metaxploit.so") +comp = utils.Escalate().host_computer + +NAME = "guest.so" +DIR = "/root/Downloads/" +PATH = NAME+DIR +lib = comp.File(PATH) +if not lib then exit("No lib available at "+PATH) + +if not utils.UserPrompt("Are you sure you want to switch this Terminal into a guest access?") then exit("Execution cancelled") + +DIR = "/libs/" +PATH = NAME+DIR + +if typeof(lib.copy(DIR, NAME)) == "file" then lib = comp.File(PATH) else lib = null +if not lib then exit("Unable to copy "+NAME) + +metalib = metaxploit.load(PATH) +if not metalib then exit(NAME+" is not a library!?") +guest = metalib.overflow(MEM, VAL) +lib.delete() + +if not guest then exit("Exploit failed!?") +guest.start_terminal() \ No newline at end of file diff --git a/logincleanup.src b/scripts/defense/logincleanup.src similarity index 100% rename from logincleanup.src rename to scripts/defense/logincleanup.src diff --git a/setup.src b/scripts/defense/setup.gs similarity index 89% rename from setup.src rename to scripts/defense/setup.gs index 7422b7c33e11eb5d36b076ccffc7dd679bb35ee5..fa6d6934699e69efd6a8b6443f1499353b879a5c 100644 --- a/setup.src +++ b/scripts/defense/setup.gs @@ -1,3 +1,5 @@ +"#import libs/utils.inc.src" + // Can create two limited users : ssh and ftp (when optional passwords are provided) // Make sure to have created the custom remote and members accounts before that // For the exact effects on permissions, see https://usine.solution-libre.fr/qtg/grey-hack/-/issues/9 @@ -5,29 +7,6 @@ // !!! This program will self-delete after use !!! // Note : chmodding takes a bit of time for unknown reasons (and GH doesn't show prints while running) // Expect ONE MINUTE or so until the single print statement shows up - -// Meant for preprocessor use -imports = {} -imports.utils = {} -imports.utils.GetProgName = function() - return program_path.split("/")[-1] -end function -imports.utils.IsRoot = function() - return active_user == "root" -end function - -imports.utils.Exit = function(reason) - exit(imports.utils.GetProgName()+": "+reason) -end function -imports.utils.GetParam = function(params, index) - if index < 0 or index >= imports.utils.ParamLength(params) then return null - return params[index] -end function -imports.utils.HasFlag = function(params, short, long) - if imports.utils.ParamLength(params) == 0 then return null - param = params[0] - return param == "-"+short or param == "--"+long -end function imports.temp = {} imports.file = {} @@ -194,7 +173,7 @@ Safe(USER_GROUP, imports.file.ALLOWED) Safe(SSH_GROUP, imports.file.SSH) Safe(FTP_GROUP, imports.file.FTP) // Normally no-op -comp.File(program_path).delete +imports.utils.SelfDestruct() // #2.2: It would be a good idea to delete/reset (...), just in case. and the log file too. WipeDir("/var/system.log") diff --git a/scripts/libs/antilogs.inc.src b/scripts/libs/antilogs.inc.src new file mode 100644 index 0000000000000000000000000000000000000000..125569f2d9b89c499e013017b5cfb597951be27a --- /dev/null +++ b/scripts/libs/antilogs.inc.src @@ -0,0 +1,58 @@ +// Untested! +// This file has only been merged into master because it depended on the Repo Unification Process +// Which caused a lot of merge conflicts, so reducing merge requests made life easier for everybody at the time + +"#ifbuild" +if not globals.hasIndex("imports") then imports = {} +imports.temp = {} +"#endif" +imports.antilogs = {} +"#ifbuild" +antilogs = imports.antilogs +"#endif" + +imports.antilog.ENABLED = true + +imports.antilog.cache = null + +imports.antilog.check = function() + t = imports.antilog // this + if not t.ENABLED then return null + + comp = get_shell.host_computer + utils = imports.utils + if not utils.FileAccess(comp.File("/var/"), "r") then return null + + if not utils.FileAccess(comp.File(user_folder+"/.Trash/),"w") then + if not utils.FileAccess(comp.File(user_folder)," w") then return null + if not comp.create_folder(user_folder,".Trash") then return null + end if + + log = comp.File("/var/system.log") + if utils.FileAccess(log,"w") then return log + return null +end function + +imports.antilog.store = function(force=false) + cache = imports.antilog.cache + if cache != null then + if not force then return + cache.delete() +end if + +imports.antilog.refresh = function() + log = imports.antilog.check() + if not log then return + + NAME="system.log" + PATH = user_folder+"/.Trash/" + if typeof(log.copy(PATH,NAME)) == "string" then return + imports.antilog.cache = comp.File(PATH+"/"+NAME) +end function + +imports.antilog.rollback = function() + if not imports.antilog.check() then return + cache = imports.antilog.cache + if not cache then return + cache.copy("/var/","system.log") +end function \ No newline at end of file diff --git a/scripts/libs/file.inc.src b/scripts/libs/file.inc.src index 13b94d48de01bdee38875e20c4c1ef5322f5d0d2..cf6bf7b3724bd14449e455a39f47ac2287b525fd 100644 --- a/scripts/libs/file.inc.src +++ b/scripts/libs/file.inc.src @@ -175,6 +175,10 @@ imports.file.FileAccess = function(file, perms, shout=true) if not file then return false for i in range(0,perms.len-1) perm = perms[i] + + // Ugly hack: directories don't need r or x permission to enumerate files + if file.is_folder and perm != "w" then continue + if file.has_permission(perm) then continue if shout then imports.utils.Print("Error: can't use ('"+perm+"') contents of '"+file.path+"'") return false @@ -183,8 +187,8 @@ imports.file.FileAccess = function(file, perms, shout=true) end function // Tries deleting a file, but checks that you have the required permissions first (returns false if unallowed) -imports.file.Delete = function(file) - if not imports.file.FileAccess(file) then return false +imports.file.delete = function(file) + if not imports.file.FileAccess(file.parent,"w") then return false file.delete() return true end function @@ -193,6 +197,12 @@ imports.file.GetDir = function(path) if typeof(path) == "file" then path = path.path return path[0:path.lastIndexOf("/")] end function +// Like GetDir but return a file instead of a path +// Unlike GetDir, the result doesn't change if the file is already a folder! +imports.file.GetDirRef = function(folder) + if folder.is_folder then return folder + return folder.parent +end function // Determines the filename from a String path imports.file.GetName = function(path) if typeof(path) == "file" then path = path.path diff --git a/scripts/libs/filereaper.inc.src b/scripts/libs/filereaper.inc.src index 6728003e8b998b108973f23d20acc7441ef53ce0..983092814c162b76cc77332eea7fefa250689de8 100644 --- a/scripts/libs/filereaper.inc.src +++ b/scripts/libs/filereaper.inc.src @@ -1,5 +1,5 @@ -"#import utils.src" -"#import file.src" +"#import libs/utils.src" +"#import libs/file.src" "#ifbuild" if not globals.hasIndex("imports") then imports = {} @@ -19,14 +19,14 @@ filereaper = imports.filereaper imports.filereaper.FindFile = function(origin, children) if origin == null then return null // May be available through another user - if not imports.file.FileAccess(origin, "r") then return false + if not imports.file.FileAccess(origin, "r") then return false for child in children if typeof(origin) != "file" then return origin origin = imports.filereaper._FindFile(origin, child) end for return origin end function -imports.filereaper._FindFile = function(origin, child) +imports.filereaper._FindFile = function(origin, child) found = null for file in origin.get_files() if file.name == child then @@ -100,7 +100,7 @@ end function imports.filereaper.LoadPasswdList = function(pars) state = pars[0] creds = pars[1] - + for cred in creds imports.filereaper.AddPasswd([state,cred]) end for @@ -176,30 +176,30 @@ imports.filereaper.exploitFile = function(pars, file, targetRoot=true) if imports.filereaper.exploitFile(pars, file.parent, targetRoot) == true then return true end if if not imports.file.FileAccess(file, "r") then return false - + ACC_OK = @imports.filereaper.UseAccFile ACC_FAIL = @imports.filereaper.MissingAcc PASS_OK = @imports.filereaper.UsePasswdFile PASS_FAIL = @imports.filereaper.MissingPasswdList - + if file.path == "/" then imports.filereaper.HandleFile(file, ["etc","passwd"], @PASS_OK, @PASS_FAIL, [state]) imports.filereaper.HandleFile(file, ["root","Config","Bank.txt"], @ACC_OK, @ACC_FAIL, [state, "root", true]) imports.filereaper.HandleFile(file, ["root","Config","Mail.txt"], @ACC_OK, @ACC_FAIL, [state, "root", false]) - + home = imports.filereaper._FindFile(file, ["home"]) imports.filereaper.HandleFile(home, [], null, @imports.filereaper.MissingUserList, [state]) if typeof(home) == "file" then imports.filereaper.exploitFile(pars, home, false) return true end if - + if imports.utils.starts_with(file.path, "/etc/") then pasd = null if file.path == "/etc/" then pasd = file if file.path == "/etc/passwd" then pasd = imports.filereaper._FindFile(file, ["passwd"]) imports.filereaper.HandleFile(pasd, [], @PASS_OK, @PASS_FAIL, [state, pasd]) end if - + if imports.utils.starts_with(file.path, "/home/") then count = imports.utils.char_count(file.path,"/") if count == 2 then @@ -209,12 +209,12 @@ imports.filereaper.exploitFile = function(pars, file, targetRoot=true) else if count == 3 then imports.filereaper.AddUser(file.name) end if - else if imports.utils.starts_with(file.path, "/root/") then + else if imports.utils.starts_with(file.path, "/root/") then count = imports.utils.char_count(file.path,"/")+1 else count = 0 //or return end if - + if count == 4 and file.name == "Config" then imports.filereaper.HandleFile(file, ["Bank.txt"], @ACC_OK, @ACC_FAIL, [state, file.parent.name, true]) imports.filereaper.HandleFile(file, ["Mail.txt"], @ACC_OK, @ACC_FAIL, [state, file.parent.name, false]) diff --git a/scripts/tools/jsonparser.gs b/scripts/libs/models/jsonparser.gs similarity index 100% rename from scripts/tools/jsonparser.gs rename to scripts/libs/models/jsonparser.gs diff --git a/scripts/tools/utils.gs b/scripts/libs/models/utils.gs similarity index 100% rename from scripts/tools/utils.gs rename to scripts/libs/models/utils.gs diff --git a/scripts/models/vuln.gs b/scripts/libs/models/vuln.gs similarity index 100% rename from scripts/models/vuln.gs rename to scripts/libs/models/vuln.gs diff --git a/scripts/libs/passwords.inc.src b/scripts/libs/passwords.inc.src index b1247746505167966e223a8c4a1d65c0a7ae6b34..82d580fe10db2073b2e784f2a35489c866f6a107 100644 --- a/scripts/libs/passwords.inc.src +++ b/scripts/libs/passwords.inc.src @@ -1,5 +1,5 @@ -"#import utils.inc.src" -"#import file.inc.src" +"#import libs/utils.inc.src" +"#import libs/file.inc.src" "#ifbuild" if not globals.hasIndex("imports") then imports = {} diff --git a/scripts/libs/qtglogo.inc.src b/scripts/libs/qtglogo.inc.src new file mode 100644 index 0000000000000000000000000000000000000000..896ec8723e2ff4c0563a2265a8fde32797591259 --- /dev/null +++ b/scripts/libs/qtglogo.inc.src @@ -0,0 +1,69 @@ +"#import libs/ui.inc.src" + +printLogo = function() + R = @imports.ui.Repeat + J = function(text) + return imports.ui.Color("#f4ae34",text) + end function + B = function(text) + return imports.ui.Color("#1a508d",text) + end function + N = function(text) + return imports.ui.Color("#182d53",text) + end function + + // Bord droit + temp = "&%%%" + D = " "+temp + // Bord gauche + G = temp+"& " + // Taille totale + L = 80 + // Ligne vide + V = R(" ",L-G.len-D.len) + + // Haut du moniteur + print(B(R(" ", 6)+R("&", L-6-5)+R(" ", 5))) + print(B(" "+"&"+R("%", L-2-1)+" ")) + print(B("&"+R("%", 4)+R(" ", L-5-4)+R("%", 4))) + + // Dessus vide + for i in range(1,5) + print(B(G+V+D)) + end for + + // Pour simplifier un peu... + R4=R(" ",4) + R5=R(" ",5) + R17=R(" ",17) + + // Source : univscan.gs + print(B(G+R5+ J(",***,***,***,***, ") +" "+ R17 +" "+R5+ J("***,***,***,***,*") +D)) + print(B(G+R5+ J("*")+"%%%%%%%%%%%%%%"+J("** ") +" "+ R17 +" "+R5+ J("**")+"%%%%%%%%%%%%%"+J("**") +D)) + print(B(G+ J("******")+"%%%%%%%%%%%%%%"+J("*****,") +" "+ J("**************,**") +" "+ J("*******")+"%%%%%%%%%%%%%"+J("**") +D)) + print(B(G+ J("**")+"%%%%%"+J("*, **")+"%%%%"+J("*,") +" "+J("**")+"%%%%%%%%%%%%%"+J("**")+" "+ J("**")+"%%%%%"+J("**") +R(" ",13)+D)) + print(B(G+ J("*,")+"%%%%%"+J("*, **")+"%%%%"+J("*,") +" "+J("******,")+"%%%%"+J("***,**")+" "+ J("**")+"%%%%%"+J("****")+"%%%%"+J("**") +R5+D)) + print(B(G+ J("**")+"%%%%%"+J("*,******** **")+"%%%%"+J("*,") +" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+J("**")+"%%%%%"+J("****")+"%%%%"+J("*******")+D)) + print(B(G+J("**")+"%%%%%"+J("*,,*")+"%%%%"+J("** **")+"%%%%"+J("*,")+" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+J("**")+"%%%%%"+J("*****,**")+"%%%%%"+J("**")+D)) + print(B(G+J("**")+"%%%%%"+J("****")+"%%%%"+J("*****")+"%%%%"+J("*,")+" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+J("**")+"%%%%%"+J("*****,**")+"%%%%%"+J("**")+D)) + print(B(G+ J("*,*,*,")+"*%%%%%%%%%%%%%"+J("*,*,*,") +" "+R5+ J("*,")+"%%%%"+J("*,") +R4+" "+ J(",*,*,*,")+"%%%%%%%%%%%%%"+J(",*") +D)) + print(B(G+R5+ J("**")+"%%%%%%%%%%%%%"+J("*****,") +" "+R5+ J("**")+"%%%%"+J("**") +R4+" "+R5+ J("**")+"%%%%%%%%%%%%%"+J("**") +D)) + print(B(G+R5+ J("****,**********")+"%%%%"+J("*,") +" "+R5+ J("********") +R4+" "+R5+ J("*******,*********") +D)) + print(B(G+R(" ",18)+ J("**####*,") +R(" ", 41)+D)) + + // Dessous vide + for i in range(1,4) + print(B(G+V+D)) + end for + + // Bas du moniteur + print(B("@"+R("%",L-1))) + print(B(R(" ",4)+"&"+R("%",L-5-2)+" ")) + print(R(" ",L)) + + // Support du moniteur + for i in range(1,2) + print(N(R(" ", 31)+R("&",L-31-29)+R(" ",29))) + end for + print(B(R(" ",17)+R("%",L-17-16)+R(" ",16))) +end function diff --git a/scripts/libs/remote.inc.src b/scripts/libs/remote.inc.src index 0dd9cc5d99202912c21d1e028a815b8614c1f3bf..16e1211967a964dfdb88425a803e6d0c0a4ad6be 100644 --- a/scripts/libs/remote.inc.src +++ b/scripts/libs/remote.inc.src @@ -1,3 +1,5 @@ +"#import libs/file.inc.src" + "#ifbuild" if not globals.hasIndex("imports") then imports = {} imports.temp = {} @@ -14,7 +16,7 @@ imports.remote.LoadFromCache = function(key, shell, user, pass, ip) imports.remote.cache[key] = result return result end function - + imports.remote.servers = {} imports.remote.servers.FILES = function() return imports.remote.LoadFromCache("files", get_shell, "root", "Helby", "220.47.69.119") @@ -99,24 +101,24 @@ end function // if not imports.utils.UserPrompt("Acceptez-vous de transférer non-anonymement?") then exit() // anon = false // end if - + // if dest[dest.len-1] != "/" then dest = dest + "/" // origin = imports.file.AbsolutePath(origin, null, sourceShell) - + // comp = sourceShell.host_computer // src = comp.File(origin) // if src == null then // print(origin+" doesn't exist on source server") // return null // end if - + // fileName = origin[origin.lastIndexOf("/")+1:] // destPath = dest+fileName // if targetShell.host_computer.File(destPath) != null then // print(destPath+" already exists on target server") // return null // end if - + // temp = null // if anon then // comp.create_folder("/", "server") @@ -128,13 +130,13 @@ end function // if targetShell.host_computer.File(dest+fileName) != null then continue // break // end while - + // DANGER: cette ligne fait remplacer votre harddrive par celui du serveur!? // src.copy("/server/temp/", fileName) // temp = comp.File("/server/temp/"+fileName) // origin = temp.path // end if - + // result = sourceShell.scp_upload(origin, dest, targetShell) // if temp != null then temp.delete() // return targetShell.host_computer.File(destPath) @@ -153,42 +155,36 @@ imports.remote.download = function(shell, origin, dest, destName=null) destName = null end if // TODO: temporary limiter ends here - - temp = imports.remote.PreTransfer(origin, dest) + + temp = imports.remote.PreTransfer(origin, dest, shell, get_shell) origin = temp[0] dest = temp[1] if destName != null then server = shell.host_computer - if not imports.remote.CheckTempFolder(server) then - print("ERROR: unable to write in /server/temp/") - return null - end if - + if not imports.remote.CheckTempFolder(server) then return "unable to write in /server/temp/" + src = server.File(origin) - if src == null then - print(origin+" doesn't exist on source server") - return null - end if - + if src == null then return origin+" doesn't exist on source server" + destName = imports.remote.RandomName(server, get_shell.host_computer, dest, destName) - + // DANGER: cette ligne fait remplacer votre harddrive par celui du serveur!? src.copy("/server/temp/", destName) origin = "/server/temp/"+destName end if - + result = imports.remote.transfer(shell, get_shell, origin, dest) - + if destName != null then src.delete() - + return result end function // Upload a file with scp if it doesn't already exist // Can also use a different name than the original file : if said name is blank, a random name will be generated imports.remote.upload = function(shell, origin, dest, destName=null) - + // TODO : remove this limiter when the GH issue gets fixed if destName != null then print("Les téléchargements renommés font reset les harddrives suite à un bug") @@ -198,47 +194,41 @@ imports.remote.upload = function(shell, origin, dest, destName=null) destName = null end if // TODO: temporary limiter ends here - - temp = imports.remote.PreTransfer(origin, dest) + + temp = imports.remote.PreTransfer(origin, dest, get_shell, shell) origin = temp[0] dest = temp[1] transferDest = dest - + if destName != null then server = shell.host_computer - if not imports.remote.CheckTempFolder(server) then - print("ERROR: unable to write in /server/temp/") - return null - end if - + if not imports.remote.CheckTempFolder(server) then return "unable to write in /server/temp/" + if dest[dest.len-1] != "/" then dest = dest + "/" // The destination file doesn't need to be available in temp folder // Also, in this case the server is ALSO the target destName = imports.remote.RandomName(null, server, "", destName) - + src = server.File(dest+destName) - if src != null then - print(dest+destName+" already exists on target server") - return null - end if - + if src != null then return dest+destName+" already exists on target server" + // The temporary folder doesn't need to be available in the target folder folderName = imports.remote.RandomName(server, null, dest, "") // Creates a temporary folder which will receive the file, no matter what its name is server.create_folder("/server/temp/", folderName) transferDest = "/server/temp/"+folderName end if - + result = imports.remote.transfer(get_shell, shell, origin, transferDest) - + if destName != null then // DANGER: cette ligne fait remplacer votre harddrive par celui du serveur!? if result then result.move(dest,destName) // Delete the temporary folder server.File(transferDest).delete() end if - + return result end function @@ -247,30 +237,25 @@ end function // Returns : the new file, or NULL imports.remote.transfer = function(sourceShell, targetShell, origin, dest) src = sourceShell.host_computer.File(origin) - if src == null then - print(origin+" doesn't exist on source server") - return null - end if - + if src == null then return origin+" doesn't exist on source server" + fileName = origin[origin.lastIndexOf("/")+1:] - + destPath = dest+fileName comp = targetShell.host_computer - - if comp.File(destPath) != null then - print(destPath+" already exists on target server") - return null - end if - - result = sourceShell.scp_upload(origin, dest, targetShell) - if result != true then print("scp_upload error: "+result) + + if comp.File(destPath) != null then return destPath+" already exists on target server" + + result = sourceShell.scp(origin, dest, targetShell) + if result != true then return result return comp.File(destPath) end function -imports.remote.PreTransfer = function(origin, dest) +imports.remote.PreTransfer = function(origin, dest, originShell, destShell) if dest[dest.len-1] != "/" then dest = dest + "/" - origin = imports.file.AbsolutePath(origin, null, sourceShell) - dest = imports.file.AbsolutePath(dest, null, targetShell) + origin = imports.file.AbsolutePath(origin, null, originShell) + dest = imports.file.AbsolutePath(dest, null, destShell) + return [origin, dest] end function // Returns false if /server/temp/ is not usable diff --git a/scripts/libs/ui.inc.src b/scripts/libs/ui.inc.src index c974f1263689043ead61a5c8da02b70478be4544..7730021a3018f44e225f4ed5319f5a8bbb69cb68 100644 --- a/scripts/libs/ui.inc.src +++ b/scripts/libs/ui.inc.src @@ -1,6 +1,5 @@ -"#import utils.inc.src" -"#import file.inc.src" -"#import json.inc.src" +"#import libs/utils.inc.src" +"#import libs/file.inc.src" "#ifbuild" if not globals.hasIndex("imports") then imports = {} @@ -101,7 +100,6 @@ imports.ui.Repeat = function(char, len) for i in range(0,len-1) result = result + char end for - print("!"+result+"!") return result end function diff --git a/scripts/libs/utils.inc.src b/scripts/libs/utils.inc.src index c1f0c48e4dad1f92d4086595983f239b57de5349..d93b2b659d00cb9dcb39ef196cdfe3eabd8739cc 100644 --- a/scripts/libs/utils.inc.src +++ b/scripts/libs/utils.inc.src @@ -1,6 +1,6 @@ // Only used for ONE method, choice left to the main script -//"#import dict.inc.src" -//"#import remote.inc.src" +//"#import libs/dict.inc.src" +//"#import libs/remote.inc.src" "#ifbuild" if not globals.hasIndex("imports") then imports = {} @@ -58,6 +58,13 @@ end function imports.utils.IsRoot = function() return active_user == "root" end function +imports.utils.Escalate = function(mendatory=true) + if imports.utils.IsRoot() then return get_shell + password = user_input("Please enter root password: ") + result = get_shell("root", password) + if mendatory and not result then exit("Unable to log as root") + return result +end function imports.utils.Print = function(reason) print(imports.utils.GetProgName()+": "+reason) @@ -151,36 +158,36 @@ imports.utils.Choice = function(choices, reason=null) end function imports.utils.HASH_SIZE = 32 -imports.utils.GetSafePassword = function(userPass, cryptools, prompt=true) +imports.utils.GetSafePassword = function(userPass, cryptools, prompt=true) if userPass.indexOf(":") != null then data = userPass.split(":") username = data[0] password = data[1] else username = "" - password = userPass + password = userPass end if - + if cryptools and password.len == imports.utils.HASH_SIZE then password = imports.utils._decipher(username, password, cryptools, prompt) - + return [username,password] end function imports.utils._decipher = function(user, hash, cryptools, prompt=true) dict = imports.utils.IsImported("dict") - + if dict then password = dict.decrypt(hash, user, null) // No cryptool if not imports.utils.is_empty(password) then return password end if - + if imports.utils.is_empty(user) then return hash - + print("Decipher required for "+hash) if prompt and not imports.utils.UserPrompt("Do you want to decipher the password of "+user+"?") then print("Cancelled deciphering of "+user+":"+hash) return "" end if - + password = cryptools.decipher(user, hash) if dict and not imports.utils.is_empty(password) then dict.addPass(hash, password) return password diff --git a/scripts/libs/versioning.inc.src b/scripts/libs/versioning.inc.src index b92bdff922ee0ca1f1fd9dd5e503aebcb166a28c..efb4268a8a146a5a44a085b4290623176efbdd19 100644 --- a/scripts/libs/versioning.inc.src +++ b/scripts/libs/versioning.inc.src @@ -1,4 +1,4 @@ -"#import utils.inc.src" +"#import libs/utils.inc.src" "#ifbuild" if not globals.hasIndex("imports") then imports = {} diff --git a/scripts/libs/vshell.inc.src b/scripts/libs/vshell.inc.src new file mode 100644 index 0000000000000000000000000000000000000000..2693b6268d26af67f37cd608d333354697274a75 --- /dev/null +++ b/scripts/libs/vshell.inc.src @@ -0,0 +1,161 @@ +// Untested! +// This file has only been merged into master because it depended on the Repo Unification Process +// Which caused a lot of merge conflicts, so reducing merge requests made life easier for everybody at the time + +"#import libs/utils.inc.src" +"#import libs/file.inc.src" + +"#ifbuild" +if not globals.hasIndex("imports") then imports = {} +imports.temp = {} +"#endif" +imports.vshell = {} +"#ifbuild" +vshell = imports.vshell +"#endif" + +imports.vshell.EXIT = "exit" + +imports.vshell.constrs = {} + +imports.vshell.constrs.shell = function(object) + result = {} + + result.start_terminal = function() + while true + print("Please enter a command:"+imports.file.NEW_LINE) + command = user_prompt().split(" ") + if command[0] == imports.vshell.EXIT then break + cmd = imports.utils.SafeMapAccess(imports.vshell.cmds,command[0]) + if cmd == null then + print(cmd+ " is not a recognized command") + return + end if + + // Remove the command name + params = [] + for i in range(1,command.len-1) + params.push(command[i]) + end for + + heart = result.heart + current_path = result.current_path + + result = cmd(self, params) + if result and typeof(result) != "function" then + print(command[0] +" error: "+result) + // Rollback + result.heart = heart + result.current_path = current_path + end if + end while + end function + + result.navigate = function(path) + isFile = typeof(self.heart) == "file" + if not path then + if isFile then return self.heart + return self.heart.File(current_path) + end if + + path = imports.file.AbsolutePath(path) + + if isFile then + result = imports.vshell.navigate(self.heart, path) + else + result = self.heart.File(path) + end if + + if not imports.file.FileAccess(result,"r") then + print("Error, unable to access the target") + return + end if + folder = imports.file.GetDirRef(result) + if not imports.file.FileAccess(folder,"r") then + print("Error, unable to access the target's folder") + return + end if + + self.current_path = folder.path + if typeof(self.heart) == "file" then self.heart = result + return result + end function + + result.heart = object + + // Init the current_path var + if typeof(object) == "file" then path = object.path else path = object.current_path + result.navigate(path) + + return result +end function + +imports.vshell.navigate = function(file, target) + originSteps = file.path.split("/") + targetSteps = file.path.split("/") + // TODO: File navigation + return null +end function + +imports.vshell.init = function(object) + if typeof(object) == "shell" then object = object.host_computer + type = typeof(object) + if type != "computer" and type != "file" then return null + return imports.vshell.constrs.shell(object) +end function + +imports.vshell.run = function(object) + imports.vshell.init(object).start_terminal() +end function + +imports.vshell.read = function(shell, params) + if params.len > 0 then return "Parameter required" + file = shell.navigate(params[0]) + // TODO: File reading +end function + +imports.vshell.cmds = {} + +imports.vshell.cmds.help = function(shell, params) + names = ["exit"] + for name in imports.vshell.cmds.values + names.put(name) + end for + print("List of accepted commands:") + print(imports.utils.PrintList(names,imports.file.NEW_LINE)) +end function + +imports.vshell.cmds.cd = function(shell, params) + if params.len == 0 then path = "" else path = params[0] + if not shell.navigate(path).is_folder then return "target is not a folder!" + + names = [] + for item in file.get_folders + names = item.name+"/" + end for + for item in file.get_files + names = item.name + end for + + print("List of folders in: "+file.path) + print(imports.utils.PrintList(names,imports.file.NEW_LINE)) +end function + +imports.vshell.cmds.read = function(shell, params) + result = imports.vshell.read(shell,params) + if typeof(result) != "list" then return result + print(imports.utils.PrintList(result,imports.file.NEW_LINE)) +end function + +imports.vshell.cmds.get = function(shell, params) + result = imports.vshell.read(shell,params) + if typeof(result) != "list" then return result + content = imports.utils.PrintList(result,imports.file.NEW_LINE) +end function + +imports.vshell.cmds.delete = function(shell, params) + if params.len > 0 then return "Parameter required" + file = shell.navigate(params[0]) + if not imports.utils.UserPrompt("Do you *REALLY* want to delete '"+file.path+"' ?") then return "Execution cancelled by user" + if not imports.file.delete(file) then return "Permission defined" +end function \ No newline at end of file diff --git a/archive.src b/scripts/tools/archive.src similarity index 83% rename from archive.src rename to scripts/tools/archive.src index 214b750b3fcfd518734921535fd52836a7f0ed7d..eb8ed8b0b3109961434c75307b489c60b5d7903e 100644 --- a/archive.src +++ b/scripts/tools/archive.src @@ -1,38 +1,42 @@ +"#import includes/utils.inc.src" +"#import includes/file.inc.src" + // Used by passing the path of the (txt) archive, then the path of all the files to add // More information at https://usine.solution-libre.fr/qtg/grey-hack/-/issues/6 +"#ifbuild" imports = {} - + // The methods here are "good enough" to work in those cases // For example, the ParamLength normally discards flag-style args // But I don't want to give you all my tricks... yet, at least ;) imports.utils = {} imports.utils.ParamLength = function(params) - if params == null then return 0 + if params == null then return 0 return params.len end function imports.utils.GetParam = function(params, index) - if index < 0 or index >= imports.utils.ParamLength(params) then return null + if index < 0 or index >= imports.utils.ParamLength(params) then return null return params[index] end function imports.utils.HasFlag = function(params, short, long) - if imports.utils.ParamLength(params) == 0 then return null + if imports.utils.ParamLength(params) == 0 then return null param = params[0] return param == "-"+short or param == "-"+long end function // Dynamically getting the name of the command is left as an exercise to the reader :) imports.utils.GetProgName = function() - return program_path.split("/")[-1] + return program_path.split("/")[-1] end function imports.utils.Print = function(reason) print(imports.utils.GetProgName()+": "+reason) end function - + imports.file = {} imports.file.NEW_LINE = char(10) // Disclaimer : brand new method created for this script, may not handle special cases -imports.file.RelativePath = function(path) - if path[0] != "/" then path = get_shell.host_computer.current_path + "/" + path +imports.file.AbsolutePath = function(path) + if path[0] != "/" then path = get_shell.host_computer.current_path + "/" + path return path end function // Should return [] for unavailable files (binary or no read perms) @@ -50,6 +54,20 @@ imports.file.FileAccess = function(file, perm) imports.utils.Print("Error: can't use ('"+perm+"') contents of '"+file.path+"'") return false end function +imports.file.save = function(content, path, name) + data = name.split("/") + if data.len > 1 then + for index in range(0, data.len-2) + name = data[index] + comp.create_folder(path, name) + path = path +"/"+ name + end for + end if + name = data[data.len-1] + comp.touch(path, name) + comp.File(path+"/"+name).set_content(content) +end function +"#endif" // To avoid bruning our eyes with escaping QUOTE = """" @@ -63,6 +81,8 @@ GetLastChar = function(str) end function // Returns the text in the 'unused' string or NULL if not a standalone string StringInstruction = function(str) + if str == null then return null + str = str.trim() if GetLastChar(str) != QUOTE then return null if str[0] != QUOTE then return null str = str[1:str.len-1] @@ -88,7 +108,7 @@ length = imports.utils.ParamLength(params) if length == 0 or imports.utils.HasFlag(params, "h", "help") then exit("<b>Usage: "+imports.utils.GetProgName()+" [file to compress/decompress] [...file paths]</b>") comp = get_shell.host_computer -mainPath = imports.file.RelativePath(imports.utils.GetParam(params, 0) + ".tar") +mainPath = imports.file.AbsolutePath(imports.utils.GetParam(params, 0) + ".tar") mainFile = comp.File(mainPath) temp = mainPath.lastIndexOf("/") @@ -108,7 +128,7 @@ if mainFile == null then // Read all files in order and add them for i in range(1,length-1) - path = imports.file.RelativePath(imports.utils.GetParam(params, i)) + path = imports.file.AbsolutePath(imports.utils.GetParam(params, i)) // Get the name of the file name = path[path.lastIndexOf("/")+1:] @@ -131,7 +151,7 @@ if mainFile == null then content = content + imports.file.NEW_LINE + line end for end for - + mainFile.set_content(content) print("Archive is now available") else @@ -149,40 +169,28 @@ else content = "" nextLine = false - CreateFile = function(path, name, content) - data = name.split("/") - for index in range(0, data.len-2) - name = data[index] - comp.create_folder(path, name) - path = path +"/"+ name - end for - name = data[data.len-1] - comp.touch(path, name) - comp.File(path+"/"+name).set_content(content) - end function - for line in lines temp = ArchiveName(line) // New file if temp != null then - if currentName != null then CreateFile(path, currentName, content) + if currentName != null then imports.file.save(content, path, currentName) currentName = temp content = "" nextLine = false continue end if - + if nextLine then content = content + imports.file.NEW_LINE else nextLine = true end if - + content = content + line - + end for - CreateFile(path, currentName, content) + imports.file.save(content, path, currentName) print("Unarchiving completed") -end if \ No newline at end of file +end if diff --git a/breakhash.src b/scripts/tools/breakhash.gs similarity index 62% rename from breakhash.src rename to scripts/tools/breakhash.gs index 3fa66da86fc6d8fb3b7f8d02e7d6f1b31a9120f7..98c961b9ee44be680eb38447bd1f9f5011a12e73 100644 --- a/breakhash.src +++ b/scripts/tools/breakhash.gs @@ -1,43 +1,4 @@ - -if not globals.hasIndex("imports") then - imports = {} - imports.utils = {} - - imports.utils.Exit = function(reason) - exit(imports.utils.GetProgName()+": "+reason) - end function - - imports.utils.ParamLength = function(params) - length = 0 - for param in params - if param[0] != "-" then length = length + 1 - end for - return length - end function - imports.utils.GetParam = function(params, index) - i = 0 - for param in params - if param[0] == "-" then continue - if (i == index) then return param - i = i+1 - end for - return null - end function - imports.utils.HasFlag = function(params, short, long) - for param in params - if param[0:1] == "--" then - if slice(param,2) == long then return true - else if param[0] == "-" then - if slice(param,1) == short then return true - end if - end for - return false - end function - - imports.utils.Pause = function() - user_input("Press ENTER to continue") - end function -end if +"#import libs/utils.inc.src" //command: breakhash length = imports.utils.ParamLength(params) @@ -103,4 +64,4 @@ for length in range(minLen,maxLen) imports.utils.Pause() end for -imports.utils.Exit("Not found under those parameters!") \ No newline at end of file +imports.utils.Exit("Not found under those parameters!") diff --git a/decipher2.src b/scripts/tools/decipher2.src similarity index 100% rename from decipher2.src rename to scripts/tools/decipher2.src diff --git a/scripts/tools/scanlib2.src b/scripts/tools/scanlib2.src new file mode 100644 index 0000000000000000000000000000000000000000..19b59b76f4619228e24229dff5f947cebff14965 --- /dev/null +++ b/scripts/tools/scanlib2.src @@ -0,0 +1,44 @@ +//command scanlib +if params.len != 1 or params[0] == "-h" or params[0] == "--help" then exit(command_info("scanlib_usage")) +metaxploit = include_lib("/lib/metaxploit.so") +if not metaxploit then exit("Error: Missing metaxploit library") +libFile = get_shell.host_computer.File(params[0]) +// First modification : remote scanning +if not libFile then + metaLib = null + if params[0].indexOf(":") != null then + data = params[0].split(":") + metaLib = metaxploit.net_use(data[0], data[1].to_int).dump_lib + end if + if not metaLib then exit("can't find library: " + params[0]) +else + metaLib = metaxploit.load(libFile.path) +end if +print("Scanning memory address...") +listMem = metaxploit.scan(metaLib) +// Second modification : looping in order to reuse the results from the scan+exit on input +while true + print("0: EXIT") + index = 1 + for itemMem in listMem + print(index +": [" + itemMem + "]") + index = index + 1 + end for + if listMem.len == 0 then exit("Scan completed: No issues detected.") + + print("Scan completed: detected issues in " + listMem.len + " memory zones.") + option = "" + inputOk = false + while( not inputOk ) + option = user_input("Select memory index: ").to_int + if typeof(option) != "number" or (option < 1 or option > listMem.len) then + // Third modification : exit on input + if option == 0 then exit() + print("Invalid input. Type a valid number") + else + inputOk = true + end if + end while + print("Scanning for vulnerabilities at memory zone: " + listMem[option - 1]) + print(metaxploit.scan_address(metaLib, listMem[option - 1])) +end while