1

Using only the ctypes library, I would like to iterate through Windows processes and obtain the name of each process for comparison checks.

Right now, I am getting weird errors like this:

Failed to open process 0. Error: (87, 'The parameter is incorrect.')
Failed to enumerate process modules for 4. Error: (299, 'Only part of a ReadProcessMemory or WriteProcessMemory request was completed.')
Failed to enumerate process modules for 196. Error: (299, 'Only part of a ReadProcessMemory or WriteProcessMemory request was completed.')
Failed to enumerate process modules for 708. Error: (5, 'Access is denied.')
Failed to open process 956. Error: (5, 'Access is denied.')
Failed to enumerate process modules for 884. Error: (5, 'Access is denied.')
Failed to open process 868. Error: (5, 'Access is denied.')
Failed to enumerate process modules for 960. Error: (5, 'Access is denied.')
Failed to enumerate process modules for 1028. Error: (5, 'Access is denied.')
Failed to enumerate process modules for 1136. Error: (5, 'Access is denied.')

Every Windows process is throwing an error. I've tried running the script with Admin privileges and ensuring that it Python is 64-bit.

Current code:

import ctypes
import ctypes.wintypes

# Library initializations
psapi = ctypes.windll.psapi
kernel32 = ctypes.windll.kernel32

FORMAT_MESSAGE_FROM_SYSTEM = 0x1000
PROCESS_QUERY_INFORMATION = 0x1000
MAX_PROCESS_NAME_LENGTH = 512
MAX_PROCESS_COUNT = 4096

FLAGGED_PROCESSES = ["test.exe"] 


def get_last_error():
    """Retrieve the last error code and its description."""
    error_code = ctypes.GetLastError()
    buffer = ctypes.create_unicode_buffer(256)
    kernel32.FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, None, error_code, 0, buffer, len(buffer), None)
    return error_code, buffer.value.strip()

def _get_process_name(process_id):
    h_process = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, False, process_id)
    if not h_process:
        print(f"Failed to open process {process_id}. Error: {get_last_error()}")
        return None
    
    try:
        module_handle = ctypes.wintypes.HMODULE()
        cb_needed = ctypes.wintypes.DWORD()

        if not psapi.EnumProcessModules(h_process, ctypes.byref(module_handle), ctypes.sizeof(module_handle), ctypes.byref(cb_needed)):
            print(f"Failed to enumerate process modules for {process_id}. Error: {get_last_error()}")
            return None

        exe_name = ctypes.create_unicode_buffer(MAX_PROCESS_NAME_LENGTH)
        if not psapi.GetModuleBaseNameW(h_process, module_handle, exe_name, ctypes.sizeof(exe_name) // 2):
            print(f"Failed to get module base name for {process_id}. Error: {get_last_error()}")
            return None
        
        return exe_name.value
    
    finally:
        kernel32.CloseHandle(h_process)

def is_flagged_process_running():
    DWORD = ctypes.wintypes.DWORD
    DWORD_ARRAY = DWORD * MAX_PROCESS_COUNT
    process_ids = DWORD_ARRAY()
    bytes_returned = DWORD()

    if not psapi.EnumProcesses(ctypes.byref(process_ids), ctypes.sizeof(process_ids), ctypes.byref(bytes_returned)):
        print(f"Failed to enumerate processes. Error: {get_last_error()}")
        return False

    number_of_processes = bytes_returned.value // ctypes.sizeof(DWORD)

    for index in range(number_of_processes):
        process_name = _get_process_name(process_ids[index])
        if process_name and process_name.lower() in FLAGGED_PROCESSES:
            return True

    return False


print(is_flagged_process_running())
zizzie
  • 11
  • 1
  • You have ***U**ndefined **B**ehavior*. [\[SO\]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer)](https://stackoverflow.com/a/58611011/4788546). Also check [\[SO\]: Get the title of a window of another program using the process name (@CristiFati's answer)](https://stackoverflow.com/a/31280850/4788546). For the *Access Denied*, you most likely need to enable some privileges. – CristiFati Aug 28 '23 at 17:01

0 Answers0