flac 发表于 2018-1-19 11:04:10

[开源]NT路径转DOS路径的简单办法

        以前也曾为NT路径转DOS路径而烦恼,网上翻了很久,总觉得那些操作太过繁琐,我本人比较懒,就一直想找个简单的办法,现在终于找到了。
        ring3下的NT路径转DOS路径,通常所采用的套路是查询符号链接,ring0下就好搞了,有IoVolumeDeviceToDosName ,IoQueryFileDosDeviceName 。看某位大表哥的博客,IoQueryFileDosDeviceName 接口在某个情况下会导致系统卡死。
        现在在提供一种办法,简单又粗暴,改改可以放到ring0下跑,粗略测试还是很靠谱的。套路如下:
typedef struct _MOUNTDEV_NAME {
        USHORTNameLength;
        WCHAR   Name;
} MOUNTDEV_NAME, *PMOUNTDEV_NAME;

typedef struct _MOUNTMGR_VOLUME_PATHS {
        ULONG MultiSzLength;
        WCHAR MultiSz;
} MOUNTMGR_VOLUME_PATHS, *PMOUNTMGR_VOLUME_PATHS;

#define MOUNTMGRCONTROLTYPE ((ULONG) 'm')
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH \
        CTL_CODE(MOUNTMGRCONTROLTYPE, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)


DWORD VolumeDeviceNameToDosName( IN LPCWSTR DeviceName, OUT LPWSTR DosName )
{
        PMOUNTDEV_NAME MountName = NULL;
        CHAR buffer1 = { 0 };
        CHAR buffer2 = { 0 };
        HANDLE MountPointMgr = NULL;
        DWORD BytesReturned = 0;

        MountPointMgr = CreateFile(
                                                L"\\\\.\\MountPointManager",
                                                0,
                                                FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                                                NULL,
                                                OPEN_EXISTING,
                                                0,
                                                NULL
                                                );
        if( MountPointMgr == INVALID_HANDLE_VALUE )
                return GetLastError();

        MountName = ( PMOUNTDEV_NAME )buffer1;
        wcscpy( MountName->Name, DeviceName );
        MountName->NameLength = wcslen( MountName->Name ) * 2;

        DeviceIoControl(
                                        MountPointMgr,
                                        IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH,
                                        MountName,
                                        512,
                                        buffer2,
                                        512,
                                        &BytesReturned,
                                        NULL
                                        );
        if( ! GetLastError() )
                wcscpy( DosName, ( ( PMOUNTMGR_VOLUME_PATHS )buffer2 )->MultiSz );

        CloseHandle( MountPointMgr );
        return GetLastError();
}输入:\Device\HarddiskVolume1
输出:C:

Tesla.Angela 发表于 2018-1-19 14:29:49

直接用QueryDosDevice可以兼容R3和R0:http://www.m5home.com/bbs/thread-7622-1-1.html

PS:杭州潜水艇(hzqst),出来走两步。

hzqst 发表于 2018-1-19 19:52:10

其实这个就是IoVolumeDeviceToDosName 的R3版本

lanjingling888 发表于 2018-1-19 23:33:36

//发个r0的
PWSTR _GetSymbolicTarget(PCWSTR pwSymbolic)
{
    OBJECT_ATTRIBUTES oa;
    UNICODE_STRING uSymbolic;
    NTSTATUS status;
    HANDLE hSymbolic;
    UNICODE_STRING uTarget;
    ULONG len = 0;
    WCHAR buf;
    PWSTR pwTarget;
   
    RtlInitUnicodeString(&uSymbolic, pwSymbolic);
    InitializeObjectAttributes(&oa, &uSymbolic, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL,NULL);
   
    status = ZwOpenSymbolicLinkObject(&hSymbolic, GENERIC_READ, &oa);
    if (!NT_SUCCESS(status))
    {
      DbgPrint(("hpsafe:%-4d ZwOpenSymbolicLinkObject failed with 0x%08X.\n", __LINE__, status));
      return NULL;
    }
   
    RtlInitEmptyUnicodeString(&uTarget, buf, 0);
    status = ZwQuerySymbolicLinkObject(hSymbolic, &uTarget, &len);
    if (status != STATUS_BUFFER_TOO_SMALL)
    {
      DbgPrint(("hpsafe:%-4d ZwQuerySymbolicLinkObject failed with 0x%08X.\n", __LINE__, status));
      return NULL;
    }

    pwTarget = ExAllocatePoolWithTag(NonPagedPool, len + sizeof(WCHAR), '_EL_');
    if (!pwTarget)
    {
      DbgPrint(("hpsafe:%-4d ExAllocatePoolWithTag failed.\n", __LINE__));
      ZwClose(hSymbolic);
      return NULL;
    }
   
    RtlInitEmptyUnicodeString(&uTarget, pwTarget, (USHORT)len + sizeof(WCHAR));
    status = ZwQuerySymbolicLinkObject(hSymbolic, &uTarget, &len);
    ZwClose(hSymbolic);
   
    if (!NT_SUCCESS(status))
    {
      DbgPrint(("hpsafe:%-4d ZwQuerySymbolicLinkObject failed with 0x%08X.\n", __LINE__, status));
      ExFreePoolWithTag(pwTarget, '_EL_');
      return NULL;
    }
   
    return pwTarget;
}

PWSTR _DosPathToNtPath(PCWSTR pwDosPath)
{
    PWSTR pwTarget, pNtPath;
    SIZE_T l1, l2;
    WCHAR pwDosDrive[] = L"\\DosDevices\\X:";
   
    if ((*pwDosPath >= L'a' && *pwDosPath <= L'z' ||
      *pwDosPath >= L'A' && *pwDosPath <= L'Z') &&
      pwDosPath == L':' && pwDosPath == L'\\')
    {
      /* get nt drive path */
      pwDosDrive = pwDosPath;
      pwTarget = _GetSymbolicTarget(pwDosDrive);
      if (!pwTarget)
            return NULL;

      /* concat two part */
      RtlStringCbLengthW(pwTarget, NTSTRSAFE_MAX_CCH * sizeof(WCHAR), &l1);
      RtlStringCbLengthW(pwDosPath + 2, NTSTRSAFE_MAX_CCH * sizeof(WCHAR), &l2);
      pNtPath = ExAllocatePoolWithTag(NonPagedPool, l1 + l2 + sizeof(WCHAR), '_EL_');
      if (pNtPath)
      {
            RtlStringCbCopyW(pNtPath, l1 + sizeof(WCHAR), pwTarget);
            RtlStringCbCopyW(pNtPath + l1 / sizeof(WCHAR), l2 + sizeof(WCHAR), pwDosPath + 2);
      }
      else
      {
            DbgPrint(("hpsafe:%-4d ExAllocatePoolWithTag failed.\n", __LINE__));
      }
      ExFreePoolWithTag(pwTarget, '_EL_');
      return pNtPath;
    }
    else
    {
      DbgPrint(("hpsafe:%-4d unsupported path: %ws.\n", __LINE__, pwDosPath));
      return NULL;
    }
}

PWSTR _NtPathToDosPath(PCWSTR pwNtPath)
{
    PWSTR pwDosPath;
    WCHAR pwDosDrive[] = L"\\DosDevices\\X:";
    PWSTR pwTarget;
    WCHAR c;
    USHORT len;
    UNICODE_STRING usTarget;
    UNICODE_STRING usNtPath;
    UNICODE_STRING usDosPath;

    RtlInitUnicodeString(&usNtPath, pwNtPath);
    for (c = L'A'; c <= L'Z'; ++ c)
    {
      pwDosDrive = c;
      pwTarget = _GetSymbolicTarget(pwDosDrive);
      if (!pwTarget)
            continue;
      /*
      DbgPrint(("hpsafe:%-4d %c:\\ -> %ws.\n", __LINE__,
            (CHAR)c, pwTarget));
      */
      RtlInitUnicodeString(&usTarget, pwTarget);
      if (RtlPrefixUnicodeString(&usTarget, &usNtPath, TRUE))
      {
            len = (wcslen(pwNtPath) - wcslen(pwTarget) + 4) * sizeof(WCHAR);
            pwDosPath = ExAllocatePoolWithTag(NonPagedPool, len, '_EL_');
            if (!pwDosPath)
            {
                DbgPrint(("hpsafe:%-4d ExAllocatePoolWithTag failed.\n", __LINE__));
                return NULL;
            }
                        memset(pwDosPath, 0, len);
            RtlInitEmptyUnicodeString(&usDosPath, pwDosPath, len);
            RtlUnicodeStringCopyString(&usDosPath, L"x:");
            *pwDosPath = c;
            RtlUnicodeStringCatString(&usDosPath, pwNtPath + wcslen(pwTarget) );
            return pwDosPath;
      }
    }

    return NULL;
}

mmlai8 发表于 2018-1-23 02:14:15

感谢分享,看看怎么实现的
页: [1]
查看完整版本: [开源]NT路径转DOS路径的简单办法