Can I mapping network drive in very special way using winapi?

泪湿孤枕 提交于 2020-06-29 03:48:13

问题


I have to start my application with admin privileges ( very important ).

When I execute this code without admin privileges everything is perfect. There is an icon in MyComputer.

NETRESOURCE nrServer;
memset(&nrServer, 0, sizeof (NETRESOURCE));
nrServer.dwType = RESOURCETYPE_ANY;
nrServer.lpLocalName = L"S:";
nrServer.lpRemoteName = L"\\\\192.168.32.36\\folderName";
nrServer.lpProvider = L"";
auto dwError = WNetAddConnection2(&nrServer, L"user", L"pass", 0);

But when I execute this code above in application with admin privileges, there is no icon in MyComputer.

I think that can be usefull: Mapped network drives are not showing in My Computer

Is there any way to execute winapi function as not admin when my application has admin privileges?


回答1:


from WNetAddConnection2W

the WNet functions create and delete network drive letters in the MS-DOS device namespace associated with a logon session because MS-DOS devices are identified by AuthenticationID (a locally unique identifier, or LUID, associated with a logon session.)

also

if a code that runs as LocalSystem calls the WNetAddConnection2 function, then the mapped drive is visible to all user logon sessions.

technically this mean if code run as LocalSystem in the \GLOBAL??\ folder will be create symbolic link to network disk. otherwise link will be created under

\Sessions\0\DosDevices\<token LogonId>\

and will be visible only for threads(processes) which have the same LogonId in token

if your code have admin privileges - it usually (almost always) have debug privileges. with this we can open process with LocalSystem token and impersonate it before call WNetAddConnection2.

possible also get TCB privilege and after this call WTSQueryUserToken, convert primary token to impersonation token, via DuplicateToken, and impersonate - SetThreadToken. and call WNetAddConnection2 finally.

ok. i try first simply impersonate to LocalSystem

let we have function

NTSTATUS ImpersonateSystemOrTcbToken(bool bTcb);

which set LocalSystem or token with Tcb privileges to current thread (as far i know all LocalSystem tokens have TCB privilege but anyway write 2 different code for get exactly token with TCB or with LocalSystem)

and

HRESULT AdjustDebugPrivilegesToThread();

which enable debug privileges in current thread token (it must exist in admin token)

in this case code can be next:

inline HRESULT BOOL_TO_HRESULT(BOOL f)
{
    return f ? NOERROR : HRESULT_FROM_WIN32(GetLastError());
}

HRESULT MapRemoteDrive(PCWSTR local, PCWSTR remote, PCWSTR username, PCWSTR password)
{
    NETRESOURCEW nr = {
        0, RESOURCETYPE_DISK, 0, 0, const_cast<PWSTR>(local), const_cast<PWSTR>(remote)
    };
    return HRESULT_FROM_WIN32(WNetAddConnection2W(&nr, password, username, 0));
}

HRESULT MapRemoteDriveEx1(PCWSTR local, PCWSTR remote, PCWSTR username, PCWSTR password)
{
    HRESULT hr = BOOL_TO_HRESULT(ImpersonateSelf(::SecurityImpersonation));

    if (SUCCEEDED(hr))
    {
        if (SUCCEEDED(hr = AdjustDebugPrivilegesToThread()) &&
            SUCCEEDED(hr = HRESULT_FROM_NT(ImpersonateSystemOrTcbToken(false))))
        {
            hr = MapRemoteDrive(local, remote, username, password);
            // WNetCancelConnection2W(local, 0, TRUE);
        }

        SetThreadToken(0, 0);
    }

    return hr;
}

code work ok and really network location created, but with next view:

despite this - drive is browsed correct on click. i not research why is Disconected word in description. but possible some problems with permissions here

if try create drive for concrete LUID, code will be more complex

HRESULT MapRemoteDriveEx2(PCWSTR local, PCWSTR remote, PCWSTR username, PCWSTR password)
{
    HRESULT hr = BOOL_TO_HRESULT(ImpersonateSelf(::SecurityImpersonation));

    if (SUCCEEDED(hr))
    {
        HANDLE hToken, hImpToken;
        if (SUCCEEDED(hr = AdjustDebugPrivilegesToThread()) &&
            SUCCEEDED(hr = HRESULT_FROM_NT(ImpersonateSystemOrTcbToken(true))) &&
            SUCCEEDED(hr = BOOL_TO_HRESULT(WTSQueryUserToken(WTSGetActiveConsoleSessionId(), &hToken))))
        {
            hr = BOOL_TO_HRESULT(DuplicateToken(hToken, ::SecurityImpersonation, &hImpToken));
            CloseHandle(hToken);
            if (SUCCEEDED(hr))
            {
                hr = BOOL_TO_HRESULT(SetThreadToken(0, hImpToken));
                CloseHandle(hImpToken);

                if (SUCCEEDED(hr))
                {
                    hr = MapRemoteDrive(local, remote, username, password);
                    // WNetCancelConnection2W(local, 0, TRUE);
                }
            }
        }

        SetThreadToken(0, 0);
    }

    return hr;
}

with this result full ok

now code for util functions:

HRESULT AdjustDebugPrivilegesToThread()
{
    ULONG dwError;
    HANDLE hToken;
    if (OpenThreadToken(NtCurrentThread(), TOKEN_ADJUST_PRIVILEGES, TRUE, &hToken))
    {
        static const ::TOKEN_PRIVILEGES tp = { 1, { { { SE_DEBUG_PRIVILEGE } } } };

        AdjustTokenPrivileges(hToken, FALSE, const_cast<::PTOKEN_PRIVILEGES>(&tp), 0, 0, 0);

        dwError = GetLastError();

        CloseHandle(hToken);
    }
    else
    {
        dwError = GetLastError();
    }

    return HRESULT_FROM_WIN32(dwError);
}

and..

NTSTATUS GetSystemToken(PVOID buf)
{
    NTSTATUS status;

    union {
        PVOID pv;
        PBYTE pb;
        PSYSTEM_PROCESS_INFORMATION pspi;
    };

    pv = buf;
    ULONG NextEntryOffset = 0;

    do 
    {
        pb += NextEntryOffset;

        HANDLE hProcess, hToken, hNewToken;

        CLIENT_ID ClientId = { pspi->UniqueProcessId };

        if (ClientId.UniqueProcess)
        {
            static SECURITY_QUALITY_OF_SERVICE sqos = {
                sizeof sqos, SecurityImpersonation, SECURITY_DYNAMIC_TRACKING, FALSE
            };

            static OBJECT_ATTRIBUTES soa = { sizeof(soa), 0, 0, 0, 0, &sqos };

            if (0 <= NtOpenProcess(&hProcess, PROCESS_QUERY_LIMITED_INFORMATION, &zoa, &ClientId))
            {
                status = NtOpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_DUPLICATE, &hToken);

                NtClose(hProcess);

                if (0 <= status)
                {
                    ULONG rcb;
                    TOKEN_STATISTICS ts;
                    static const LUID SystemLuid = SYSTEM_LUID;

                    status = -1;

                    if (0 <= NtQueryInformationToken(hToken, TokenStatistics, &ts, sizeof(ts), &rcb) &&
                        ts.AuthenticationId.LowPart == SystemLuid.LowPart &&
                        ts.AuthenticationId.HighPart == SystemLuid.HighPart)
                    {
                        status = NtDuplicateToken(hToken, TOKEN_IMPERSONATE, 
                            &soa, FALSE, TokenImpersonation, &hNewToken);
                    }

                    NtClose(hToken);

                    if (0 <= status)
                    {
                        status = NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &hNewToken, sizeof(hNewToken));
                        
                        NtClose(hNewToken);

                        return status;
                    }
                }
            }
        }

    } while (NextEntryOffset = pspi->NextEntryOffset);

    return STATUS_UNSUCCESSFUL;
}

NTSTATUS GetTcbToken(PVOID buf)
{
    NTSTATUS status;

    union {
        PVOID pv;
        PBYTE pb;
        PSYSTEM_PROCESS_INFORMATION pspi;
    };

    pv = buf;
    ULONG NextEntryOffset = 0;

    do 
    {
        pb += NextEntryOffset;

        HANDLE hProcess, hToken, hNewToken;

        if (pspi->InheritedFromUniqueProcessId && pspi->UniqueProcessId)
        {
            static SECURITY_QUALITY_OF_SERVICE sqos = {
                sizeof sqos, SecurityImpersonation, SECURITY_DYNAMIC_TRACKING, FALSE
            };

            static OBJECT_ATTRIBUTES soa = { sizeof(soa), 0, 0, 0, 0, &sqos };

            CLIENT_ID ClientId = { pspi->UniqueProcessId };

            if (0 <= NtOpenProcess(&hProcess, PROCESS_QUERY_LIMITED_INFORMATION, &zoa, &ClientId))
            {
                status = NtOpenProcessToken(hProcess, TOKEN_DUPLICATE, &hToken);

                NtClose(hProcess);

                if (0 <= status)
                {
                    status = NtDuplicateToken(hToken, TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE, 
                        &soa, FALSE, TokenImpersonation, &hNewToken);

                    NtClose(hToken);

                    if (0 <= status)
                    {
                        static const TOKEN_PRIVILEGES tp = { 1, { { { SE_DEBUG_PRIVILEGE } } } };

                        status = NtAdjustPrivilegesToken(hNewToken, FALSE, const_cast<PTOKEN_PRIVILEGES>(&tp), 0, 0, 0);

                        if (STATUS_SUCCESS == status)   
                        {
                            status = NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &hNewToken, sizeof(hNewToken));
                        }

                        NtClose(hNewToken);

                        if (STATUS_SUCCESS == status)
                        {
                            return STATUS_SUCCESS;
                        }
                    }
                }
            }
        }

    } while (NextEntryOffset = pspi->NextEntryOffset);

    return STATUS_UNSUCCESSFUL;
}

NTSTATUS ImpersonateSystemOrTcbToken(bool bTcb)
{
    NTSTATUS status;

    ULONG cb = 0x10000;

    do 
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        if (PBYTE buf = new BYTE[cb += 0x1000])
        {
            if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
            {
                status = (bTcb ? GetTcbToken : GetSystemToken)(buf);

                if (status == STATUS_INFO_LENGTH_MISMATCH)
                {
                    status = STATUS_UNSUCCESSFUL;
                }
            }

            delete [] buf;
        }

    } while(status == STATUS_INFO_LENGTH_MISMATCH);

    return status;
}


来源:https://stackoverflow.com/questions/62562195/can-i-mapping-network-drive-in-very-special-way-using-winapi

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!