首页
论坛
课程
招聘
[旧帖] [原创]Run cmd.exe as Local System 0.00雪花
2010-5-30 10:46 2588

[旧帖] [原创]Run cmd.exe as Local System 0.00雪花

2010-5-30 10:46
2588
由于已经申请看雪的号很久了,发现自己还是临时会员,最近又在学习内核编程,遇到了一些问题想跟高手请教一下,却不能在其他版块发帖,于是想写这篇文章来申请一下邀请码。
前段时间看了一篇文章《Running CMD.EXE as Local System》,引自msdn的博客http://blogs.msdn.com/b/adioltean/archive/2004/11/27/271063.aspx,我自己实现了一下发现在xp下启动服务失败却还能使cmd.exe以system身份运行,但是在之后的操作系统上不行,于是我通过学习《深入解析windows操作系统》中的第四章的服务章节,自己再写了个程序发现在xp下可以启动服务成功,并能使cmd.exe以system身份运行,在win7上也能运行成功。
下面是程序的思路:
1.首先是编写服务程序:
(1)任何一个应用程序都需要一个入口函数,一个服务程序必须具有服务主函数,服务主函数是服务启动时执行的入口,也是服务的主线程执行起点。服务主函数一般称作ServiceMain函数。但是服务主函数的名称与线程函数ThreadProc一样,其函数名并没有特殊要求,只是其参数接口和调用类型必须与要求一致。服务主函数的参数不是通过在命令行启动时设定的,而是通过SCM(服务控制管理器)的相关API StartService进行传递的。
(2)SCM要对服务进行管理,就必须知道服务程序的服务主函数。服务程序通过调用StartServiceCtrlDispatcher函数设置服务主函数,同时通知SCM。StartServiceCtrlDispatcherh函数原型如下:
BOOL StartServiceCtrlDispatcher(const LPSERVICE_TABLE_ENTRY lpServicTable);
结构SERVICE_TABLE_ENTRY的原型如下:
typedef struct _SERVICE_TABLE_ENTRY{
    LPTSTR lpServiceName; //服务名称
    LPSERVICE_MAIN_FUNCTION lpServiceProc; //指向ServiceMain的函数指针
}SERVICE_TABLE_ENTRY,*LPSERVICE_TABLE_ENTRY;
只有将函数的指针赋给lpServiceProc,再调用StartServiceCtrlDispatcher,这个函数就成为了服务主函数。
(3)控制处理函数:
1)控制处理函数Handler,控制处理函数用于处理SCM向服务传递的服务控制请求。控制处理
  函数原型如下:VOID WINAPI Handler(DWORD fdwControl);与ServiceMain函数
  一致,其函数名没有特殊要求
2)注册控制管理函数:RegisterServiceCtrlHandler函数用于向SCM设置一个服务的控制处理
  函数SERVICE_STATUS_HANDLE RegisterServiceCtrlHandler(
     LPCTSTR lpServiceName; //服务名称
        LPHANDLER_FUNCTION lpHandlerProc //为Handler函数指针);
(4)下面是一个服务程序的流程:
  先填充SERVICE_STATUS结构,然后注册服务控制请求处理历程,代码如下:
/*************************************
* VOID WINAPI SplSrvServiceStart (DWORD argc, LPTSTR *argv)
* 功能	服务启动函数
*
* 参数	未使用
**************************************/
VOID WINAPI SplSrvServiceStart (DWORD argc, LPTSTR *argv) 
{ 
	DWORD status; 
	DWORD specificError; 
	HANDLE hThread;
	// 填充SERVICE_STATUS 结构
	SplSrvServiceStatus.dwServiceType        = SERVICE_WIN32|[COLOR="Red"]SERVICE_INTERACTIVE_PROCESS[/COLOR];
	SplSrvServiceStatus.dwCurrentState       
		= SERVICE_START_PENDING;		// 服务在运行
	SplSrvServiceStatus.dwControlsAccepted   
		= SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; 
	SplSrvServiceStatus.dwWin32ExitCode      = 0; 
	SplSrvServiceStatus.dwServiceSpecificExitCode = 0; 
	SplSrvServiceStatus.dwCheckPoint         = 0; 
	SplSrvServiceStatus.dwWaitHint           = 0; 
	// 注册服务控制请求处理例程
	SplSrvServiceStatusHandle = RegisterServiceCtrlHandler( 
		"Sample_Srv",	// 服务名,在创建服务时使用了
		// SERVICE_WIN32_OWN_PROCESS,因此本参数被忽略。
		SplSrvServiceCtrlHandler);	// 控制请求处理例程,函数名

	if (SplSrvServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) 
	{ 
		SvcDebugOut(" [SPLSRV_SERVICE] RegisterServiceCtrlHandler "
			"failed %d\n", GetLastError()); 
		return; 
	}  
	// 初始化工作,本示例未使用,函数为空
	//status = SplSrvServiceInitialization(argc,argv, &specificError);  
	// 初始化出错,用户自行修改
	/*if (status != NO_ERROR) 
	{ 
		SplSrvServiceStatus.dwCurrentState       = SERVICE_STOPPED; 
		SplSrvServiceStatus.dwCheckPoint         = 0; 
		SplSrvServiceStatus.dwWaitHint           = 0; 
		SplSrvServiceStatus.dwWin32ExitCode      = status; 
		SplSrvServiceStatus.dwServiceSpecificExitCode = specificError; 

		SetServiceStatus (SplSrvServiceStatusHandle, &SplSrvServiceStatus); 
		return; 
	} */
	// 初始化完成,设置运行状态
	SplSrvServiceStatus.dwCurrentState       = SERVICE_RUNNING; 
	SplSrvServiceStatus.dwCheckPoint         = 0; 
	SplSrvServiceStatus.dwWaitHint           = 0; 

	if (!SetServiceStatus (SplSrvServiceStatusHandle, &SplSrvServiceStatus)) 
	{ 
		status = GetLastError(); 
		SvcDebugOut(" [SPLSRV_SERVICE] SetServiceStatus error %ld\n",status); 
	} 
	// 用户自行修改,用于完成服务的工作
	hThread=CreateThread(NULL,0,CmdService,NULL,0,NULL);
	SvcDebugOut(" [SPLSRV_SERVICE] Returning the Main Thread \n",0); 

	return; 
} 

线程函数如下:
DWORD WINAPI CmdService(LPVOID lpParam)
{
        ShellExecute(0,0,TEXT("cmd.exe"),0,0,SW_SHOW);
        return(0);
}
下面是入口主函数:
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{ 
	// 设置SERVICE_TABLE_ENTRY 数据结构,以NULL 结构结束,
	// 作为StartServiceCtrlDispatcher 函数的参数。
	SERVICE_TABLE_ENTRY   DispatchTable[] = 
	{ 
		{ "Sample_Srv", (LPSERVICE_MAIN_FUNCTION) SplSrvServiceStart }, 
		{ NULL, NULL } 
	}; 
	if (!StartServiceCtrlDispatcher( DispatchTable)) 
	{ 
		SvcDebugOut(" [SPLSRV_SERVICE] StartServiceCtrlDispatcher (%d)\n", 
			GetLastError()); 
	} 
} 
加为红色的类型SERVICE_INTERACTIVE_PROCESS:允许该服务在控制台上显示窗口,并且接受用户的输入,刚开始我没加这个类型,运行时一直没看到cmd窗口,后来看书才明白是这样
2.接下来是编写对服务的控制和管理:
通过OpenSCManager获得服务控制管理器句柄,然后用CreateService创建服务,然后是启动服务,主要过程代码如下:
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
	TCHAR szBinFilePath[MAX_PATH];
	PTCHAR pTemp;

	// 构造服务可执行程序的路径
	GetModuleFileName(NULL,szBinFilePath,MAX_PATH);
	pTemp = szBinFilePath+lstrlen(szBinFilePath);
	while(*--pTemp!='\\');
	lstrcpy(pTemp,TEXT("\\Service.exe"));
	
	// 打开 SCM
	schSCManager = OpenSCManager( 
		NULL,                    // local machine 
		NULL,                    // ServicesActive database 
		SC_MANAGER_ALL_ACCESS);  // full access rights 
	
	if (NULL == schSCManager) 
	{
		wsprintf(szBuffer,TEXT("OpenSCManager failed (%d)"),GetLastError());
		MessageBox(NULL,szBuffer,NULL,MB_OK);
	}
	// 创建服务
	CreateSampleService(schSCManager, szBinFilePath, szServiceName);
	// 启动服务
	StartSampleService(schSCManager,szServiceName);
	// 停止服务
	DeleteSampleService(szServiceName);
	CloseServiceHandle(schSCManager); 
}

3.至此一个服务程序就写完了,程序附上来,第一次在看雪上发帖,有点小兴奋,希望能够得到邀请码,想在《安全编程》版块向高手请教些内核编程的问题。支持看雪!希望看雪越办越好!!!

看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (16)
雪    币: 0
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
fzuer 活跃值 2010-5-30 16:30
2
0
好厉害。。。
雪    币: 76
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
主动防御 活跃值 2010-6-2 14:23
3
0
好贴不沉哦...
雪    币: 8
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zhuoyujian 活跃值 2010-6-2 14:26
4
0
  牛顶个
雪    币: 28
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hchky 活跃值 2010-6-3 12:58
5
0
虽然么看懂。。但是顶一个、、、
雪    币: 31
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
林smile 活跃值 2010-6-3 13:17
6
0
楼主好厉害啊
雪    币: 1032
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
dahual 活跃值 2 2010-6-3 20:59
7
0
学习。
雪    币: 31
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
fengkiss 活跃值 2010-6-3 21:14
8
0
好复杂 啊 喊了
雪    币: 18
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dsuker 活跃值 2010-6-7 14:25
9
0
你好,在win7下使用此代码,在调用StartService时出现错误,返回错误代码为“2”。
能够说明一下怎么解决么?谢谢~
雪    币: 14
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hzmforce 活跃值 2010-6-7 21:51
10
0
偶来作个标记
雪    币: 304
活跃值: 活跃值 (148)
能力值: ( LV15,RANK:310 )
在线值:
发帖
回帖
粉丝
dragonltx 活跃值 6 2010-6-7 22:49
11
0
2是“系统找不到指定文件”的意思!你要把注册服务的程序“service.exe”复制到启动服务的那个程序的Debug里!
雪    币: 4
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cating 活跃值 2010-6-8 00:11
12
0
虽然看不懂,但是顶一个,总有一天会看懂的!
雪    币: 44
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bupthui 活跃值 2010-6-8 00:14
13
0
真厉害啊
技术帝
雪    币: 14
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hzmforce 活跃值 2010-6-12 11:44
14
0
偶决定好好学习这一块
雪    币: 18
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dsuker 活跃值 2010-6-12 14:16
15
0
十分感谢,已经解决!
雪    币: 20
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cblcbl 活跃值 2010-6-12 14:53
16
0
虽然看不懂,但是还是感谢楼主,
该贴可以收藏,待有朝一日能重温该贴,而茅塞顿开。呵呵呵

革命尚未成功,同志仍须努力!
雪    币: 488
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hankcs 活跃值 2010-6-16 09:28
17
0
不错,支持了,技术贴啊
游客
登录 | 注册 方可回帖
返回