A very simple question, if i create a HANDLE in app1.exe and it gets value 0x01 is that value globally unique ?
Or is it possible that when some other process creates a HANDLE that also has value 0x01.
If they are not unique what other construct can i use to get a unique id compatible with handles (such that it will be impossible or highly unlikely that a HANDLE with that id is created anywhere else).
The important thing to understand is that handles are not objects. Handles are pointers (or indexes) to per-process object table. To answer your question, HANDLES are not globally unique, but they are scoped to only make sense inside a particular process.
For any kernel object to be able to be accessible from other process, you have to DuplicateHandle.
Another way to share objects across processes is to call CreateProcess with bInheritHandles set to true.
They are not unique. HANDLE values are local to the current process. Same value may be invalid handle or refer to a different object in another process. An exception to this rule are handles inherited from parent process.
The only way to have unique id without a centralized registry is to use GUID. But they are not compatible with HANDLE, they are 128-bit while handles are 32 or 64-bit.
Use DuplicateHandle to pass handles between processes.
Related
I've been experimenting with using the Windows API to launch child processes that communicate with the parent process through anonymous pipes. The basic idea is to create one or more pipes in the parent process using CreatePipe, and then launch the child process with inherited pipe handles using CreateProcess with a STARTUPINFOEX argument that specifies the inherited handles in the PROC_THREAD_ATTRIBUTE_HANDLE_LIST attribute.
Experimentally it seems to me that the first element of handle list is used as the child process's standard input, the second is used as it's standard output, and the third is used as it's standard error. I haven't seen any documentation of this behavior, and I didn't expect it because the STARTUPINFO fields hStdInput, hStdOutput, hStdError (along with the STARTF_USESTDHANDLES flag in dwFlags) seem specifically designed to communicate the CreateProcess caller's intent with respect to standard handles. Experimentally it seems to me that PROC_THREAD_ATTRIBUTE_HANDLE_LIST overrides STARTF_USESTDHANDLES, which I find even more surprising.
So two questions:
Is this behavior documented somewhere that I've missed?
How do you inherit handles while also using the default behavior for determining the standard handles of the child process?
UPDATE: It turns out that the behavior I was seeing was specific to the application I was launching as the child process. It must have been inspecting the inherited handles and doing something order specific with them. Most Windows applications do not behave that way.
PROC_THREAD_ATTRIBUTE_HANDLE_LIST extended attribute is used to explicitly specify exactly which handles a particular process inherits.
Raymond Chen's blog gives more details,
But all this inheritability fiddling still had a fatal flaw: What if
two threads within the same process both call CreateProcess but
disagree on which handles they want to be inherited? For example,
suppose you have a function CreateProcessWithSharedMemory whose
job it is to launch a process, passing it a custom-made shared memory
block. Suppose two threads run this function simultaneously.
...
Windows Vista addresses this problem by allowing you to pass an
explicit list of handles you want the bInheritHandles parameter to
apply to. (If you pass an explicit list, then you must pass TRUE for
bInheritHandles.) And as before, for a handle to be inherited, it
must be also be marked as inheritable.
And the blog gives detailed code sample and implementation methods.
For anonymous communication between parent-child processes, please refer to:
Creating a Child Process with Redirected Input and Output
PROC_THREAD_ATTRIBUTE_HANDLE_LIST overrides STARTF_USESTDHANDLES, it won't make any effect. Instead, the child process will not inherit the handle of the parent process.
In Windows, what is the formal way of identifying a process uniquely? I am not talking about PID, which is allocated dynamically, but a unique ID or a name which is permanent to that process. I know that every program/process has a security descriptor but it seems to hold SIDs for loggedin user and group (not the process). We cannot use the path and name of executable from where the process starts as that can change.
My aim is to identify a process in the kernel mode and allow it to perform certain operation. What is the easiest and best way of doing this?
Your question is too vague to answer properly. For example how could the path possibly change (without poking around in kernel memory) after creation of a process? And yes, I am aware that one could hook into the memory-mapping process during process creation to replace the image originally destined to be loaded with another. Point is that a process is merely one instance of running a given executable. And it's not clear what exact tampering attempts you want to counter here.
But from kernel mode you do have the ability to simply use the pointer to the EPROCESS structure. No need to use the PID, although that will be unique while the process is still alive.
So assuming your process uses an IRP to communicate to the driver (whether it be WriteFile, ReadFile, DeviceIoControl or something more exotic), in order to register itself, you can use IoGetCurrentProcess to get the PEPROCESS value which will be unique to the process.
While the structure itself is not officially documented, hints can be gleaned from the "Windows Internals" book (in its various incarnations), the dt (Display Type) command in WinDbg (and friends) as well as from third-party resources on the internet (e.g. here, specific to Vista).
The process objects are kept in several linked lists. So if you know the (officially undocumented!!!) layout for a particular OS version, you may traverse the lists to get from one to the next process object (i.e. EPROCESS structure).
Cautionary notes
Make sure to reference the object of the process, by using the respective object manager routines. Otherwise you cannot be certain it's safe to both reach into these structures (which is anyway unsafe, since you cannot rely on their layout across OS versions) or to pass it to functions that expect a PEPROCESS.
As a side-note: Harry Johnston is of course right to assert that a privileged user can insert arbitrary (well almost arbitrary) code into the TCB in order to thwart your protective measures. In the end it is going to be an arms race.
Also keep in mind that similar to PIDs, theoretically the value of the PEPROCESS may be recycled. But in both cases you can simply counter this by invalidating whatever internal state you keep in your driver that allows the process to do its magic, whenever the process goes down. Using something like PsSetCreateProcessNotifyRoutine would seem to be a good method here. In order to translate your process handle from the callback to a PEPROCESS value, use ObReferenceObjectByHandle.
An alternative of countering recycling of the PID/PEPROCESS is by keeping a reference to the process object and thus keeping it in a kind of undead state (similar to not closing a handle in user mode), although the main thread may have finished.
Simply put, if I were to call some API returning a handle, such as GetActiveWindow(), which would give me a handle of type HWND, what do I get back? Is it a unique address in the process' VAS, or a unique index into some OS structure? Or something else?
An opaque integer identifier that has no meaning or use outside the API calls it's designed to work with - IOW, there's no way of knowing most of the time, and most of the time you shouldn't care. :-)
Yes to all of the above. In other words, it varies (widely) by handle type. Some are addresses (often hashed), others are indexes into particular tables, etc.
I've been reading some books on windows programming in C++ lately, and I have had some confusing understanding of some of the recurring concepts in WinAPI. For example, there are tons of data types that start with the handle keyword'H', are these supposed to be used like pointers? But then there are other data types that start with the pointer keyword 'P'. So I guess not. Then what is it exactly? And why were pointers to some data types given separate data types in the first place? For example, PCHAR could have easily designed to be CHAR*?
Handles used to be pointers in early versions of Windows but are not anymore. Think of them as a "cookie", a unique value that allows Windows to find back a resource that was allocated earlier. Like CreateFile() returns a new handle, you later use it in SetFilePointer() and ReadFile() to read data from that same file. And CloseHandle() to clean up the internal data structure, closing the file as well. Which is the general pattern, one api function to create the resource, one or more to use it and one to destroy it.
Yes, the types that start with P are pointer types. And yes, they are superfluous, it works just as well if you use the * yourself. Not actually sure why C programmers like to declare them, I personally think it reduces code readability and I always avoid them. But do note the compound types, like LPCWSTR, a "long pointer to a constant wide string". The L doesn't mean anything anymore, that dates back to the 16-bit version of Windows. But pointer, const and wide are important. I do use that typedef, not doing so will risk future portability problems. Which is the core reason these typedefs exist.
A handle is the same as a pointer only so far as both ID a particular item. Obviously a pointer is the address of the item so if you know it's structure you can start getting fields in the item. A handle may or may not be a pointer - basically if it is a pointer you don't know what it is pointing to so you can't get into the fields.
Best way to think of a handle is that it is a unique ID for something in the system. When you pass it to something in the system the system will know what to cast it to (if it is a pointer) or how to treat it (if it is just some id or index).
I have got many of my questions solved here, many thanks to you guys. And I'd like to ask one more. :)
I am reading about < Windows via C/C++ >, it said:
When we wnat to gain access to an existing kernel object (rather than create a new one), we must speicify the operations we intend to perform on the object. If we are allowed access with such operations, a handle to the kernel object is returned.
...if the returned handle is used to call an API that requires a right different from you requested for, the access-denied error occurs.
AFAIK, handle is just a plain integer number, it's just an index into the process' handle table, nothing more could the handle value provide. If we have already got a handle to a kernel object, how could the system detect we use it for other operations than we requested for?
A kernel object can have more than one handles, and the owners of these handles may have different access types. Where does the system store these different access type info? I think it should be in the process' handle table.
Suppose I try to open a single kernel object with 2 different access types, 2 handles to the same kernel object should be returned, and thus there'll be 2 entries in the process' handle table, pointing to the same kernel object.
Any insight will be deeply appreciated.
Update 1
Thanks guys.
I referred to the < Windows Internals > 5th edition, it said at Ch 6. Access Checks:
The Windows security model requires that a therad speicfy up front, at the time that it opens an object, what types of actions it wants to perfrom on the object. The object manager calls the SRM to perform access checks based on a thread's desired access, and if the access is granted, a handle is assigned to the thread's process with which the thread (or other threads in the process) can perform further operations on the object. As explained in Chapter 3, the object menager records the access permissions granted for a handle in the process's handle table.
So it seems my guess is right.
Thanks.
Every kernel object that is active will have a series of rights stored against it. This is just another table managed by the Security Reference Manager (SRM). When the security is asserted by the object manager then the object handle will looked up to collect the object reference (ObReferenceObjectByHandle) and the resultant object , can be used to look up the rights (ObCheckObjectAccess). There will be indirections involving security tokens, but in essence this is the theory. So two handles may indeed point to the same reference object.
There is a good description of what happens during a ObCheckObjectAccess call in Windows Internals (mine version 5).
Paraphrasing it here :
The ObCheckObjectAccess takes the object, the credentials of the calling thread and the access requested and calls the SRM (SeAccessCheck) so that it can work out whether the right is asserted or denied.