Modify STARTUPINFO after CreateProcess - windows

I would like to be able to change the STARTUPINFO values, right after CreateProcess has been called (suspended).
So the new remote/child process can get custom GetStartupInfo values as soon as it starts.
How could I achieve this?
More Info:
I would like to pass arbitary data to the child process.
Regarding to this article: http://www.catch22.net/tuts/undocumented-createprocess it is possible to do so with the reserved2 members from the STARTUPINFO structure. This method works but has a limit of 65536 bytes. A theoretical solution in order to pass more than 65536 bytes would be if you:
Create the process (suspended)
Alloc space with VirtualAllocEx in the child process
Write data > 65536 bytes to the child process with WriteProcessMemory
Change the reserved2 members with the address from Step 2
Resume the process
The child process calls GetStartupInfo and gets the data

I'm not aware of any supported way for you to do what you ask. However, I suggest an alternative solution to the root problem.
You should not be using lpReserved2 anyway since the documentation tells you to set it to NULL.
Have the parent process create a named memory mapped file.
Pass the name of this file mapping to the child process as a command line argument.
Indeed, there are many variants on this approach, but command line arguments are the way to pass information to a new process.

Related

Why does WriteProcessMemory need the handle value passed in, not the ID of the target process?

In the Windows 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 Boolean value, which represents whether the write operation is successful. It needs to pass four parameters, let's take a look at these four parameters:
handler. This is a process handle, and it can be used to find B process.
p_B_addr. In process B, the address offset to be written into memory.
p_A_buff. In process A, the pointer to the write data buffer.
write_size. The number of bytes to write.
I am confused about 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, and 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.
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 A process be passed in?
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 calls OpenProcess+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 no WriteFileByFilename function" (and all other Read/Write functions).

How to display array of structure pointer in user space which is copied from kernel via read call

Depending on the number of processes currently running, by using for_each_process macro call and one simple counter, I have used kmalloc to allocate memory for those processes to store process pid and its parent pid in structure. And use copy_to_user to copy it into the user space segment like below,
copy_to_user(buffer, &data, sizeof(Data) * process_counter);
But the problem is I am not able to figure out how should I suppose to display it on the user space application using read system call.
Is it possible in one read call Or do i need to use while loop for it ?
Thanks in advance.

Retrieving command line argument of process at driver level

Hello I am writing a minifilter driver for intercepting all the irp packets from a certain process say a.exe .
So , in the driver code it can be done by applying a check on the command line arguments that started the process.
Does anyone know how can i retrieve the command line argument ??
Thanks in advance .
There's no supported way to do this from within kernel-mode. In fact, trying to access user-mode process information from the kernel is a pain in general. I would suggest firing up a request to a user-mode service, which can then find that information and pass it back down to your kernel component.
However, there an undocumented method to do it. If you can get a handle to an EPROCESS struct for the target process, you can get at a pointer to the PEB (process environment block) struct within it, which then has a pointer to an RTL_USER_PROCESS_PARAMETERS structure, which has a member called CommandLine.
Example:
UNICODE_STRING* commandLine = epProcess->Peb->ProcessParameters->CommandLine;
The downside to this is that EPROCESS is almost entirely opaque and PEB is semi-opaque too, meaning that it may change in future versions of Windows. I certainly wouldn't advocate trying this in production code.
Try using the NtQueryInformationProcess or ZwQueryInformationProcess function with the PROCESSINFOCLASS parameter as ProcessBasicInformation. The output parameter, ProcessInformation, will be a struct of type PROCESS_BASIC_INFORMATION. As Polynomial mentioned, this struct has a pointer to the process's PEB struct, which contains the information you are looking for in its ProcessParameters field.

How can one process access foreign TIB?

Is it possible (and how) to access Thread Information Block of a thread of some another process?
It is possible.
The first step is to get the adress of the Thread Information Block by using the NtQueryInformationThread function with ThreadInformationClass set to ThreadBasicInformation. The THREAD_BASIC_INFORMATION structure contains a pointer to the TEB of the thread. Then you can use ReadProcessMemory and WriteProcessMemory in order to read or modify the content of the TEB.

file_operations Question, how do i know if a process that opened a file for writing has decided to close it?

I'm currently writing a simple "multicaster" module.
Only one process can open a proc filesystem file for writing, and the rest can open it for reading.
To do so i use the inode_operation .permission callback, I check the operation and when i detect someone open a file for writing I set a flag ON.
i need a way to detect if a process that opened a file for writing has decided to close the file so i can set the flag OFF, so someone else can open for writing.
Currently in case someone is open for writing i save the current->pid of that process and when the .close callback is called I check if that process is the one I saved earlier.
Is there a better way to do that? Without saving the pid, perhaps checking the files that the current process has opened and it's permission...
Thanks!
No, it's not safe. Consider a few scenarios:
Process A opens the file for writing, and then fork()s, creating process B. Now both A and B have the file open for writing. When Process A closes it, you set the flag to 0 but process B still has it open for writing.
Process A has multiple threads. Thread X opens the file for writing, but Thread Y closes it. Now the flag is stuck at 1. (Remember that ->pid in kernel space is actually the userspace thread ID).
Rather than doing things at the inode level, you should be doing things in the .open and .release methods of your file_operations struct.
Your inode's private data should contain a struct file *current_writer;, initialised to NULL. In the file_operations.open method, if it's being opened for write then check the current_writer; if it's NULL, set it to the struct file * being opened, otherwise fail the open with EPERM. In the file_operations.release method, check if the struct file * being released is equal to the inode's current_writer - if so, set current_writer back to NULL.
PS: Bandan is also correct that you need locking, but the using the inode's existing i_mutex should suffice to protect the current_writer.
I hope I understood your question correctly: When someone wants to write to your proc file, you set a variable called flag to 1 and also save the current->pid in a global variable. Then, when any close() entry point is called, you check current->pid of the close() instance and compare that with your saved value. If that matches, you turn flag to off. Right ?
Consider this situation : Process A wants to write to your proc resource, and so you check the permission callback. You see that flag is 0, so you can set it to 1 for process A. But at that moment, the scheduler finds out process A has used up its time share and chooses a different process to run(flag is still o!). After sometime, process B comes up wanting to write to your proc resource also, checks that the flag is 0, sets it to 1, and then goes about writing to the file. Unfortunately at this moment, process A gets scheduled to run again and since, it thinks that flag is 0 (remember, before the scheduler pre-empted it, flag was 0) and so sets it to 1 and goes about writing to the file. End result : data in your proc resource goes corrupt.
You should use a good locking mechanism provided by the kernel for this type of operation and based on your requirement, I think RCU is the best : Have a look at RCU locking mechanism

Resources