In the window system, we can modify the memory of another process across processes. For example, if process A wants to modify the memory of process B, A can call the system function WriteProcessMemory, the approximate form is as follows:
BOOL flag = WriteProcessMemory(handler, p_B_addr, &p_A_buff, write_size); ...
this function return a bool value, which represents whether the wirte operation is successful. it needs pass 4 parameters, let's take a look at these 4 parameters:
1: handler, this is a process handle, it can be used to find B process.
2: p_B_addr, in process B, the address offset to be written into memory.
3: p_A_buff, in process A, the pointer to write data buffer.
4: write_size, number of bytes to write.
What I am confused about is the first parameter handler, which is a variable of type HANDLE. for example, when our program is actually running, the ID of process B is 2680, then I want to write memory to process B, first I need to use this 2680 to get the handle of process B in process A, the specific form is handler=OpenProcess(PROCESS_ALL_ACCESS, FALSE, 2680), and then you can use this handler to fall into the kernel to modify the memory of process B. What I want to ask is: Since they are all trapped in kernel functions to modify memory across processes, why is the WriteProcessMemory function not designed to be in the form of WriteProcessMemory(B_procID, p_B_addr, &p_A_buff, write_size)?among them, B_procID is the ID of the B process, since each process they all have unique IDs, can the system kernel not find the physical address that the virtual address of the B process can map through this B_procID? why must the process handle index of the B process in the Aprocess be passed in?
PS: please forgive my long-winded question, because I have been researching SOV for a long time and can not upload pictures, so it is difficult to ask in a more concise way, thank your for reading!
CodePudding user response:
There are multiple reasons, all touched on in the comments.
- Lifetime. The process id is simply a number, knowing the id does not keep the process alive. Having a open handle to a process means the kernel EPROCESS structure and the process address space will stay intact, even if said process finishes by calling
ExitProcess
. Windows tries to not re-use the id for a new process right away but it will happen some time in the future given enough time. - Security/Access control. In Windows NT, access control is performed when you open a object, not each time you interact with the object. In this case, the kernel needs to know that the caller has PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process. This is related to point 3, efficiency.
- Speed. Windows could of course implement a
WriteProcessMemoryById
function that callsOpenProcess
WriteProcessMemory
CloseHandle
but this encourages sub optimal design as well as opening you up to race conditions related to point 1. The same applies to "why is there noWriteFileByFilename
function" (and all other Read/Write functions).