Tuesday, April 21, 2009

Handling And Re-Handling


NTSTATUS
: STATUS_IT_WASNT_REALLY_OBVIOUS


In the Windows system, an object that represents a system resource such as a process, thread, file or synchronization object are accessed via a handle. The application will have to obtain a handle to such objects which can then be used to manipulate or examine these objects.

Here are some common handle types in Win32:

Kernel Objects
:
  • Process: HANDLE
  • Thread: HANDLE
  • File: HANDLE
  • Synchronization Objects (mutex, semaphore): HANDLE

User Objects:
  • Window: HWND
  • Menu: HMENU
  • Icon: HICON

GDI Objects:
  • Device Context: HDC
  • Bitmap: HBITMAP
  • Brush: HBRUSH

What we're going to focus on here are kernel objects, and a particular scenario where a not-so-obvious Win32 API function earns it's dollars.

Here's the scenario. You have obtained a handle to a kernel object, and for this example, it is a process handle (HANDLE). You did not create the process to which this handle is for, nor did you open the process to which this handle is for. You just got hold of it. Now, you want to get some information on this process, so let's start by trying to get the process's module file name with GetProcessImageFileName().

Boom! The function returns a failure. And the error reason is that you basically do not have the access permissions to do so. The handle must have one of the following permissions:
  • PROCESS_QUERY_INFORMATION
  • PROCESS_QUERY_LIMITED_INFORMATION
So clearly, it doesn't. And since you did not create or open that process, you also don't know which Process ID it was either that the handle came from. !@#$%. Guess we'll just have to try to get that information from the handle then. Oh, wait, we probably can't either coz we don't have the necessary permissions. How now brown cow?

Well, as it turns out, there is a particular Win32 API function I've known for ages, but had never examined it (clearly, I've not used it until not too long ago) as it seemed silly back then. The function: DuplicateHandle(). I guess I never paid attention to it because I didn't see the need for that as I could just use another HANDLE variable and assign it the same value. D-uh...

However, here's the prototype:

BOOL WINAPI DuplicateHandle(
__in HANDLE hSourceProcessHandle,
__in HANDLE hSourceHandle,
__in HANDLE hTargetProcessHandle,
__out LPHANDLE lpTargetHandle,
__in DWORD dwDesiredAccess,
__in BOOL bInheritHandle,
__in DWORD dwOptions
);


So, it clearly does a whole lot more than just duplicating a handle, so to speak. The magic is in the parameter
dwDesiredAccess. You can set the permissions for the new handle that is to be duplicated from the original. So, what you'd get is a new handle that accesses the same object as the original handle, but with different properties such as the access permissions. However, there is another catch. This won't work either unless the source process of the original handle has the PROCESS_DUP_HANDLE permission. So far, I don't think it's common to not have this permission.

Just for good measure, you can specify DUPLICATE_SAME_ACCESS in the
dwOptions parameter, and the dwDesiredAccess parameter will be ignored.
Therefore, by duplicating the original process handle this way, you can now obtain some information from it, like what GetProcessImageFileName() can tell you.

No comments:

Post a Comment