I'm hooking kernel32!DeviceIoControl Windows API (using Python Deviare). Is there a way to retrieve the device name corresponding to the device handle passed as the first parameter of this API ?
BOOL WINAPI DeviceIoControl(
_In_ HANDLE hDevice, <---------- This one
_In_ DWORD dwIoControlCode,
_In_opt_ LPVOID lpInBuffer,
_In_ DWORD nInBufferSize,
_Out_opt_ LPVOID lpOutBuffer,
_In_ DWORD nOutBufferSize,
_Out_opt_ LPDWORD lpBytesReturned,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
I've made some tries using DuplicateHandle and NtQueryObject API, but i do not manage to make it works. I'm not sure that it's possible this way. Here is the code I'm talking about :
class LSA_UNICODE_STRING(Structure):
"""Represent the LSA_UNICODE_STRING on ntdll."""
_fields_ = [
("Length", USHORT),
("MaximumLength", USHORT),
("Buffer", LPWSTR),
]
class PUBLIC_OBJECT_TYPE_INFORMATION(Structure):
"""Represent the PUBLIC_OBJECT_TYPE_INFORMATION on ntdll."""
_fields_ = [
("Name", LSA_UNICODE_STRING),
("Reserved", ULONG * 22),
]
class OBJECT_NAME_INFORMATION (Structure):
"""Represent the OBJECT_NAME_INFORMATION on ntdll."""
_fields_ = [
("Name", LSA_UNICODE_STRING),
]
STATUS_INFO_LENGTH_MISMATCH = 0xC0000004
STATUS_BUFFER_OVERFLOW = 0x80000005L
STATUS_INVALID_HANDLE = 0xC0000008L
STATUS_BUFFER_TOO_SMALL = 0xC0000023L
STATUS_SUCCESS = 0
def GetProcessHandle(pid, handle):
"""Get a handle for the process with the given pid"""
try:
hProcess = OpenProcess(win32con.PROCESS_DUP_HANDLE, 0, pid)
dupHandle = DuplicateHandle(hProcess, handle, GetCurrentProcess(), 0, 0, win32con.DUPLICATE_SAME_ACCESS)
return dupHandle
except ApiError,(errno, errctx, errmsg):
if errno in (
winerror.ERROR_ACCESS_DENIED,
winerror.ERROR_INVALID_PARAMETER,
winerror.ERROR_INVALID_HANDLE,
winerror.ERROR_NOT_SUPPORTED
):
return None
else:
raise
def GetTypeInfo(handle):
""" Get the handle type information """
public_object_type_information = PUBLIC_OBJECT_TYPE_INFORMATION()
size = DWORD(sizeof(public_object_type_information))
NtQueryObject = windll.ntdll.NtQueryObject
while True:
result = NtQueryObject(handle, 2, byref(public_object_type_information), size, None)
print result
if result == STATUS_SUCCESS:
return public_object_type_information.Name.Buffer
elif result == STATUS_INFO_LENGTH_MISMATCH:
size = DWORD(size.value * 4)
resize(public_object_type_information, size.value)
elif result == STATUS_INVALID_HANDLE:
return "[invalid handle]"
#print "invalid handle"
#return "INVALID HANDLE: {0}".format(hex(handle))
else:
return "[error]"
def GetNameInfo(handle):
""" Get the handle name information """
object_name_information = OBJECT_NAME_INFORMATION()
size = DWORD(sizeof(object_name_information))
NtQueryObject = windll.ntdll.NtQueryObject
while True:
result = NtQueryObject(handle, 1, byref(object_name_information), size, None)
print result
if result == STATUS_SUCCESS:
return object_name_information.Name.Buffer
elif result in (STATUS_BUFFER_OVERFLOW, STATUS_BUFFER_TOO_SMALL, STATUS_INFO_LENGTH_MISMATCH):
size = DWORD(size.value * 4)
resize(object_name_information, size.value)
else:
return "[name retrieval error]"
def GetDeviceInfo(targetPid, handle):
#currentPid = os.getpid()
dupHandle = GetProcessHandle(targetPid, handle)
if dupHandle is None:
print "Duplicate handle failed"
else:
typeInfo = GetTypeInfo(int(dupHandle))
nameInfo = GetNameInfo(int(dupHandle))
print "type = {0} - name = {1}".format(typeInfo, nameInfo)
Do you have any idea ?