What is the "hProcess" parameter of the Win32 API Writeprocessmemory function?

Asked

Viewed 51 times

0

I am creating a program that needs to read and write a value in a given memory address. For this, I am using the functions ReadProcessMemory and WriteProcessMemory Win32 API - through the package ctypes python.

The problem is that both functions receive a parameter called hProcess. Initially, I thought that this parameter was the PID (Process ID), but I realized that it was something else, after getting the code below on the internet, which uses some functions of the package pywin32:

def SetValue(w_title, address, data, bufflength):
    
    kernel32 = ctypes.windll.LoadLibrary("kernel32.dll")

    hwnd = FindWindow(None, w_title)
    hpid, pid = win32process.GetWindowThreadProcessId(hwnd)
    hProcess = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
    
    kernel32.WriteProcessMemory(
        int(hProcess),                          # hProcess
        address,                                # lpBaseAddress
        ctypes.byref(ctypes.c_ulong(data)),     # lpBuffer
        bufflength,                             # nSize
        None                                    # *lpNumberOfBytesWritten
    )
    return data

I read several times to documentation of the API, however, it does not explain right what this parameter is. So my question is: what exactly should be passed as argument to this parameter?

  • You already have the hProcess (which means process Handle), No? He’s being returned by OpenProcess.

  • @Luizfelipe Yes, but the question is not about how to get it. I want to know "what is" it.

1 answer

0


The parameter hProcess means Process Handle - the letter "H" is Handle - and it is an integer value as well as the PID (Process ID - Process Identifier).

Unlike a PID, a Process Handle is a reference to a system object. Handles allow these objects to be referenced, so that the data to which they refer can be read or modified, as in your case. So that you can understand better, let’s make the following analogy:

What is your real-life identifier (ID)? Your CPF, of course. Through from the CPF, we can know that you are alive, we can distinguish two people with the same name, etc. But through your CPF, we can communicate with you? Of course not. For that, we would need your mobile number (Handle).

And just as you are born with a CPF, but you are not born with a mobile number, a process is started with a PID and your Handle is created later. For this reason, you need to use the function OpenProcess. What this function does is just get a PID, create a new Process Handle and return it, so that you can carry out communication with the process.

Another characteristic of Process Handles is that they need to have a permission for what can be done in the process. In addition, they can be inherited by their child processes, depending on the flag specified when they are created. The first two function parameters OpenProcess serve to define such settings.

# Obtém o Process Handle (referência do objeto) a partir do ID do processo.
hProcess = win32api.OpenProcess(
    PROCESS_ALL_ACCESS, # Parâmetro "reqdAccess": permissão para o Handle
    False,              # Parâmetro "bInherit": permite que o Handle seja herdado ou não
    pid                 # Parâmetro "pid": PID (ID do Processo)
)

It is important to point out that you should always close one Handle after its use. This is because if you do not release the Handle for a feature, other programs may not be able to access it. This is why sometimes you cannot delete a particular file because Windows warns that it is in use.

To release the Handle, use the function win32api.CloseHandle, passing the Process Handle as argument. See the code below:

def set_value(w_title, address, data, bufflength):
    
    kernel32 = ctypes.windll.LoadLibrary("kernel32.dll")
    
    # Obtém o HWND (Window Handle — Handle de janela) através do seu título.
    hwnd = FindWindow(None, w_title)

    # Obtém o Thread ID (inútil nesse código) e o Process ID.
    tid, pid = win32process.GetWindowThreadProcessId(hwnd)

    # Obtém o Handle do processo, através do seu PID. Abaixo, o Handle é configurado
    # para ter acesso total e não ser herdado.
    hProcess = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, pid)
    
    # Modifica o valor no endereço de memória, utilizando o Process Handle.
    kernel32.WriteProcessMemory(
        int(hProcess),                      # Process Handle
        address,                            # Endereço de memória (hexadecimal)
        ctypes.byref(ctypes.c_ulong(data)), # Valor passado por referência
        bufflength,                         # Tamanho do valor em bytes
        None                                # Número de bytes escritos (segundo a docum.)
    )

    # Libera o Handle do processo, afim de evitar problemas futuros.
    win32api.CloseHandle(hProcess)

You can also find more information - in English - on this documentation and the following questions, asked on Stack Overflow and Serverfault.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.