Esempio n. 1
0
    def invoke(self, ctlcode, value, outlength=0x1000):
        device_handle = KERNEL32.CreateFileA(
            "\\\\.\\%s" % self.pipepath, GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE, None, OPEN_EXISTING, 0,
            None) % 2**32

        if device_handle == 0xffffffff:
            # Only report an error if the error is not "name not found",
            # indicating that no kernel analysis is currently taking place.
            if KERNEL32.GetLastError() != 2:
                log.warning("Error opening handle to driver (%s): %d!",
                            driver_name, KERNEL32.GetLastError())
            return False

        out = ctypes.create_string_buffer(outlength)
        length = ctypes.c_uint()

        ret = KERNEL32.DeviceIoControl(device_handle, ctlcode, value,
                                       len(value), out, ctypes.sizeof(out),
                                       ctypes.byref(length), None)
        KERNEL32.CloseHandle(device_handle)

        if not ret:
            log.warning("Error performing ioctl (0x%08x): %d!", ctlcode,
                        KERNEL32.GetLastError())
            return False

        return out.raw[:length.value]
Esempio n. 2
0
    def run(self):
        while self.do_run:
            flags = FILE_FLAG_WRITE_THROUGH
            if self.message:
                pipe_handle = KERNEL32.CreateNamedPipeA(
                    self.pipe_name, PIPE_ACCESS_DUPLEX | flags,
                    PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
                    PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 0, None)
            else:
                pipe_handle = KERNEL32.CreateNamedPipeA(
                    self.pipe_name, PIPE_ACCESS_INBOUND | flags,
                    PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
                    PIPE_UNLIMITED_INSTANCES, 0, BUFSIZE, 0, None)

            if pipe_handle == INVALID_HANDLE_VALUE:
                log.warning("Error opening logging pipe server.")
                continue

            if KERNEL32.ConnectNamedPipe(pipe_handle, None) or \
                    KERNEL32.GetLastError() == ERROR_PIPE_CONNECTED:
                handler = self.pipe_handler(pipe_handle, **self.kwargs)
                handler.daemon = True
                handler.start()
                self.handlers.add(handler)
            else:
                KERNEL32.CloseHandle(pipe_handle)
Esempio n. 3
0
def spCreateProcessW(application_name, command_line, process_attributes,
                     thread_attributes, inherit_handles, creation_flags,
                     environment, current_directory, startup_info):
    class STARTUPINFO(Structure):
        _fields_ = [
            ("cb", c_uint),
            ("reserved1", c_void_p),
            ("desktop", c_void_p),
            ("title", c_void_p),
            ("unused1", c_uint * 7),
            ("flags", c_uint),
            ("show_window", c_uint16),
            ("reserved2", c_uint16),
            ("reserved3", c_void_p),
            ("std_input", c_void_p),
            ("std_output", c_void_p),
            ("std_error", c_void_p),
        ]

    class PROCESS_INFORMATION(Structure):
        _fields_ = [
            ("process_handle", c_void_p),
            ("thread_handle", c_void_p),
            ("process_identifier", c_uint),
            ("thread_identifier", c_uint),
        ]

    class Handle(int):
        def Close(self):
            KERNEL32.CloseHandle(self)

    if environment:
        environment = "\x00".join("%s=%s" % (k, v)
                                  for k, v in environment.items()) + "\x00\x00"

    si = STARTUPINFO()
    si.cb = sizeof(STARTUPINFO)

    if startup_info:
        si.flags = startup_info.dwFlags
        si.show_window = startup_info.wShowWindow

    if si.flags & STARTF_USESTDHANDLES:
        si.std_input = cast(int(startup_info.hStdInput), c_void_p)
        si.std_output = cast(int(startup_info.hStdOutput), c_void_p)
        si.std_error = cast(int(startup_info.hStdError), c_void_p)

    pi = PROCESS_INFORMATION()

    result = KERNEL32.CreateProcessW(application_name, command_line, None,
                                     None, inherit_handles, creation_flags,
                                     environment, current_directory, byref(si),
                                     byref(pi))
    if not result:
        # TODO We'll just assume this is correct for now.
        raise WindowsError(KERNEL32.GetLastError())

    return (Handle(pi.process_handle), Handle(pi.thread_handle),
            pi.process_identifier, pi.thread_identifier)
Esempio n. 4
0
    def _read_message(self, buf):
        """Reads a message."""
        bytes_read = c_uint()
        ret = ""

        while True:
            success = KERNEL32.ReadFile(self.pipe_handle, byref(buf),
                                        sizeof(buf), byref(bytes_read), None)

            if KERNEL32.GetLastError() == ERROR_MORE_DATA:
                ret += buf.raw[:bytes_read.value]
            elif success:
                return ret + buf.raw[:bytes_read.value]
            else:
                return
Esempio n. 5
0
    def run(self):
        buf = create_string_buffer(BUFSIZE)
        bytes_read = c_uint()
        pid = c_uint()

        # The first four bytes indicate the process identifier. In case the
        # pipe handle is closed in an unknown way, reopening one and
        # specifying the same process identifier will reuse the same socket,
        # thus making it look like as if it was never closed in the first
        # place.
        success = KERNEL32.ReadFile(self.pipe_handle, byref(pid), sizeof(pid),
                                    byref(bytes_read), None)

        if not success or bytes_read.value != sizeof(pid):
            log.warning("Unable to read the process identifier of this "
                        "log pipe instance.")
            KERNEL32.CloseHandle(self.pipe_handle)
            return

        if self.active.get(pid.value):
            log.warning("A second log pipe handler for an active process is "
                        "being requested, denying request.")
            KERNEL32.CloseHandle(self.pipe_handle)
            return

        if pid.value:
            sock = self.sockets.get(pid.value)
            if not sock:
                sock = socket.create_connection(self.destination)
                self.sockets[pid.value] = sock

            self.active[pid.value] = True
        else:
            sock = socket.create_connection(self.destination)

        open_handles.add(sock)

        while self.do_run:
            success = KERNEL32.ReadFile(self.pipe_handle, byref(buf),
                                        sizeof(buf), byref(bytes_read), None)

            if success or KERNEL32.GetLastError() == ERROR_MORE_DATA:
                try:
                    sock.sendall(buf.raw[:bytes_read.value])
                except socket.error as e:
                    if e.errno != errno.EBADF:
                        log.warning("Failed socket operation: %s", e)
                    break

            # If we get the broken pipe error then this pipe connection has
            # been terminated for one reason or another. So break from the
            # loop and make the socket "inactive", that is, another pipe
            # connection can in theory pick it up. (This will only happen in
            # cases where malware for some reason broke our pipe connection).
            elif KERNEL32.GetLastError() == ERROR_BROKEN_PIPE:
                break
            else:
                log.warning("The log pipe handler has failed, last error %d.",
                            KERNEL32.GetLastError())
                break

        if pid.value:
            self.active[pid.value] = False