gpt4 book ai didi

windows-7 - 在 Windows 7 欢迎屏幕上运行进程

转载 作者:行者123 更新时间:2023-12-04 01:35:45 29 4
gpt4 key购买 nike

所以这是独家新闻:

不久前我编写了一个小型 C# 应用程序,它显示主机名、IP 地址、成像日期、解冻状态(我们使用 DeepFreeze)、当前域和当前日期/时间,以显示在我们的 Windows 7 实验室机器的欢迎屏幕上.这是为了替换我们之前的信息 block ,它在启动时静态设置,实际上将文本嵌入到背景中,变得更加动态和实用。该应用程序使用 Timer 来更新 IP 地址、deepfreeze 状态和每秒时钟,它会检查用户是否已登录并在检测到此类情况时杀死自己。

如果我们只是通过我们的启动脚本(通过组策略设置)运行它,它会使脚本保持打开状态,并且机器永远不会进入登录提示符。如果我们使用 start 或 cmd 命令之类的命令在单独的 shell/进程下启动它,它会一直运行到启动脚本完成,此时 Windows 似乎会清理脚本的所有子进程。我们目前可以使用 psexec -s -d -i -x 绕过它。启动它,让它在启动脚本完成后持续存在,但速度可能非常慢,在我们的启动时间中增加 5 秒到 1 多分钟之间的任何时间。

我们已经尝试过使用另一个 C# 应用程序来启动进程,通过 Process 类,使用带有各种启动标志的 WMI 调用(Win32_Process 和 Win32_ProcessStartup)等,但都以脚本完成和信息 block 进程获取的相同结果结束被杀。我尝试将应用程序重写为服务,但服务从未被设计为与桌面交互,更不用说登录窗口了,而且让事情在正确的上下文中运行似乎从来没有真正成功过。

所以对于这个问题:有没有人有一个很好的方法来做到这一点?启动一个任务,使其独立于启动脚本并在欢迎屏幕上运行?

最佳答案

忽略 pre-Vista 操作系统,假设您的 token 上有 TCB 权限(基本上作为系统运行),您可以使用 CreateProcessAsUser去做这个。
作为系统运行的示例(例如:NT 服务或使用 psexec -s )将在控制台 session winlogon 桌面中启动记事本:

#define WIN32_LEAN_AND_MEAN

#pragma comment(lib, "Userenv.lib")

#include <Windows.h>
#include <UserEnv.h>
#include <iostream>
#include <string>

HANDLE GetTokenForStart();
LPVOID GetEnvBlockForUser(HANDLE hToken);
void StartTheProcess(HANDLE hToken, LPVOID pEnvironment);

int main(int argc, wchar_t* argv[])
{
//while (!IsDebuggerPresent()) Sleep(500);

try
{
HANDLE hUserToken = GetTokenForStart();
LPVOID env = GetEnvBlockForUser(hUserToken);
StartTheProcess(hUserToken, env);
}
catch (std::wstring err)
{
auto gle = GetLastError();
std::wcerr << L"Error: " << err << L" GLE: " << gle << L"\r\n";
return -1;
}
}

HANDLE GetTokenForStart()
{
HANDLE hToken = 0;
{
HANDLE processToken = 0;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_EXECUTE, &processToken))
{
throw std::wstring(L"Could not open current process token");
}
if (!DuplicateTokenEx(processToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hToken))
{
throw std::wstring(L"Could not duplicate process token");
}
}

DWORD consoleSessionId = WTSGetActiveConsoleSessionId();
if (!SetTokenInformation(hToken, TokenSessionId, &consoleSessionId, sizeof(consoleSessionId)))
{
throw std::wstring(L"Could not set session ID");
}

return hToken;
}

LPVOID GetEnvBlockForUser(HANDLE hToken)
{
LPVOID pEnvironment = NULL;
if (!CreateEnvironmentBlock(&pEnvironment, hToken, FALSE))
{
throw std::wstring(L"Could not create env block");
}
return pEnvironment;
}

void StartTheProcess(HANDLE hToken, LPVOID pEnvironment)
{
STARTUPINFO si = { 0 };
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
si.lpDesktop = (LPWSTR)L"winsta0\\winlogon";

wchar_t path[MAX_PATH] = L"notepad.exe";

PROCESS_INFORMATION pi = { 0 };
if (!CreateProcessAsUser(hToken, NULL, path, NULL, NULL, FALSE,
CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, pEnvironment, NULL, &si, &pi))
{
throw std::wstring(L"Could not start process");
}

if (!CloseHandle(pi.hThread))
{
throw std::wstring(L"Could not close thread handle");
}
}
或者,如果您更喜欢 C#:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;

namespace StartWinlogonManaged
{
class Program
{
static void Main(string[] args)
{
var hUserToken = GetTokenForStart();
var env = GetEnvBlockForUser(hUserToken);
StartTheProcess(hUserToken, env);
}

const string
Advapi32 = "advapi32.dll",
Userenv = "userenv.dll",
Kernel32 = "kernel32.dll";

[DllImport(Kernel32, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetCurrentProcess();

[DllImport(Advapi32, ExactSpelling = true, SetLastError = true)]
public static extern bool OpenProcessToken(IntPtr ProcessToken, int DesiredAccess, out IntPtr TokenHandle);

[DllImport(Advapi32, ExactSpelling = true, SetLastError = true)]
public static extern bool DuplicateTokenEx(IntPtr ExistingToken, int DesiredAccess,
IntPtr TokenAttributes, int ImpersonationLevel, int TokenType, out IntPtr NewToken);

[DllImport("kernel32.dll", ExactSpelling = true)]
static extern int WTSGetActiveConsoleSessionId();

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetTokenInformation(IntPtr hToken,
int tokenInfoClass, ref int pTokenInfo, int tokenInfoLength);

static IntPtr GetTokenForStart()
{
IntPtr hToken = IntPtr.Zero;
{
IntPtr processToken = IntPtr.Zero;
if (!OpenProcessToken(GetCurrentProcess(), 0x2001f /* TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_EXECUTE */, out processToken))
{
throw new Win32Exception("Could not open current process token");
}
if (!DuplicateTokenEx(processToken, 0x02000000 /* MAXIMUM_ALLOWED */, IntPtr.Zero, 2 /* SecurityImpersonation */, 1 /* TokenPrimary */, out hToken))
{
throw new Win32Exception("Could not duplicate process token");
}
}

int consoleSessionId = WTSGetActiveConsoleSessionId();
if (!SetTokenInformation(hToken, 12 /* TokenSessionId */, ref consoleSessionId, 4 /* sizeof(int) */))
{
throw new Win32Exception("Could not set session ID");
}

return hToken;
}

[DllImport(Userenv, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);

static IntPtr GetEnvBlockForUser(IntPtr hToken)
{
IntPtr pEnvironment = IntPtr.Zero;
if (!CreateEnvironmentBlock(out pEnvironment, hToken, true))
{
throw new Win32Exception("Could not create env block");
}
return pEnvironment;
}

[DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CreateProcessAsUser(IntPtr hToken,
StringBuilder appExeName, StringBuilder commandLine, IntPtr processAttributes,
IntPtr threadAttributes, bool inheritHandles, uint dwCreationFlags,
IntPtr environment, string currentDirectory, ref STARTUPINFO startupInfo,
out PROCESS_INFORMATION startupInformation);

[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}

[StructLayout(LayoutKind.Sequential)]
internal struct STARTUPINFO
{
public int cb;
public IntPtr lpReserved;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpDesktop;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}

[DllImport(Kernel32, ExactSpelling = true, SetLastError = true)]
public static extern bool CloseHandle(IntPtr handle);

static void StartTheProcess(IntPtr hToken, IntPtr pEnvironment)
{
var si = new STARTUPINFO();
si.cb = Marshal.SizeOf<STARTUPINFO>();
si.dwFlags = 1 /* STARTF_USESHOWWINDOW */;
si.wShowWindow = 5 /* SW_SHOW */;
si.lpDesktop = "winsta0\\winlogon";

var path = new StringBuilder("notepad.exe", 260);

PROCESS_INFORMATION pi;
if (!CreateProcessAsUser(hToken, null, path, IntPtr.Zero, IntPtr.Zero, false,
0x410 /* CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT */, pEnvironment, null, ref si, out pi))
{
throw new Win32Exception("Could not start process");
}

if (!CloseHandle(pi.hThread))
{
throw new Win32Exception("Could not close thread handle");
}
}
}
}
请注意,这确实需要在您的 token 中启用多个权限(TCB、AssignPrimaryToken、IncreaseQuota)。此代码还泄漏句柄,没有制定完整的命令行,使用名称常量等......,并且仅用作说明性引用 - 而不是作为现成的解决方案。

关于windows-7 - 在 Windows 7 欢迎屏幕上运行进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3070152/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com