如何在系统登陆桌面运行程序
来源:互联网 发布:windows配置ntp客户端 编辑:程序博客网 时间:2024/05/18 00:45
这是有位朋友看到我的博客文章《OpenThread种种》中的这个截屏后问的问题,这里解释一下。
首先要明白的是,在基于Windows NT(包括2K/XP/2K3等)的系统中,除了smss.exe (Session Manager Subsystem),其他进程都至少关联到一个Window Station和一个Desktop(Desktop隶属于某个Window Station)。在用户登陆后,运行的程序一般都关联到WinSta0/Default桌面(WinSta0为window station名,Default为桌面名)。对于以系统身份登陆的服务程序,会关联到Service-0x0-3e7$/Default。而上面截图中的系统登陆界面则是WinSta0/Winlogon。
如果你使用过CreateProcess API的话应该对STARTUPINFO结构不陌生:
这里关键的一个参数是lpDesktop。在登陆界面运行一个程序其实就是把它的桌面指定到"WinSta0/Winlogon":
真的就这么简单?基本上就这么简单,前提是你得有足够高的权限来运行这段代码。高到什么程度?高到你至少要有管理员权限,但在运行这段代码之前你还要拿到比管理员还高的权限,即SYSTEM权限才行!其实关键是要拿到TCB特权-如果你的帐号有这个特权,直接运行这段代码就行了。否则的话就要费点儿劲。有几种方法可用。
首先要明白的是,在基于Windows NT(包括2K/XP/2K3等)的系统中,除了smss.exe (Session Manager Subsystem),其他进程都至少关联到一个Window Station和一个Desktop(Desktop隶属于某个Window Station)。在用户登陆后,运行的程序一般都关联到WinSta0/Default桌面(WinSta0为window station名,Default为桌面名)。对于以系统身份登陆的服务程序,会关联到Service-0x0-3e7$/Default。而上面截图中的系统登陆界面则是WinSta0/Winlogon。
如果你使用过CreateProcess API的话应该对STARTUPINFO结构不陌生:
typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO, *LPSTARTUPINFO;
这里关键的一个参数是lpDesktop。在登陆界面运行一个程序其实就是把它的桌面指定到"WinSta0/Winlogon":
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(STARTUPINFO) );
si.cb = sizeof( STARTUPINFO );
si.lpDesktop = "WinSta0/Winlogon";
if( ::CreateProcessA( "c://windows//system32//notepad.exe",
NULL, NULL, NULL, FALSE, 0, NULL, NULL,
&si, &pi ) )
{
::CloseHandle( pi.hProcess );
::CloseHandle( pi.hThread );
}
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(STARTUPINFO) );
si.cb = sizeof( STARTUPINFO );
si.lpDesktop = "WinSta0/Winlogon";
if( ::CreateProcessA( "c://windows//system32//notepad.exe",
NULL, NULL, NULL, FALSE, 0, NULL, NULL,
&si, &pi ) )
{
::CloseHandle( pi.hProcess );
::CloseHandle( pi.hThread );
}
真的就这么简单?基本上就这么简单,前提是你得有足够高的权限来运行这段代码。高到什么程度?高到你至少要有管理员权限,但在运行这段代码之前你还要拿到比管理员还高的权限,即SYSTEM权限才行!其实关键是要拿到TCB特权-如果你的帐号有这个特权,直接运行这段代码就行了。否则的话就要费点儿劲。有几种方法可用。
- 方法之一,是用组策略编辑器给你的帐号加上TCB特权:
- 方法之二是把你的程序安装成服务程序并以系统帐号运行。缺点是你要写一个服务程序,好像有点儿小题大做。
- 方法之三是Scheduler启动你的程序:at <hh:mm> "your program"。缺点是Scheduler服务程序必须运行。
- 方法之四,是远程注入,即写一段代码把CreateProcess代码注入到具有TCP特权的进程(比如winlogon.exe或者任何用系统帐号启动的服务进程)。这是我做这张截图时用的方法。远程注入看起来很难做,其实网上有现成的库可用,比如CodeProject的这个。用这种方法有一点要注意的是在Windows XP SP2及以后的操作系统上,需要先打开Debug特权代码注入会失败。在XP SP2以前的版本中DEBUG特区是默认打开的,所以没有问题。
- 方法之五,上面的四种方法都是在管理员权限的基础上间接获得TCB特权。但是最方便的方法无疑应该是直接用代码获得TCB权限。我记得以前在网上看过别人介绍怎么做,可惜现在忘掉了,回头研究研究。
- 如何在系统登陆桌面运行程序
- 如何在系统登陆桌面运行程序(续)
- Delphi编写系统服务四:如何限制系统服务和桌面程序只运行一个
- Delphi编写系统服务四:如何限制系统服务和桌面程序只运行一个
- 在Windows桌面无缝运行Linux程序
- 如何保证同时只有一个程序在系统中运行
- 如何在android系统上运行C语言的程序
- 如何在Windows系统中设置Python程序定时运行
- linux可执行程序如何在系统后台运行
- 如何在Windows系统中设置Python程序定时运行
- 如何在Android系统锁屏后使程序继续运行
- 如何在Windows系统中设置Python程序定时运行
- 如何在LINUX中开机、登陆、退出、定时、定期自动运行程序
- Win7系统如何在桌面右键菜单里添加自定义程序或网址?
- android 判断是否在桌面,当前程序是否在运行
- 如何开机不桌面进入直接运行某一个程序
- 如何编译运行系统自带桌面Launcher2源码
- 如何编译运行Android系统自带桌面Launcher2源码
- ESB(企业服务总线)的是与非
- 程序员的素质之编程修养
- 基于SOA的企业信息化建设——ESB企业服务总线技术实现
- open source 开源之旅
- It is an error to use a section registered allowDefinition='MachineToApplication' beyond application lev
- 如何在系统登陆桌面运行程序
- AltiVec综述
- Ajax技术实现树菜单
- 80后的你,是这样么?
- ASP.NET的Request对象的属性介绍
- 学习C++primer心得08.5.25以前
- HelloRequest.java
- new说透 C#---.net 学习
- Request对象探讨