zoukankan      html  css  js  c++  java
  • 系统权限服务创建桌面进程(进程也是系统权限)

    系统权限服务,创建进程.

    一丶简介

    为什么要创建系统权限服务.首先.强调权限一说. 我们创建的系统服务默认是系统权限的.然后系统权限(System)创建我们的进程.那么也是系统权限.我们的进程如果要注入到Explorer.exe中就很简单了.

    二丶创建服务的几个步骤

    1.编写服务步骤

    1.main函数中注册服务的入口函数(servicemain)并开始派发
    2.服务入口函数注册服务控制函数.并且设置自己的服务状态
    3.服务控制函数回调的处理

    1.1 main函数注册服务入口函数

    int main()
    {
    	/*
    
    	定义服务列表结构体
    	参数1.指定的服务名字.
    	参数2.服务的入口Main函数地址.
    	*/
    	////安装服务.
    	
    	    SERVICE_TABLE_ENTRY ServiceTable[2] = { NULL };
    		ServiceTable[0].lpServiceName = (LPWSTR)TEXT(SERVICE_NAME); //指定我们的服务名字
    		ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)SerMain;//指向服务的函数地址
    		//LPSERVICE_MAIN_FUNCTIONW
    
    		ServiceTable[1].lpServiceName = NULL;
    		ServiceTable[1].lpServiceProc = NULL;
    		StartServiceCtrlDispatcher(ServiceTable); //开始派发.
    	
    	return 0;
    }
    

    2.服务入口函数注册服务控制函数.

    服务入口服务控制回调函数,注册到SCM(服务控制管理器)当中.
    当我们服务控制管理器中点击 启动服务.关闭服务.暂停服务的时候.则会调用我们的回调函数.
    代码如下

    VOID WINAPI SerMain(DWORD   dwNumServicesArgs,LPWSTR* lpServiceArgVectors)
    {
    	//在服务Main里面.我们需要注册服务.
    	/*
    	RegisterServiceCtrlHandler 
    	注册一个函数来处理服务的请求控制.
    	*/
    
    	g_ServiceStatus.dwServiceType = SERVICE_WIN32;    //服务的类型是Win32服务
    	g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; ; //服务的状态是正在巡行
    	g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP ;// 服务接手的控制代码喊处理函数中的处理. (Reg注册的函数地址); 当前的意思就是这个服务可以停止.并且会传入Reg注册的ServiceHandle处理.
    	g_ServiceStatus.dwWin32ExitCode = 0;  //服务用语报告启动或停止时候发生的错误代码.返回特定的错误代码就设置.
    	g_ServiceStatus.dwServiceSpecificExitCode = 0;//服务特定的错误代码
    	g_ServiceStatus.dwCheckPoint = 0;             //跟进度条一样,服务在启动的时候会递增这个值
    	g_ServiceStatus.dwWaitHint = 0;               //挂起启动,停止,暂停.或继续操作所需要的估计时间. 
    
    	BOOL bRet = FALSE;
    	g_RegRetServiceStatusHandle = RegisterServiceCtrlHandlerEx(TEXT(SERVICE_NAME), ServiceHandle,NULL);//返回服务状态. 注册服务控制函数
    	if (g_RegRetServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
    	{
    		return;
    	}
    	//否则,调用SetServiceStatus进行更新服务的状态信息 结构体是最新服务状态结构信息.
    	
    	g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; //Service Status Setting Start.
    	 bRet = SetServiceStatus(g_RegRetServiceStatusHandle,&g_ServiceStatus);//设置服务的状态.
    
    	if (!bRet)
    	{
    		return ;
    	}
    	//编写自己的代码.
    	g_ContrlCodeExcue = TRUE;
    	
    	
    	
    	RunRemoteControl();
    	
    	
    	while (g_ContrlCodeExcue)
    	{
    		Sleep(2000);
    	}
    	return;
    }
    

    3.服务控制函数回调的处理

    
    DWORD WINAPI ServiceHandle(DWORD    dwControl, DWORD    dwEventType, LPVOID   lpEventData, LPVOID   lpContext)
    {
    	//服务的控制状态.管理
    	switch (dwControl)
    	{
    		//回调函数会传入dwControl让我们控制服务.我们只需要控制即可.更改状态并且设置即可.
    	case SERVICE_CONTROL_PAUSE:
    		//暂停
    		g_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
    		break;
    	case SERVICE_CONTROL_CONTINUE:
    		g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    
    		break;
    	case SERVICE_CONTROL_STOP:
    		g_ServiceStatus.dwWin32ExitCode = 0;
    		g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    		g_ServiceStatus.dwCheckPoint = 0;
    		g_ServiceStatus.dwWaitHint = 0;
    		//SetServiceStatus(g_RegRetServiceStatusHandle, &g_ServiceStatus);
    		g_ContrlCodeExcue = FALSE;
    		break;
    	case SERVICE_CONTROL_INTERROGATE:
    		break;
    	default:
    		break;
    	}
    	SetServiceStatus(g_RegRetServiceStatusHandle, &g_ServiceStatus);
    	return 0;
    }
    
    

    编写完上面的几步,我们的一个系统服务就能创建出来了.

    4.服务控制的完整代码

    
    #pragma warning (disable:4996)
    #include <userenv.h>
    #include <Windows.h>
    #include <stdio.h>
    #include <tlhelp32.h>
    #include <string>
    #include <vector>
    using namespace std;
    
    #pragma comment(lib,"Userenv.lib")
    SERVICE_STATUS_HANDLE g_RegRetServiceStatusHandle;
    SERVICE_STATUS        g_ServiceStatus; //服务的状态
    BOOL g_ContrlCodeExcue;   //控制我们的代码是否执行
    
    
    DWORD WINAPI ServiceHandle(DWORD    dwControl, DWORD    dwEventType, LPVOID   lpEventData, LPVOID   lpContext)
    {
    	//服务的控制状态.管理
    	switch (dwControl)
    	{
    		//回调函数会传入dwControl让我们控制服务.我们只需要控制即可.更改状态并且设置即可.
    	case SERVICE_CONTROL_PAUSE:
    		//暂停
    		g_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
    		break;
    	case SERVICE_CONTROL_CONTINUE:
    		g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    
    		break;
    	case SERVICE_CONTROL_STOP:
    		g_ServiceStatus.dwWin32ExitCode = 0;
    		g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    		g_ServiceStatus.dwCheckPoint = 0;
    		g_ServiceStatus.dwWaitHint = 0;
    		//SetServiceStatus(g_RegRetServiceStatusHandle, &g_ServiceStatus);
    		g_ContrlCodeExcue = FALSE;
    		break;
    	case SERVICE_CONTROL_INTERROGATE:
    		break;
    	default:
    		break;
    	}
    	SetServiceStatus(g_RegRetServiceStatusHandle, &g_ServiceStatus);
    	return 0;
    }
    
    
    
    
    
    VOID WINAPI SerMain(DWORD   dwNumServicesArgs,LPWSTR* lpServiceArgVectors)
    {
    	//在服务Main里面.我们需要注册服务.
    	/*
    	RegisterServiceCtrlHandler 
    	注册一个函数来处理服务的请求控制.
    	*/
    
    	g_ServiceStatus.dwServiceType = SERVICE_WIN32;    //服务的类型是Win32服务
    	g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; ; //服务的状态是正在巡行
    	g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP ;// 服务接手的控制代码喊处理函数中的处理. (Reg注册的函数地址); 当前的意思就是这个服务可以停止.并且会传入Reg注册的ServiceHandle处理.
    	g_ServiceStatus.dwWin32ExitCode = 0;  //服务用语报告启动或停止时候发生的错误代码.返回特定的错误代码就设置.
    	g_ServiceStatus.dwServiceSpecificExitCode = 0;//服务特定的错误代码
    	g_ServiceStatus.dwCheckPoint = 0;             //跟进度条一样,服务在启动的时候会递增这个值
    	g_ServiceStatus.dwWaitHint = 0;               //挂起启动,停止,暂停.或继续操作所需要的估计时间. 
    
    	BOOL bRet = FALSE;
    	g_RegRetServiceStatusHandle = RegisterServiceCtrlHandlerEx(TEXT(SERVICE_NAME), ServiceHandle,NULL);//返回服务状态.
    	if (g_RegRetServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
    	{
    		return;
    	}
    	//否则,调用SetServiceStatus进行更新服务的状态信息 结构体是最新服务状态结构信息.
    	
    	g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; //Service Status Setting Start.
    	 bRet = SetServiceStatus(g_RegRetServiceStatusHandle,&g_ServiceStatus);
    
    	if (!bRet)
    	{
    		return ;
    	}
    	//编写自己的代码.
    	g_ContrlCodeExcue = TRUE;
    	
    	
    	
    	
    	
    	
    	while (g_ContrlCodeExcue)
    	{
    		Sleep(2000); //写你自己的代码
    	}
    	return;
    }
    
    int main()
    {
    	/*
    
    	定义服务列表结构体
    	参数1.指定的服务名字.
    	参数2.服务的入后Main函数地址.
    	*/
    	////安装服务.
    
    	//SERVICE_TABLE_ENTRY ServiceTable[2] = { NULL };
    	//ServiceTable[0].lpServiceName = (LPWSTR)TEXT(SERVICE_NAME); //指定我们的服务名字
    	//ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)SerMain;//指向服务的函数地址
    	////LPSERVICE_MAIN_FUNCTIONW
    
    	//ServiceTable[1].lpServiceName = NULL;
    	//ServiceTable[1].lpServiceProc = NULL;
    	//StartServiceCtrlDispatcher(ServiceTable); //开始派发.
    
    	
    		 SERVICE_TABLE_ENTRY ServiceTable[2] = { NULL };
    		ServiceTable[0].lpServiceName = (LPWSTR)TEXT(SERVICE_NAME); //指定我们的服务名字
    		ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)SerMain;//指向服务的函数地址
    		//LPSERVICE_MAIN_FUNCTIONW
    
    		ServiceTable[1].lpServiceName = NULL;
    		ServiceTable[1].lpServiceProc = NULL;
    		StartServiceCtrlDispatcher(ServiceTable); //开始派发.
    	
    
    	return 0;
    }
    
    

    三丶服务中创建桌面进程

    3.1服务中创建桌面进程原理

    在服务中虽然说创建的进程是System权限.但是在win7系统以上,我们创建的进程都会是隐藏的.也就是说你的进程虽然创建出来了.
    也是Sysem权限.但是并不能操作.仅仅就只能在管理器看到这个进程而已.
    ps:(winxp下没有尝试是否能创建进程)
    所以我们有了新的方法.不调用CreateProcess函数.而调用 CreateProcessAsUser函数.
    并且进行一定的设置才可以.

    核心代码如下:

    void RunRemoteControl() //在服务中创建桌面进程.
    {
    	HANDLE ProcessHandle = NULL;
    	HANDLE CurrentToken = NULL;
    	HANDLE TokenDup = NULL;
    	wstring wOpenProcessName;
    	if (!GetAppendNmae(wOpenProcessName, PROCESS_NAME))
    	{
    		int d = GetLastError();
    		WriteLogString(L"RunRemoteControl OpenProcessToken failed.Last Error is:%d", d);
    		return ;
    	}
    	ProcessHandle = GetCurrentProcess();
    	if (!OpenProcessToken(ProcessHandle, TOKEN_ALL_ACCESS, &CurrentToken))
    	{
    		int d = GetLastError();
    		WriteLogString(L"RunRemoteControl OpenProcessToken failed.Last Error is:%d", d);
    		return;
    	}
    	if (!DuplicateTokenEx(CurrentToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &TokenDup))
    	{
    		int dd = GetLastError();
    		WriteLogString(L"RunRemoteControl DuplicateTokenEx failed.Last error is:%d", dd);
    		return;
    	}
    	DWORD dwSessionID = WTSGetActiveConsoleSessionId();
    	WriteLogString(L" WTSGetActiveConsoleSessionId:%d", dwSessionID);
    	if (!SetTokenInformation(TokenDup, TokenSessionId, &dwSessionID, sizeof(DWORD)))
    	{
    		int ddd = GetLastError();
    		WriteLogString(L"RunRemoteControl SetTokenInformation failed.Last error is:%d", ddd);
    		return;
    	}
    	STARTUPINFO si;
    	PROCESS_INFORMATION pi;
    	ZeroMemory(&si, sizeof(STARTUPINFO));
    	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    	si.cb = sizeof(STARTUPINFO);
    	si.lpDesktop = L"WinSta0\Default";
    
    	LPVOID pEnv = NULL;
    	DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
    	if (!CreateEnvironmentBlock(&pEnv, TokenDup, FALSE))
    	{
    		int error1 = GetLastError();
    		WriteLogString(L"RunRemoteControl CreateEnvironmentBlock failed.Last error is:%d", error1);
    		return;
    	}
    	TCHAR szPath[1024] =  TEXT_CREATE_PROCESS_NAME_SY;
    	//wcsncpy_s(szPath, wOpenProcessName.c_str(), wOpenProcessName.length());
    	OutputDebugString(szPath);
    	if (!CreateProcessAsUser(TokenDup, szPath, NULL, NULL, NULL, FALSE, dwCreationFlags, pEnv, NULL, &si, &pi))
    	{
    		int error2 = GetLastError();
    		WriteLogString(L"RunRemoteControl CreateProcessAsUser failed.Last error is:%d", error2);
    		return;
    	}
    
    	return	;
    }
    
    

    其中函数 GetAppendNmae WriteLogString 函数是我自己写的.不影响这个核心函数.可以去掉的.
    最后就可以创建我们的进程.

    3.2服务中创建桌面进程完整代码

    完整代码如下:

    
    
    
    
    #pragma warning (disable:4996)
    #include <userenv.h>
    #include <Windows.h>
    #include <stdio.h>
    #include <tlhelp32.h>
    #include <string>
    #include <vector>
    using namespace std;
    
    #pragma comment(lib,"Userenv.lib")
    SERVICE_STATUS_HANDLE g_RegRetServiceStatusHandle;
    SERVICE_STATUS        g_ServiceStatus; //服务的状态
    BOOL g_ContrlCodeExcue;   //控制我们的代码是否执行
    #define SERVICE_NAME "SystemServices"
    #define LOAG_FILE_NAME "SystemServicesLog.txt"
    #define TEXT_CREATE_PROCESS_NAME_OD TEXT("D:\HackTools\OllyDbg\OllyICE 吾爱扣扣专版\OllyICE 吾爱扣扣专版\OllyICE.exe")//SystemRun.exe
    #define TEXT_CREATE_PROCESS_NAME_SY TEXT("C:\Users\Administrator\Desktop\SystemServices\run\x64InjectProcess.exe")
    #define PROCESS_NAME TEXT("SystemRun.exe")
    
    BOOL GetAppendNmae(wstring &wGetName, wstring AppendName); //Get Moudle Name Last - 1 Path Cat In Path
    //服务控制函数
    
    DWORD WINAPI ServiceHandle(DWORD    dwControl, DWORD    dwEventType, LPVOID   lpEventData, LPVOID   lpContext)
    {
    	//服务的控制状态.管理
    	switch (dwControl)
    	{
    		//回调函数会传入dwControl让我们控制服务.我们只需要控制即可.更改状态并且设置即可.
    	case SERVICE_CONTROL_PAUSE:
    		//暂停
    		g_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
    		break;
    	case SERVICE_CONTROL_CONTINUE:
    		g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    
    		break;
    	case SERVICE_CONTROL_STOP:
    		g_ServiceStatus.dwWin32ExitCode = 0;
    		g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    		g_ServiceStatus.dwCheckPoint = 0;
    		g_ServiceStatus.dwWaitHint = 0;
    		//SetServiceStatus(g_RegRetServiceStatusHandle, &g_ServiceStatus);
    		g_ContrlCodeExcue = FALSE;
    		break;
    	case SERVICE_CONTROL_INTERROGATE:
    		break;
    	default:
    		break;
    	}
    	SetServiceStatus(g_RegRetServiceStatusHandle, &g_ServiceStatus);
    	return 0;
    }
    
    BOOL GetEachLevelDir(PWSTR GetPathName, vector<wstring> &wSavePath) //传入一个路径,获取每一级的目录.并且用数组进行存储.
    {
    	TCHAR *pCurPoint = GetPathName;//使用指针遍历
    
    	TCHAR  *Begin = GetPathName;
    	DWORD dwEnd = 0;
    	DWORD dwCount = 0;
    	wstring wstrTemp = TEXT("");
    	while (pCurPoint)
    	{
    
    		//否则进行循环
    		//wcscmp((TCHAR *)*pCurPoint,TEXT("\")) == 0
    		if (*pCurPoint == TEXT('\'))//以反斜杠为分割.
    		{
    
    			wSavePath.push_back(wstrTemp);
    			wstrTemp.clear();
    			pCurPoint++; //控制指针去相加.
    			dwEnd = 0;
    
    		}
    
    		if (*pCurPoint == 0x0)//结尾是0则跳出循环.记录下路径.
    		{
    			return TRUE;
    			break;
    		}
    		wstring::iterator it = wstrTemp.begin() + dwEnd;
    		wstrTemp.insert(it, *pCurPoint);  //插入字符
    		dwEnd++;
    		pCurPoint++;
    		dwCount++; //获取判断长度进行退出.
    	}
    	return FALSE;
    }
    
    BOOL   GetTokenByName(HANDLE   &hToken, LPWSTR   lpName)
    {
    	if (!lpName)
    	{
    		return   FALSE;
    	}
    	HANDLE                   hProcessSnap = NULL;
    	BOOL                       bRet = FALSE;
    	PROCESSENTRY32   pe32 = { 0 };
    
    	hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    	if (hProcessSnap == INVALID_HANDLE_VALUE)
    		return   (FALSE);
    
    	pe32.dwSize = sizeof(PROCESSENTRY32);
    
    	if (Process32First(hProcessSnap, &pe32))
    	{
    		do
    		{
    			if (!wcscmp(_wcsupr(pe32.szExeFile), _wcsupr(lpName)))
    			{
    				HANDLE   hProcess =
    					OpenProcess(PROCESS_QUERY_INFORMATION,
    					FALSE, pe32.th32ProcessID);
    				bRet = OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken);
    				CloseHandle(hProcessSnap);
    				return   (bRet);
    			}
    		} while (Process32Next(hProcessSnap, &pe32));
    		bRet = TRUE;
    	}
    	else
    		bRet = FALSE;
    
    	CloseHandle(hProcessSnap);
    	return   (bRet);
    }
    
    //也可以创建进程,但是创建出来的是根据你得当前EXPLORER的权限创建的。 创建出来是管理员权限。
    BOOL   RunProcess(LPWSTR   lpImage)
    {
    	if (!lpImage)
    	{
    		return   FALSE;
    	}
    	HANDLE   hToken;
    	//TEXT("EXPLORER.EXE")
    	if (!GetTokenByName(hToken, TEXT("EXPLORER.EXE")))
    	{
    		return   FALSE;
    	}
    	STARTUPINFO   si;
    	PROCESS_INFORMATION   pi;
    
    	ZeroMemory(&si, sizeof(STARTUPINFO));
    	si.cb = sizeof(STARTUPINFO);
    	si.lpDesktop = TEXT("winsta0\default");
    
    	BOOL   bResult =
    		CreateProcessAsUser(hToken, lpImage, NULL, NULL, NULL,
    		FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
    	CloseHandle(hToken);
    	if (bResult)
    	{
    		OutputDebugString(TEXT("CreateProcessAsUser   ok!
    "));
    	}
    	else
    	{
    		OutputDebugString(TEXT("CreateProcessAsUser   false!
    "));
    	}
    	return   bResult;
    } 
    
    BOOL GetAppendNmae(wstring &wGetName, wstring AppendName)//获取启动进程的启动的名字
    {
    
    	TCHAR FilePath[MAX_PATH] = { 0 };
    	GetModuleFileName(GetModuleHandle(0), FilePath, MAX_PATH);
    	vector<wstring> wSaveDirLeavePath;
    	if (!GetEachLevelDir(FilePath, wSaveDirLeavePath))
    	{
    		return FALSE;
    	}
    	//cat 
    	wstring wCatPath = TEXT("");
    	for (int i = 0; i < wSaveDirLeavePath.size(); i++)
    	{
    		if (i == (wSaveDirLeavePath.size() - 1))
    		{
    			break;
    		}
    		wCatPath.append(wSaveDirLeavePath[i]);
    		wCatPath.append(TEXT("\"));
    	}
    	wCatPath.append(AppendName);
    	wGetName = wCatPath;
    
    	return TRUE;
    }
    
    void WriteLogString(LPWSTR lpParam, DWORD dwCode)
    {
    	TCHAR lpBuffer[1024]  {0};
    	wsprintf(lpBuffer,lpParam, dwCode);
    	OutputDebugString(lpBuffer);
    	//GetCurrentDirectory(1024, lpBuffer);
    	wstring WriteLogName;
    	if (!GetAppendNmae(WriteLogName, TEXT(LOAG_FILE_NAME)))
    	{
    		return;
    	}
    	FILE *pFile = NULL;
    	_wfopen_s(&pFile, WriteLogName.c_str(), TEXT("a+"));
    	if (NULL == pFile)
    	{
    		return;
    	}
    	fwprintf_s(pFile, lpParam); //写入到文件
    	fclose(pFile);
    	return;
    }
    
    void RunRemoteControl() //在服务中创建桌面进程.
    {
    	HANDLE ProcessHandle = NULL;
    	HANDLE CurrentToken = NULL;
    	HANDLE TokenDup = NULL;
    	wstring wOpenProcessName;
    	if (!GetAppendNmae(wOpenProcessName, PROCESS_NAME))
    	{
    		int d = GetLastError();
    		WriteLogString(L"RunRemoteControl OpenProcessToken failed.Last Error is:%d", d);
    		return ;
    	}
    	ProcessHandle = GetCurrentProcess();
    	if (!OpenProcessToken(ProcessHandle, TOKEN_ALL_ACCESS, &CurrentToken))
    	{
    		int d = GetLastError();
    		WriteLogString(L"RunRemoteControl OpenProcessToken failed.Last Error is:%d", d);
    		return;
    	}
    	if (!DuplicateTokenEx(CurrentToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &TokenDup))
    	{
    		int dd = GetLastError();
    		WriteLogString(L"RunRemoteControl DuplicateTokenEx failed.Last error is:%d", dd);
    		return;
    	}
    	DWORD dwSessionID = WTSGetActiveConsoleSessionId();
    	WriteLogString(L" WTSGetActiveConsoleSessionId:%d", dwSessionID);
    	if (!SetTokenInformation(TokenDup, TokenSessionId, &dwSessionID, sizeof(DWORD)))
    	{
    		int ddd = GetLastError();
    		WriteLogString(L"RunRemoteControl SetTokenInformation failed.Last error is:%d", ddd);
    		return;
    	}
    	STARTUPINFO si;
    	PROCESS_INFORMATION pi;
    	ZeroMemory(&si, sizeof(STARTUPINFO));
    	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    	si.cb = sizeof(STARTUPINFO);
    	si.lpDesktop = L"WinSta0\Default";
    
    	LPVOID pEnv = NULL;
    	DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
    	if (!CreateEnvironmentBlock(&pEnv, TokenDup, FALSE))
    	{
    		int error1 = GetLastError();
    		WriteLogString(L"RunRemoteControl CreateEnvironmentBlock failed.Last error is:%d", error1);
    		return;
    	}
    	TCHAR szPath[1024] =  TEXT_CREATE_PROCESS_NAME_SY;
    	//wcsncpy_s(szPath, wOpenProcessName.c_str(), wOpenProcessName.length());
    	OutputDebugString(szPath);
    	if (!CreateProcessAsUser(TokenDup, szPath, NULL, NULL, NULL, FALSE, dwCreationFlags, pEnv, NULL, &si, &pi))
    	{
    		int error2 = GetLastError();
    		WriteLogString(L"RunRemoteControl CreateProcessAsUser failed.Last error is:%d", error2);
    		return;
    	}
    
    	return	;
    }
    
    VOID WINAPI SerMain(DWORD   dwNumServicesArgs,LPWSTR* lpServiceArgVectors)
    {
    	//在服务Main里面.我们需要注册服务.
    	/*
    	RegisterServiceCtrlHandler 
    	注册一个函数来处理服务的请求控制.
    	*/
    
    	g_ServiceStatus.dwServiceType = SERVICE_WIN32;    //服务的类型是Win32服务
    	g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; ; //服务的状态是正在巡行
    	g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP ;// 服务接手的控制代码喊处理函数中的处理. (Reg注册的函数地址); 当前的意思就是这个服务可以停止.并且会传入Reg注册的ServiceHandle处理.
    	g_ServiceStatus.dwWin32ExitCode = 0;  //服务用语报告启动或停止时候发生的错误代码.返回特定的错误代码就设置.
    	g_ServiceStatus.dwServiceSpecificExitCode = 0;//服务特定的错误代码
    	g_ServiceStatus.dwCheckPoint = 0;             //跟进度条一样,服务在启动的时候会递增这个值
    	g_ServiceStatus.dwWaitHint = 0;               //挂起启动,停止,暂停.或继续操作所需要的估计时间. 
    
    	BOOL bRet = FALSE;
    	g_RegRetServiceStatusHandle = RegisterServiceCtrlHandlerEx(TEXT(SERVICE_NAME), ServiceHandle,NULL);//返回服务状态.
    	if (g_RegRetServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
    	{
    		return;
    	}
    	//否则,调用SetServiceStatus进行更新服务的状态信息 结构体是最新服务状态结构信息.
    	
    	g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; //Service Status Setting Start.
    	 bRet = SetServiceStatus(g_RegRetServiceStatusHandle,&g_ServiceStatus);
    
    	if (!bRet)
    	{
    		return ;
    	}
    	//编写自己的代码.
    	g_ContrlCodeExcue = TRUE;
    	
    	
    	
    	RunRemoteControl();
    	
    	
    	while (g_ContrlCodeExcue)
    	{
    		Sleep(2000);
    	}
    	return;
    }
    
    int main()
    {
    	/*
    
    	定义服务列表结构体
    	参数1.指定的服务名字.
    	参数2.服务的入后Main函数地址.
    	*/
    	////安装服务.
    
    	//SERVICE_TABLE_ENTRY ServiceTable[2] = { NULL };
    	//ServiceTable[0].lpServiceName = (LPWSTR)TEXT(SERVICE_NAME); //指定我们的服务名字
    	//ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)SerMain;//指向服务的函数地址
    	////LPSERVICE_MAIN_FUNCTIONW
    
    	//ServiceTable[1].lpServiceName = NULL;
    	//ServiceTable[1].lpServiceProc = NULL;
    	//StartServiceCtrlDispatcher(ServiceTable); //开始派发.
    
    	
    		 SERVICE_TABLE_ENTRY ServiceTable[2] = { NULL };
    		ServiceTable[0].lpServiceName = (LPWSTR)TEXT(SERVICE_NAME); //指定我们的服务名字
    		ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)SerMain;//指向服务的函数地址
    		//LPSERVICE_MAIN_FUNCTIONW
    
    		ServiceTable[1].lpServiceName = NULL;
    		ServiceTable[1].lpServiceProc = NULL;
    		StartServiceCtrlDispatcher(ServiceTable); //开始派发.
    	
    
    	return 0;
    }
    
    
    
    

    4.总结

    代码没有进行完善,比如服务中创建的进程是写死的.这个我没有做.因为时间有限.只为了测试代码.
    其实不难.有兴趣的可以自己做一下.
    最后附上完整代码:

    链接:https://pan.baidu.com/s/1Yn0zHfHi9ZBfiNKkCNdMpA ")
    提取码:iius

  • 相关阅读:
    leetcode 10 正则表达式匹配(c++)
    基于.NetCore3.1系列 —— 日志记录之初识Serilog
    AspNetCore WebApi:Serilog(日志)
    .NET Core下的日志(3):如何将日志消息输出到控制台上
    Asp.Net Core用NLog记录日志操作方法
    .NET Core3.0 日志 logging-最好用的日志集合介绍
    .net core 3.1 使用nlog记录日志 NLog.Web.AspNetCore
    NetCore3.1 日志组件 Nlog的使用
    配置 ASP.NET Core 请求(Request)处理管道
    vue进入页面每次都调用methods里的方法
  • 原文地址:https://www.cnblogs.com/iBinary/p/10801835.html
Copyright © 2011-2022 走看看