Example #1
0
    def get_parent_pid(self):
        """Get the Parent Process ID."""
        class PROCESS_BASIC_INFORMATION(Structure):
            _fields_ = [
                ("ExitStatus", c_void_p),
                ("PebBaseAddress", c_void_p),
                ("AffinityMask", c_void_p),
                ("BasePriority", c_void_p),
                ("UniqueProcessId", c_void_p),
                ("InheritedFromUniqueProcessId", c_void_p),
            ]

        NT_SUCCESS = lambda val: val >= 0

        pbi = PROCESS_BASIC_INFORMATION()
        size = c_int()

        # Set return value to signed 32bit integer.
        NTDLL.NtQueryInformationProcess.restype = c_int

        process_handle = self.open_process()
        ret = NTDLL.NtQueryInformationProcess(process_handle, 0, byref(pbi),
                                              sizeof(pbi), byref(size))
        KERNEL32.CloseHandle(process_handle)

        if NT_SUCCESS(ret) and size.value == sizeof(pbi):
            return pbi.InheritedFromUniqueProcessId
Example #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)
Example #3
0
    def get_filepath(self):
        """Get process image file path.
        @return: decoded file path.
        """
        process_handle = self.open_process()

        NT_SUCCESS = lambda val: val >= 0

        pbi = create_string_buffer(200)
        size = c_int()

        # Set return value to signed 32bit integer.
        NTDLL.NtQueryInformationProcess.restype = c_int

        ret = NTDLL.NtQueryInformationProcess(process_handle, 27, byref(pbi),
                                              sizeof(pbi), byref(size))

        KERNEL32.CloseHandle(process_handle)

        if NT_SUCCESS(ret) and size.value > 8:
            try:
                fbuf = pbi.raw[8:]
                fbuf = fbuf[:fbuf.find("\x00\x00") + 1]
                return fbuf.decode("utf16", errors="ignore")
            except:
                return ""

        return ""
Example #4
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]
def grant_privilege(privilege):
    """Grant debug privileges.
    @param pid: PID.
    @return: operation status.
    """
    ADVAPI32.OpenProcessToken.argtypes = (wintypes.HANDLE, wintypes.DWORD,
                                          POINTER(wintypes.HANDLE))

    ADVAPI32.LookupPrivilegeValueW.argtypes = (wintypes.LPWSTR,
                                               wintypes.LPWSTR, POINTER(LUID))

    ADVAPI32.AdjustTokenPrivileges.argtypes = (wintypes.HANDLE, wintypes.BOOL,
                                               POINTER(TOKEN_PRIVILEGES),
                                               wintypes.DWORD,
                                               POINTER(TOKEN_PRIVILEGES),
                                               POINTER(wintypes.DWORD))

    h_process = KERNEL32.GetCurrentProcess()

    h_current_token = wintypes.HANDLE()
    if not ADVAPI32.OpenProcessToken(h_process, TOKEN_ALL_ACCESS,
                                     h_current_token):
        return False

    se_original_luid = LUID()
    if not ADVAPI32.LookupPrivilegeValueW(None, privilege, se_original_luid):
        return False

    luid_attributes = LUID_AND_ATTRIBUTES()
    luid_attributes.Luid = se_original_luid
    luid_attributes.Attributes = SE_PRIVILEGE_ENABLED
    token_privs = TOKEN_PRIVILEGES()
    token_privs.PrivilegeCount = 1
    token_privs.Privileges = luid_attributes

    if not ADVAPI32.AdjustTokenPrivileges(h_current_token, False, token_privs,
                                          0, None, None):
        return False

    KERNEL32.CloseHandle(h_current_token)
    KERNEL32.CloseHandle(h_process)
    return True
Example #6
0
    def exit_code(self):
        """Get process exit code.
        @return: exit code value.
        """
        process_handle = self.open_process()

        exit_code = c_ulong(0)
        KERNEL32.GetExitCodeProcess(process_handle, byref(exit_code))
        KERNEL32.CloseHandle(process_handle)

        return exit_code.value
Example #7
0
    def terminate(self):
        """Terminate process.
        @return: operation status.
        """
        process_handle = self.open_process()

        ret = KERNEL32.TerminateProcess(process_handle, 1)
        KERNEL32.CloseHandle(process_handle)

        if ret:
            log.info("Successfully terminated process with pid %d.", self.pid)
            return True
        else:
            log.error("Failed to terminate process with pid %d.", self.pid)
            return False
Example #8
0
    def run(self):
        """Run the pipe dispatcher."""
        buf = create_string_buffer(BUFSIZE)
        bytes_written = c_uint()

        while self.do_run:
            message = self._read_message(buf)
            if not message:
                break

            response = self.dispatcher.dispatch(message) or "OK"

            KERNEL32.WriteFile(self.pipe_handle, response, len(response),
                               byref(bytes_written), None)

        KERNEL32.CloseHandle(self.pipe_handle)
Example #9
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
Example #10
0
 def Close(self):
     KERNEL32.CloseHandle(self)