Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
无法获取映射驱动器C/C的关联网络UNC++_C_Windows_Uac_Unc_Mapped Drive - Fatal编程技术网

无法获取映射驱动器C/C的关联网络UNC++

无法获取映射驱动器C/C的关联网络UNC++,c,windows,uac,unc,mapped-drive,C,Windows,Uac,Unc,Mapped Drive,编写了一个DLL,试图将映射驱动器转换为其等效的网络UNC。但当DLL被作为提升进程运行的安装程序调用时,它会失败。作为一种潜在的修复方法,我修改了@RbMn提供的示例源代码,对以下问题进行了回答: 对GetLogicalDrives的调用就像声明的那样工作。但是,当它使用映射的驱动器号调用WNetGetConnection时,返回的错误是1222 error_NO_NETWORK,因此不会给出相关的UNC。我相信这个问题源于我如何假装登录。由于我对UAC事务的了解非常有限,我不确定为了正确获取

编写了一个DLL,试图将映射驱动器转换为其等效的网络UNC。但当DLL被作为提升进程运行的安装程序调用时,它会失败。作为一种潜在的修复方法,我修改了@RbMn提供的示例源代码,对以下问题进行了回答:

对GetLogicalDrives的调用就像声明的那样工作。但是,当它使用映射的驱动器号调用WNetGetConnection时,返回的错误是1222 error_NO_NETWORK,因此不会给出相关的UNC。我相信这个问题源于我如何假装登录。由于我对UAC事务的了解非常有限,我不确定为了正确获取所需信息,我必须对模拟登录进行哪些修改

非常感谢您的帮助

以下是实际代码:

BOOL ConvertToMappedFolder(LPSTR pUncPath, LPSTR pMappedDrive)
{
   BOOL bRet = 0; 

if (1) 
{
  HANDLE hToken = NULL;
  ULONG rcb = 0;
  TOKEN_ELEVATION_TYPE tet = 0;
  TOKEN_LINKED_TOKEN tlt = { 0 };
  ULONG err = BOOL_TO_ERR(OpenProcessToken(GetCurrentProcess() /* NtCurrentProcess() */, TOKEN_QUERY, &hToken));

if (err == NOERROR)
{
  err = BOOL_TO_ERR(GetTokenInformation(hToken, TokenElevationType, &tet, sizeof(tet), &rcb));

  if (err == NOERROR)
  {
   if (tet == TokenElevationTypeFull)
   {
     err = BOOL_TO_ERR(GetTokenInformation(hToken, TokenLinkedToken, &tlt, sizeof(tlt), &rcb));

    if (err == NOERROR)
    {
      if (NOERROR == (err = BOOL_TO_ERR(SetThreadToken(0, tlt.LinkedToken))))
      {
         bRet = ConvertToMappedFolderEx(pUncPath, pMappedDrive); 
         SetThreadToken(0, 0);
      }

      CloseHandle(tlt.LinkedToken);
    }
  }
}
}
}

BOOL ConvertToMappedFolderEx(LPSTR pUncPath, LPSTR pMappedDrive)
{
int  nPos  = 0;
UINT nType = 0; 
char strDrive[MAX_PATH+1] = "?:\\"; 
DWORD dwDriveList = GetLogicalDrives();
BOOL bRet = FALSE; 

(*pMappedDrive) = 0; 

// Check each drive letter determining if it is a mapped drive...
while (dwDriveList) 
{
if (dwDriveList & 1) 
{
strDrive[0] = 0x41 + nPos;

nType = GetDriveType(strDrive);

// If drive unknown do not attempt to determine if its UNC matches up...
if (DRIVE_UNKNOWN != nType) 
{
char  szDeviceName[MAX_PATH+1] = ""; 
char  szDriveLetter[4] = " :"; 
DWORD dwResult = 0;
DWORD cchBuff  = MAX_PATH; 

szDriveLetter[0] = strDrive[0]; 
dwResult = WNetGetConnection(szDriveLetter, (LPSTR) szDeviceName, &cchBuff); 


if (NO_ERROR == dwResult) 
{ 
LPSTR pPath = _stristr(pUncPath, szDeviceName); 

if (NULL != pPath)
{
strcpy(pMappedDrive, szDriveLetter); 
strcat(pMappedDrive, (pUncPath + strlen(szDeviceName))); 

bRet = TRUE; 
break; 
}
}
}
}

dwDriveList >>= 1;
nPos++;
}

return (bRet); 
}

每个登录会话使用Microsoft LAN Manager进行连接。更确切地说,它与登录会话LUID关联。这存储在令牌中,可以从中读取。所以,若您模拟或处理,任何网络驱动器函数的结果都取决于您当前的令牌线程。使用不同的标记-可以得到不同的结果。提升进程和未提升进程始终在不同的登录会话中运行,进程令牌中的AuthenticationId不同

因此,在windows中谈论网络驱动器毫无意义。需要在登录会话中谈论网络驱动器。不同的登录会话具有不同的网络驱动器集。下一步我们可以做-枚举所有当前运行的进程,为每个进程打开它的令牌并查询AuthenticationId-然后我们可以一次模拟并查询每个新的AuthenticationId,或者说我们可以查询AuthenticationId以查找链接到提升令牌的未提升令牌,然后尝试使用此令牌找到进程,模拟它,并使用此令牌进行查询

代码示例:

void CheckDrives()
{
    LONG dwDriveList = GetLogicalDrives();

    WCHAR Drive[] = L"Z:";

    ULONG n = 1 + 'Z' - 'A';

    do 
    {
        if (_bittest(&dwDriveList, --n))
        {
            if (DRIVE_REMOTE == GetDriveTypeW(Drive))
            {
                PUSE_INFO_0 pui;

                if (NET_API_STATUS err = NetUseGetInfo(0, Drive, 0, (BYTE**)&pui))
                {
                    DbgPrint("%S error=%u\n", Drive, err);
                }
                else
                {
                    DbgPrint("%S -> %S\n", pui->ui0_local, pui->ui0_remote);
                    NetApiBufferFree(pui);
                }
            }
        }

        --*Drive;

    } while (n);
}

BOOL ImpersonateNotElevated(LUID AuthenticationId)
{
    BOOL fOk = FALSE;

    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (hSnapshot != INVALID_HANDLE_VALUE)
    {
        PROCESSENTRY32W pe = { sizeof(pe) };

        ULONG rcb;

        BOOL fFound = FALSE;

        if (Process32First(hSnapshot, &pe))
        {
            do 
            {
                if (HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID))
                {
                    HANDLE hToken, hNewToken;                   

                    if (OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_DUPLICATE, &hToken))
                    {
                        TOKEN_STATISTICS ts;

                        if (GetTokenInformation(hToken, TokenStatistics, &ts, sizeof(ts), &rcb))
                        {
                            if (ts.AuthenticationId.LowPart == AuthenticationId.LowPart && ts.AuthenticationId.HighPart == AuthenticationId.HighPart)
                            {
                                fFound = TRUE;

                                if (DuplicateToken(hToken, SecurityImpersonation, &hNewToken))
                                {
                                    fOk = SetThreadToken(0, hNewToken);

                                    CloseHandle(hNewToken);
                                }
                            }
                        }
                        CloseHandle(hToken);
                    }

                    CloseHandle(hProcess);
                }

            } while (!fFound && Process32Next(hSnapshot, &pe));
        }

        CloseHandle(hSnapshot);
    }

    return fOk;
}

void CheckDrivesNotElevated()
{
    HANDLE hToken;

    if (OpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &hToken))
    {
        union {
            TOKEN_ELEVATION_TYPE tet;
            TOKEN_LINKED_TOKEN tlt;
        };

        ULONG rcb;

        if (GetTokenInformation(hToken, TokenElevationType, &tet, sizeof(tet), &rcb))
        {
            if (tet == TokenElevationTypeFull)
            {
                if (GetTokenInformation(hToken, TokenLinkedToken, &tlt, sizeof(tlt), &rcb))
                {
                    TOKEN_STATISTICS ts;

                    BOOL fOk = GetTokenInformation(tlt.LinkedToken, ::TokenStatistics, &ts, sizeof(ts), &rcb);

                    CloseHandle(tlt.LinkedToken);

                    if (fOk)
                    {
                        if (ImpersonateNotElevated(ts.AuthenticationId))
                        {
                            CheckDrives();
                            SetThreadToken(0, 0);
                        }
                    }
                }
            }
            else
            {
                CheckDrives();
            }
        }
        CloseHandle(hToken);
    }
}

@HarryJohnston-否,WNetGetConnection或更好的NetUseGetInfo完全支持模拟。只是它不支持SecurityIdentification模拟级别。几乎没有人接受这个水平。GetLogicalDrives在这里很少例外。但对于WNetGetConnection,需要SecurityImpersonation级别。因此,需要更多的代码来实现进程内查询keep,记住提升的令牌可能有自己的一组驱动器映射(例如,如果用户打开了提升的命令窗口并使用了net use),因此您需要确定这两个令牌中的哪一个是您想要的。对于一个安装程序来说,一开始就关心驱动器映射是很奇怪的。感谢您提供的代码示例。复习之后,我对路易斯有了更好的了解。