-->

Mapping network drive using WNetAddConnection2 fro

2019-07-27 05:36发布

问题:

I have an application which calls WNetAddConnection2 to map a network drive. This works perfectly unless I run the application as Administrator (right click - Run As Administrator) in which case the function returns 0 (success) but the mapped drive does not appear.

What seems to be happening here is that there are two Contexts, the Admin one in which my program is running and the user one in which windows explorer is running and I am looking for the mapped drive. I think the drive mapping is succeeding the in "Admin Context" but is not visible in the "User context".

When I'm running as administrator Environment.GetLogicalDrives() includes the drive letter I tried to map, making me think the mapping succeeded in the "Admin Context".

Apologies if I have totally got the wrong idea with multiple contexts, but it seems like the best explanation for what I am seeing.

There are two potential answers to this question:

1) How do I map a drive so it is visible in all contexts?

2) How do I execute something (process / thread / API call) from a "Run as Administrator" process without Admin rights (i.e. within the "User Context")?

回答1:

1) drive will be visible only in logon session with LUID same as your token TOKEN_STATISTICS.AuthenticationId

will be created Symbolic link object under \Sessions\0\DosDevices\<LogonId>\<X>: to \Device\LanmamRedirector\;<X>:<LogonId>\server\share as result drive <X>: will be visible only for processes running in <LogonId> session. and processes running "As Admin" have different <LogonId> compare processes run not "As Admin"

2) you need impersonate another context before call NetUseAdd or WNetAddConnection2.

for example you can enumerate processes, found explorer which have same terminal SessionId (not confuse with logon sessions) and impersonate it (open it token, duplicate and impersonate) . or more general open every process token in same terminal session as your process, query it token TokenElevationType (TOKEN_ELEVATION_TYPE) and if it TokenElevationTypeLimited - duplicate and impersonate this token, before call NetUseAdd


How do I execute something (process / thread / API call) from a "Run as Administrator" process without Admin rights (i.e. within the "User Context")?

example of working code:

#include <TlHelp32.h>

#define BOOL_TO_ERR(b) ((b) ? NOERROR : GetLastError())

ULONG RunNonElevated(PCWSTR lpApplicationName, PWSTR lpCommandLine)
{
    HANDLE hToken;

    ULONG err = BOOL_TO_ERR(OpenProcessToken(NtCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hToken));

    if (err != NOERROR)
    {
        return err;
    }

    DWORD cb, rcb;

    union {
        TOKEN_ELEVATION_TYPE tet;
        TOKEN_LINKED_TOKEN tlt;
    };

    TOKEN_STATISTICS ts;
    LUID AuthenticationId = {};

    BOOL bSearchToken = FALSE, bFound = FALSE;

    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)
            {
                err = BOOL_TO_ERR(GetTokenInformation(tlt.LinkedToken, TokenStatistics, &ts, sizeof(ts), &rcb));

                CloseHandle(tlt.LinkedToken);

                if (bSearchToken = (err == NOERROR))
                {
                    AuthenticationId.LowPart = ts.AuthenticationId.LowPart;
                    AuthenticationId.HighPart = ts.AuthenticationId.HighPart;

                    TOKEN_PRIVILEGES tp = {
                        1, { { { SE_DEBUG_PRIVILEGE } , SE_PRIVILEGE_ENABLED } }
                    };

                    AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
                }
            }
        }
    }

    CloseHandle(hToken);

    STARTUPINFO si = { sizeof (si) };
    PROCESS_INFORMATION pi;

    if (bSearchToken)
    {
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

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

            static volatile UCHAR guz;

            PVOID stack = alloca(guz);

            cb = 0, rcb = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[SE_MAX_WELL_KNOWN_PRIVILEGE]);

            union {
                PVOID buf;
                PTOKEN_PRIVILEGES ptp;
            };

            BOOL fHavePrivs = FALSE;

            if (Process32FirstW(hSnapshot, &pe))
            {
                do 
                {
                    if (HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID))
                    {
                        if (OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_DUPLICATE, &hToken))
                        {

                            if (!fHavePrivs) do 
                            {
                                if (cb < rcb)
                                {
                                    cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
                                }

                                if (GetTokenInformation(hToken, TokenPrivileges, buf, cb, &rcb))
                                {
                                    if (ULONG PrivilegeCount = ptp->PrivilegeCount)
                                    {
                                        int n = 3;
                                        BOOL fAdjust = FALSE;

                                        PLUID_AND_ATTRIBUTES Privileges = ptp->Privileges;
                                        do 
                                        {
                                            switch (Privileges->Luid.LowPart)
                                            {
                                            case SE_ASSIGNPRIMARYTOKEN_PRIVILEGE:
                                            case SE_INCREASE_QUOTA_PRIVILEGE:
                                            case SE_DEBUG_PRIVILEGE:
                                                if (!(Privileges->Attributes & SE_PRIVILEGE_ENABLED))
                                                {
                                                    Privileges->Attributes |= SE_PRIVILEGE_ENABLED;
                                                    fAdjust = TRUE;
                                                }

                                                if (!--n)
                                                {
                                                    if (DuplicateTokenEx(hToken, 
                                                        TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE, 
                                                        0, SecurityImpersonation, TokenImpersonation, 
                                                        &tlt.LinkedToken))
                                                    {
                                                        if (fAdjust)
                                                        {
                                                            AdjustTokenPrivileges(tlt.LinkedToken, FALSE, ptp, rcb, NULL, NULL);
                                                        }
                                                        fHavePrivs = SetThreadToken(0, tlt.LinkedToken);
                                                        CloseHandle(tlt.LinkedToken);
                                                    }
                                                    goto __1;
                                                }
                                            }
                                        } while (Privileges++, --PrivilegeCount);
                                    }
                                    break;
                                }

                            } while (GetLastError() == ERROR_INSUFFICIENT_BUFFER);

__1:
                            if (fHavePrivs &&
                                GetTokenInformation(hToken, TokenStatistics, &ts, sizeof(ts), &rcb) &&
                                ts.AuthenticationId.LowPart == AuthenticationId.LowPart &&
                                ts.AuthenticationId.HighPart == AuthenticationId.HighPart)
                            {
                                bFound = DuplicateTokenEx(hToken, 
                                    TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY, 
                                    0, SecurityImpersonation, TokenPrimary, &tlt.LinkedToken);
                            }
                            CloseHandle(hToken);
                        }
                        CloseHandle(hProcess);
                    }
                } while (!bFound && Process32NextW(hSnapshot, &pe));
            }
            CloseHandle(hSnapshot);

            if (bFound)
            {
                err = BOOL_TO_ERR(CreateProcessAsUserW(tlt.LinkedToken, lpApplicationName, lpCommandLine, 
                    NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi));

                CloseHandle(tlt.LinkedToken);

                if (err == NOERROR)
                {
                    CloseHandle(pi.hThread);
                    CloseHandle(pi.hProcess);
                }
            }
        }
    }
    else if (err == NOERROR)
    {
        if ((err = BOOL_TO_ERR(CreateProcessW(lpApplicationName, lpCommandLine,
            NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))) == NOERROR)
        {
            CloseHandle(pi.hThread);
            CloseHandle(pi.hProcess);
        }
    }

    return err;
}