pee*_*man 11 login-script windows-7
所以这是独家新闻:
我在前一段时间写了一个小小的C#应用程序,显示主机名,IP地址,图像日期,解冻状态(我们使用DeepFreeze),当前域和当前日期/时间,以显示在我们的Windows 7实验室机器的欢迎屏幕上.这是为了取代我们以前的信息块,它是在启动时静态设置的,实际上是嵌入到背景中的文本,带有更多动态和功能.该应用程序使用Timer来每秒更新IP地址,deepfreeze状态和时钟,并检查用户是否已登录并在检测到此类情况时自行终止.
如果我们只是通过我们的启动脚本(通过组策略设置)运行它,它会保持脚本打开,并且机器永远不会进入登录提示.如果我们使用类似start或cmd命令的东西在单独的shell /进程下启动它,它将运行直到启动脚本完成,此时Windows似乎清理脚本的所有子进程.我们现在能够绕过它psexec -s -d -i -x来启动它,这使得它在启动脚本完成后仍然存在,但可能非常慢,在我们的启动时间增加了5秒到一分钟之间.
我们已经尝试使用另一个C#应用程序来启动进程,通过Process类,使用WMI调用(Win32_Process和Win32_ProcessStartup)以及各种启动标志等,但所有结束都与脚本完成和信息块进程获得相同的结果杀害.我修改了将应用程序重写为服务,但服务从未设计为与桌面交互,更不用说登录窗口,并且在正确的上下文中运行操作似乎从未真正解决过.
所以对于这个问题:有没有人有一个很好的方法来实现这个目标?启动一个任务,使其独立于启动脚本并在欢迎屏幕上运行?
小智 12
这可以通过许多Win32 API调用来完成.我已经设法将一个带有GUI的程序放到Winlogon桌面上(在任何人要求之前,它不是一个交互式GUI).基本上,您需要以SYSTEM身份运行加载程序进程,然后将生成新进程.由于您很可能希望此过程在启动时运行,因此您可以使用任务计划程序以SYSTEM身份运行加载程序,也可以使用服务执行相同的操作.我目前正在使用服务,但我尝试使用任务调度程序,它确实工作得很好.
简短的摘要:
代码示例:
// 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, process, process, ref tokenAttributes, ref threadAttributes,
true, (uint)CreateProcessFlags.CREATE_NEW_CONSOLE | (uint)CreateProcessFlags.INHERIT_CALLER_PRIORITY, IntPtr.Zero,
logInfoDir, 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");
}
Run Code Online (Sandbox Code Playgroud)
这是"你真的需要一个很好的理由来做这个"问题之一.Microsoft非常努力地阻止在启动屏幕上运行的应用程序 - Windows中与登录屏幕交互的每一段代码都经过仔细的代码审查,因为在登录屏幕上运行的代码中的错误的安全后果是可怕的 - 如果你搞砸了甚至稍微提高,你将允许恶意软件进入计算机.
为什么要在登录屏幕上运行程序?也许有一种记录在案的方式并没有风险.
我在C++中翻译了上面的代码,如果其他人需要它...注意我的代码部分有引用,但它可能有所帮助:
static bool StartProcess(LPCTSTR lpApplicationPath)
{
CAutoGeneralHandle hWinlogonProcess = FindWinlogonProcess();
if (hWinlogonProcess == INVALID_HANDLE_VALUE)
{
DU_OutputDebugStringff(L"ERROR: Can't find the 'winlogon' process");
return false;
}
CAutoGeneralHandle hUserToken;
if (!OpenProcessToken(hWinlogonProcess, TOKEN_QUERY|TOKEN_IMPERSONATE|TOKEN_DUPLICATE, &hUserToken))
{
DU_OutputDebugStringff(L"ERROR: OpenProcessToken returned false (error %u)", GetLastError());
return false;
}
// Create a new token
SECURITY_ATTRIBUTES tokenAttributes = {0};
tokenAttributes.nLength = sizeof tokenAttributes;
SECURITY_ATTRIBUTES threadAttributes = {0};
threadAttributes.nLength = sizeof threadAttributes;
// Duplicate the winlogon token to the new token
CAutoGeneralHandle hNewToken;
if (!DuplicateTokenEx(hUserToken, 0x10000000, &tokenAttributes,
SECURITY_IMPERSONATION_LEVEL::SecurityImpersonation,
TOKEN_TYPE::TokenImpersonation, &hNewToken))
{
DU_OutputDebugStringff(L"ERROR: DuplicateTokenEx returned false (error %u)", GetLastError());
return false;
}
TOKEN_PRIVILEGES tokPrivs = {0};
tokPrivs.PrivilegeCount = 1;
LUID seDebugNameValue = {0};
if (!LookupPrivilegeValue(nullptr, SE_DEBUG_NAME, &seDebugNameValue))
{
DU_OutputDebugStringff(L"ERROR: LookupPrivilegeValue returned false (error %u)", GetLastError());
return false;
}
tokPrivs.Privileges[0].Luid = seDebugNameValue;
tokPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Escalate the new token's privileges
if (!AdjustTokenPrivileges(hNewToken, false, &tokPrivs, 0, nullptr, nullptr))
{
DU_OutputDebugStringff(L"ERROR: AdjustTokenPrivileges returned false (error %u)", GetLastError());
return false;
}
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
si.cb = sizeof si;
si.lpDesktop = L"Winsta0\\Winlogon";
// Start the process using the new token
if (!CreateProcessAsUser(hNewToken, lpApplicationPath, nullptr, &tokenAttributes, &threadAttributes,
true, CREATE_NEW_CONSOLE|INHERIT_CALLER_PRIORITY, nullptr, nullptr, &si, &pi))
{
DU_OutputDebugStringff(L"ERROR: CreateProcessAsUser returned false (error %u)", GetLastError());
return false;
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14217 次 |
| 最近记录: |