首页
社区
课程
招聘
[已解决] 怎么设置应用程序用system账号开机自启?
发表于: 2022-4-12 23:06 6594

[已解决] 怎么设置应用程序用system账号开机自启?

2022-4-12 23:06
6594

上周经过各位大佬指点用minifilter做R0和R3通信,经过几天摸索已经成功实现了,效果满意。

 

现在遇到一个新问题,R3的应用程序需要开机自启,同时还希望是高权限执行以便普通user不能关闭,确保监控进程持续运行。请问各位大佬这个要怎么实现呢?

 

网上查了很多资料,都说做一个LocalSystem账号运行的系统服务,在服务启动时CreateProcessAsUser启动system账号运行的R3程序,并且同时穿透session0实现服务和GUI图形界面应用程序交互。

 

但是网上这些资料都是拿Win7、Vista做的示例,经我过测试在Win10下并不生效。具体来说∶ 一台Win10 (2004)上有A、B两个账号,A是管理员,B是普通user。在A账号下安装localsystem服务C,设置自动启动,再启动R3程序,这样得到的确实是高权进程。

 

但是重启系统后,在登录界面(选择用户的界面,此时还没有登录任何账号),请问∶
1、这时服务C到底启动了没有?
2、如果服务C启动了,必然会启动R3的GUI图形界面程序,这个程序能正常显示出来吗?用哪个账号启动的?

 

然后再输入密码登录普通账号B,请问∶
3、登录后这时服务C还会再启动一次吗?如果会,服务C是以什么账号启动的?服务C启动的R3图形界面又是以什么账号登录的,system还是账号B?

 

经我测试,在Win10 2004下答案似乎是这样的∶
1、在登录界面服务C没有启动,图形界面R3弹窗也没有出现。
2、-
3、登录账号B后,服务C启动了,是用system账户启动的。R3程序也随着服务C启动了,但是却是以B账号权限启动的,所以用户B此时可以自行关闭结束R3程序,达到躲避监控的目的,不符合逾期。

 

虽然可以从驱动层面做进程保护,禁止用户结束R3的进程,但暂时不想这么做,还是想搞清楚Win10下怎么用system高权账户自启动某些图形界面R3程序(我看到有些软件确实做到这样了)?
自启动保护问题以及系统服务在登录前、登录后的状态、账号权限情况困惑我好久了,求大佬们指点一下!先拜谢了~


[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!

最后于 2022-4-17 12:49 被碧水秋沙编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 2132
活跃值: (1826)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
观注。
2022-4-13 08:23
0
雪    币: 1527
活跃值: (1890)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
nsudo 可以看下它git的代码,
其实还有其他更骚的操作
2022-4-13 10:39
0
雪    币: 3984
活跃值: (6126)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
4

可以用服务启动一个system级别的程序,正常服务运行在会话0下,要启动一个运行在会话1下的程序,可以这样
BOOL createcmd()
{
       HANDLE hPToken = NULL;
       HANDLE hUserTokenDup = NULL;
       PROCESS_INFORMATION pi;
       TOKEN_PRIVILEGES  tp;
       LUID  luid;
       BOOL bRet = FALSE;
       __try
       {
               if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
                       | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
                       | TOKEN_READ | TOKEN_WRITE, &hPToken))
                       __leave;
               if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hUserTokenDup))
               {
                       
                       __leave;
               }
               DWORD dwSessionId = 1; //会话1
               if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
               {
                       DWORD error = GetLastError();
                       __leave;
               }
               tp.PrivilegeCount = 1;
               tp.Privileges[0].Luid = luid;
               tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
               if (!AdjustTokenPrivileges(hUserTokenDup, FALSE, &tp, sizeof (TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, NULL))
               {
                       DWORD error = GetLastError();
                       __leave;
               }

               if (!SetTokenInformation(hUserTokenDup, TokenSessionId, (void *)&  dwSessionId, sizeof  (DWORD)))
               {
                       DWORD error = GetLastError();
                       __leave;
               }
               

               STARTUPINFO si;

               ZeroMemory(&si, sizeof(STARTUPINFO));
               ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
               si.cb = sizeof(STARTUPINFO);
               //si.dwXSize = 120;
               si.lpDesktop = L"WinSta0\\Default";
               si.dwFlags = STARTF_USESHOWWINDOW;
               si.wShowWindow = SW_SHOWNORMAL;
               LPVOID pEnv = NULL;
               TCHAR buffCmd[MAX_PATH] = { 0 };
               _tcscat_s(buffCmd, _countof(buffCmd) - 1, L"C:\\Windows\\System32\\CMD.exe");

               bRet = CreateProcessAsUser(hUserTokenDup, NULL, buffCmd, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);                

       }
       __finally
       {
               if (hPToken)
               {
                       CloseHandle(hPToken);
                       hPToken = NULL;
               }
               if (hUserTokenDup)
               {
                       CloseHandle(hUserTokenDup);
                       hUserTokenDup = NULL;
               }
               if (pi.hProcess)
               {
                       CloseHandle(pi.hProcess);
                       pi.hProcess = NULL;
               }
               if (pi.hThread)
               {
                       CloseHandle(pi.hThread);
                       pi.hThread = NULL;
               }
       }
       return bRet;
}

服务运行在会话0下,登录的第一个用户运行在会话1,第二个用户运行在会话2下,以此类推,这段代码运行在system服务中,即可启动一个会话1的cmd,在winlogn界面就会启动了,但是要登录进去才能看到

最后于 2022-4-13 11:28 被0346954编辑 ,原因:
2022-4-13 11:17
0
雪    币: 92
活跃值: (467)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5

谢大佬回帖,一会儿去试试这段代码。
不过对“ DWORD dwSessionId = 1; //会话1” 这行有点疑问:
1、既然cmd在winlogon界面就启动了,这时还没有用户登录,哪来的session1、session2这些sessionid呢?还是说这些sessionid是windows预置的,在用户登录前就已经存在,用户不登录就已经有了,等到用户登录后再按顺序分配?
2、如果要做到这台机器上每个用户登录时都用system启动这个cmd(预先不知道有多少个用户、是同时登录还是按顺序注销完一个再登录另一个),这样的话sessionid又要怎么写呢?

最后于 2022-4-13 12:40 被碧水秋沙编辑 ,原因:
2022-4-13 12:39
0
雪    币: 3984
活跃值: (6126)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
6
碧水秋沙 谢大佬回帖,一会儿去试试这段代码。不过对“ DWORD dwSessionId = 1; //会话1”& ...

也可以用 WTSGetActiveConsoleSessionId获取当前活跃的sessionid 第一个问题,其实已经有了session 1了,在用户登录界面,你可以在登录后,用processexplorer查看

在登录界面,登录进程winlogon.exe就是session1,如果登录成功后,切换用户,第二个winlogon就是session 2

第二个问题:如果不知道有多少个用户,其实每个用户登录后都有至少一个explorer.exe进程,遍历进程获取每个进程的sessionid,已经创建过的就不再创建了,所以可以用服务程序遍历explorer.exe或者winlogon.exe,获取sessionid,判断是否已经启动过了监控程序,然后用上面的代码动态传递sessionid,启动监控程序。

2022-4-13 13:27
0
雪    币: 92
活跃值: (467)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
0346954 也可以用 WTSGetActiveConsoleSessionId获取当前活跃的sessionid 第一个问题,其实已经有了session 1了,在用户登录界面,你可以在登录后,用processex ...
太6了~多谢大佬解答,似乎明白怎么回事了,晚上回去就试试,有问题再来请教 不愧“大侠”称号,救万民于水火,解百姓于倒悬,事了拂衣去,深藏功与名
2022-4-13 14:14
0
雪    币: 92
活跃值: (467)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
已经搞清楚原理并成功实现,再次感谢看雪的各位大侠们路见不平拔刀相助~~
2022-4-15 10:08
0
游客
登录 | 注册 方可回帖
返回