在 Windows XP 登录屏幕 (.NET / Pinvoke) 上运行进程(使用 GUI)

2024-02-20

我需要写一个小service运行一个应用程序(使用 GUI,例如calc.exe)在登录屏幕上。

我已经找到这个问题(和答案):在 Windows 7 欢迎屏幕上运行进程 https://stackoverflow.com/questions/3070152/running-a-process-at-the-windows-7-welcome-screen

如果您不明白这是如何工作的,请阅读代码注释:

        // grab the winlogon process
        Process winLogon = null;
        foreach (Process p in Process.GetProcesses())
        {
            if (p.ProcessName.Contains("winlogon"))
            {
                winLogon = p;
                break;
            }
        }
        // grab the winlogon's token
        IntPtr userToken = IntPtr.Zero;
        if (!OpenProcessToken(winLogon.Handle, TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, out userToken))
        {
            log("ERROR: OpenProcessToken returned false - " + Marshal.GetLastWin32Error());
        }

        // create a new token
        IntPtr newToken = IntPtr.Zero;
        SECURITY_ATTRIBUTES tokenAttributes = new SECURITY_ATTRIBUTES();
        tokenAttributes.nLength = Marshal.SizeOf(tokenAttributes);
        SECURITY_ATTRIBUTES threadAttributes = new SECURITY_ATTRIBUTES();
        threadAttributes.nLength = Marshal.SizeOf(threadAttributes);
        // duplicate the winlogon token to the new token
        if (!DuplicateTokenEx(userToken, 0x10000000, ref tokenAttributes, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
            TOKEN_TYPE.TokenImpersonation, out newToken))
        {
            log("ERROR: DuplicateTokenEx returned false - " + Marshal.GetLastWin32Error());
        }
        TOKEN_PRIVILEGES tokPrivs = new TOKEN_PRIVILEGES();
        tokPrivs.PrivilegeCount = 1;
        LUID seDebugNameValue = new LUID();
        if (!LookupPrivilegeValue(null, SE_DEBUG_NAME, out seDebugNameValue))
        {
            log("ERROR: LookupPrivilegeValue returned false - " + Marshal.GetLastWin32Error());
        }
        tokPrivs.Privileges = new LUID_AND_ATTRIBUTES[1];
        tokPrivs.Privileges[0].Luid = seDebugNameValue;
        tokPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        // escalate the new token's privileges
        if (!AdjustTokenPrivileges(newToken, false, ref tokPrivs, 0, IntPtr.Zero, IntPtr.Zero))
        {
            log("ERROR: AdjustTokenPrivileges returned false - " + Marshal.GetLastWin32Error());
        }
        PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
        STARTUPINFO si = new STARTUPINFO();
        si.cb = Marshal.SizeOf(si);
        si.lpDesktop = "Winsta0\\Winlogon";
        // start the process using the new token
        if (!CreateProcessAsUser(newToken, "calc.exe", null, ref tokenAttributes, ref threadAttributes,
            true, (uint)CreateProcessFlags.CREATE_NEW_CONSOLE | (uint)CreateProcessFlags.INHERIT_CALLER_PRIORITY, IntPtr.Zero,
            "C:\\Windows\\System32", ref si, out pi))
        {
            log("ERROR: CreateProcessAsUser returned false - " + Marshal.GetLastWin32Error());
        }

        Process _p = Process.GetProcessById(pi.dwProcessId);
        if (_p != null)
        {
            log("Process " + _p.Id + " Name " + _p.ProcessName);
        }
        else
        {
            log("Process not found");
        }

它适用于 Windows 7。使用 XP 我收到错误 1349ERROR_BAD_TOKEN_TYPE打电话时CreateProcessAsUser (MSDN: 令牌的类型不适合其尝试使用。).

在Windows XP中如何实现这一点呢?它不一定是上面的代码,但它应该作为服务工作(使用系统帐户?)。

感谢您的支持 助焊剂


这肯定与权限问题有关(Windows Vista 和 7 在安全性方面有显着变化)。不要尝试获取 winlogon.exe 的令牌并模拟它,而是尝试通过以下方式获取用户令牌WTSQueryUserToken像这样:

WTSQueryUserToken (WTSGetActiveConsoleSessionId(), out userToken);

将用于获取令牌的 OpenProcessToken 行替换为上述语句。

你的新代码应该是这样的:

//        if (!OpenProcessToken(winLogon.Handle, TOKEN_QUERY | TOKEN_IMPERSONATE | //TOKEN_DUPLICATE, out userToken))
//        {
//            log("ERROR: OpenProcessToken returned false - " + //Marshal.GetLastWin32Error());
//        }

WTSQueryUserToken (WTSGetActiveConsoleSessionId(), out userToken);

你的dll导入是这样的:

[DllImport("Kernel32.dll", SetLastError = true)]
[return:MarshalAs(UnmanagedType.U4)]
public static extern int WTSGetActiveConsoleSessionId ( );

您只需用此代码替换我注释掉的部分即可。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Windows XP 登录屏幕 (.NET / Pinvoke) 上运行进程(使用 GUI) 的相关文章

随机推荐