Python 从传递给DeviceIoControl()的句柄中检索设备名称

Python 从传递给DeviceIoControl()的句柄中检索设备名称,python,windows,winapi,driver,device-driver,Python,Windows,Winapi,Driver,Device Driver,我正在连接WindowsAPI(使用Python设备)。 是否有方法检索作为此API的第一个参数传递的设备句柄对应的设备名称 BOOL WINAPI DeviceIoControl( _In_ HANDLE hDevice, <---------- This one _In_ DWORD dwIoControlCode, _In_opt_ LPVOID lpInBuffer, _In_

我正在连接WindowsAPI(使用Python设备)。 是否有方法检索作为此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
);

你知道吗?

你如何调用这些函数?您试图获取关于哪个设备的信息?你是真的在挂接这个函数,还是只是想调用这个函数?(Hook的意思非常具体,一般来说,你不能从用户模式中钩住驱动程序。)当你说“我无法让它工作”时,你能告诉我们它是如何失败的吗?这是不是给了你一个错误?返回意料之外的东西?还有别的吗?@theB:你不能从用户模式钩住驱动程序,但你可以钩住DeviceIoControl()API调用,所以我认为假设OP的意思与他说的完全一致是相当安全的。另一方面,更明智的做法是先尝试获取自己打开的句柄的设备路径,然后再从钩子内部尝试。@HarryJohnston-我是基于可用的资源,例如,回想起来,它忽略了一些不太受支持的方法。不过,对于全局拦截低级(ish)系统调用,并通过python解释器对其进行过滤,我仍然会保持警惕。@theB:这个问题混淆了两种完全不同的钩子。然而,API挂钩并没有得到正式支持(尽管微软确实出售软件来实现),这绝对是真的,而且它肯定不是完全安全的,在Python这样的解释性语言环境中尝试实现API挂钩对我来说就像一场等待发生的噩梦。我只是指出它确实存在。:-)默认的
restype
c_int
(即
int
),这很好,因为
NTSTATUS
是有符号的(警告和错误是负值)。使常数签名,例如
NTSTATUS=c_long
STATUS\u INFO\u LENGTH\u MISMATCH=NTSTATUS(0xC0000004).value
。如何调用这些函数?您试图获取关于哪个设备的信息?你是真的在挂接这个函数,还是只是想调用这个函数?(Hook的意思非常具体,一般来说,你不能从用户模式中钩住驱动程序。)当你说“我无法让它工作”时,你能告诉我们它是如何失败的吗?这是不是给了你一个错误?返回意料之外的东西?还有别的吗?@theB:你不能从用户模式钩住驱动程序,但你可以钩住DeviceIoControl()API调用,所以我认为假设OP的意思与他说的完全一致是相当安全的。另一方面,更明智的做法是先尝试获取自己打开的句柄的设备路径,然后再从钩子内部尝试。@HarryJohnston-我是基于可用的资源,例如,回想起来,它忽略了一些不太受支持的方法。不过,对于全局拦截低级(ish)系统调用,并通过python解释器对其进行过滤,我仍然会保持警惕。@theB:这个问题混淆了两种完全不同的钩子。然而,API挂钩并没有得到正式支持(尽管微软确实出售软件来实现),这绝对是真的,而且它肯定不是完全安全的,在Python这样的解释性语言环境中尝试实现API挂钩对我来说就像一场等待发生的噩梦。我只是指出它确实存在。:-)默认的
restype
c_int
(即
int
),这很好,因为
NTSTATUS
是有符号的(警告和错误是负值)。使常数签名,例如
NTSTATUS=c_long
状态信息长度不匹配=NTSTATUS(0xC0000004)。值
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)