创建计划任务实现开机自启动

Collapser

发布日期: 2018-12-20 12:17:10 浏览量: 1835
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

背景

想必实现程序开机自启动,是很常见的功能了。无论是恶意程序,还是正常的应用软件,都会提供这个功能,方便用户的使用。程序开机自启动,顾名思义,就是计算机开机后,不用人为地去运行程序,程序就可以自己运行起来。对于这个功能的,一直都是杀软重点监测的地方。因为,对于病毒来说,重要的不是如何被破坏,而是如何启动。

在过去写的大大小小的程序中,我也实现过程序自启动的功能。现在,我把这些自启动功能的实现方式进行下总结。常见的方式有:修改开机自启动注册表、开机自启动目录、创建开机自启计划任务、创建开机自启系统服务等方式。现在对这些技术一一进行分析,并形成文档分享给大家。本文介绍的是创建自启动任务计划实现开机自启动的方式,其它的实现方式可以搜索我写的相关系列的文档。

实现原理

我是使用Windows Shell编程实现创建任务计划,所以会涉及COM组件相关知识。

现在,为方便大家的理解,我把整个程序的逻辑概括为 3 各部分,分别是:初始化操作、创建任务计划以及删除任务计划。现在,我们一一对每一个部分进行解析。

初始化操作

初始化操作的目的就是获取 ITaskService 对象以及 ITaskFolder 对象,我们创建任务计划,主要是对这两个指针进行操作。具体流程是:

  • 首先初始化COM接口环境,因为我们接下来会使用到COM组件

  • 然后,创建 ITaskService 对象,并连接到任务服务上

  • 接着,从 ITaskService 对象中获取 ITaskFolder 对象

这样,初始化操作就完成了,接下来就是直接使用 ITaskService 对象以及 ITaskFolder 对象进行操作了。

创建任务计划

现在,解析下任务计划的具体创建过程:

  • 首先,从 ITaskService 对象中创建一个任务定义对象 ITaskDefinition,用来来创建任务

  • 接着,就是开始对任务定义对象 ITaskDefinition进行设置:

    • 设置注册信息,包括设置作者的信息

    • 设置主体信息,包括登陆类型、运行权限

    • 设置设置信息,包括设置在使用电池运行时是否停止、在使用电池是是否允许运行、是否允许手动运行、是否设置多个实例

    • 设置操作信息,包括启动程序,并设置运行程序的路径和参数

    • 设置触发器信息,包括用户登录时触发

  • 最后,使用 ITaskFolder 对象根据任务定义对象 ITaskDefinition的设置,注册任务计划

这样,任务计划创建的操作就完成了,只要满足设置的触发条件,那么就会启动指定程序。

删除任务计划

ITaskFolder 对象存储着已经注册成功的任务计划的信息,我们只需要将任务计划的名称传入其中,调用DeleteTask接口函数,就可以删除指定的任务计划了。

编码实现

创建任务计划的初始化

  1. CMyTaskSchedule::CMyTaskSchedule(void)
  2. {
  3. m_lpITS = NULL;
  4. m_lpRootFolder = NULL;
  5. // 初始化COM
  6. HRESULT hr = ::CoInitialize(NULL);
  7. if(FAILED(hr))
  8. {
  9. ShowError("CoInitialize", hr);
  10. }
  11. // 创建一个任务服务(Task Service)实例
  12. hr = ::CoCreateInstance(CLSID_TaskScheduler,
  13. NULL,
  14. CLSCTX_INPROC_SERVER,
  15. IID_ITaskService,
  16. (LPVOID *)(&m_lpITS));
  17. if(FAILED(hr))
  18. {
  19. ShowError("CoCreateInstance", hr);
  20. }
  21. // 连接到任务服务(Task Service)
  22. hr = m_lpITS->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
  23. if(FAILED(hr))
  24. {
  25. ShowError("ITaskService::Connect", hr);
  26. }
  27. // 获取Root Task Folder的指针,这个指针指向的是新注册的任务
  28. hr = m_lpITS->GetFolder(_bstr_t("\\"), &m_lpRootFolder);
  29. if(FAILED(hr))
  30. {
  31. ShowError("ITaskService::GetFolder", hr);
  32. }
  33. }

创建任务计划

  1. BOOL CMyTaskSchedule::NewTask(char *lpszTaskName, char *lpszProgramPath, char *lpszParameters, char *lpszAuthor)
  2. {
  3. if(NULL == m_lpRootFolder)
  4. {
  5. return FALSE;
  6. }
  7. // 如果存在相同的计划任务,则删除
  8. Delete(lpszTaskName);
  9. // 创建任务定义对象来创建任务
  10. ITaskDefinition *pTaskDefinition = NULL;
  11. HRESULT hr = m_lpITS->NewTask(0, &pTaskDefinition);
  12. if(FAILED(hr))
  13. {
  14. ShowError("ITaskService::NewTask", hr);
  15. return FALSE;
  16. }
  17. /* 设置注册信息 */
  18. IRegistrationInfo *pRegInfo = NULL;
  19. CComVariant variantAuthor(NULL);
  20. variantAuthor = lpszAuthor;
  21. hr = pTaskDefinition->get_RegistrationInfo(&pRegInfo);
  22. if(FAILED(hr))
  23. {
  24. ShowError("pTaskDefinition::get_RegistrationInfo", hr);
  25. return FALSE;
  26. }
  27. // 设置作者信息
  28. hr = pRegInfo->put_Author(variantAuthor.bstrVal);
  29. pRegInfo->Release();
  30. /* 设置登录类型和运行权限 */
  31. IPrincipal *pPrincipal = NULL;
  32. hr = pTaskDefinition->get_Principal(&pPrincipal);
  33. if(FAILED(hr))
  34. {
  35. ShowError("pTaskDefinition::get_Principal", hr);
  36. return FALSE;
  37. }
  38. // 设置登录类型
  39. hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
  40. // 设置运行权限
  41. // 最高权限
  42. hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);
  43. pPrincipal->Release();
  44. /* 设置其他信息 */
  45. ITaskSettings *pSettting = NULL;
  46. hr = pTaskDefinition->get_Settings(&pSettting);
  47. if(FAILED(hr))
  48. {
  49. ShowError("pTaskDefinition::get_Settings", hr);
  50. return FALSE;
  51. }
  52. // 设置其他信息
  53. hr = pSettting->put_StopIfGoingOnBatteries(VARIANT_FALSE);
  54. hr = pSettting->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
  55. hr = pSettting->put_AllowDemandStart(VARIANT_TRUE);
  56. hr = pSettting->put_StartWhenAvailable(VARIANT_FALSE);
  57. hr = pSettting->put_MultipleInstances(TASK_INSTANCES_PARALLEL);
  58. pSettting->Release();
  59. /* 创建执行动作 */
  60. IActionCollection *pActionCollect = NULL;
  61. hr = pTaskDefinition->get_Actions(&pActionCollect);
  62. if(FAILED(hr))
  63. {
  64. ShowError("pTaskDefinition::get_Actions", hr);
  65. return FALSE;
  66. }
  67. IAction *pAction = NULL;
  68. // 创建执行操作
  69. hr = pActionCollect->Create(TASK_ACTION_EXEC, &pAction);
  70. pActionCollect->Release();
  71. /* 设置执行程序路径和参数 */
  72. CComVariant variantProgramPath(NULL);
  73. CComVariant variantParameters(NULL);
  74. IExecAction *pExecAction = NULL;
  75. hr = pAction->QueryInterface(IID_IExecAction, (PVOID *)(&pExecAction));
  76. if(FAILED(hr))
  77. {
  78. pAction->Release();
  79. ShowError("IAction::QueryInterface", hr);
  80. return FALSE;
  81. }
  82. pAction->Release();
  83. // 设置程序路径和参数
  84. variantProgramPath = lpszProgramPath;
  85. variantParameters = lpszParameters;
  86. pExecAction->put_Path(variantProgramPath.bstrVal);
  87. pExecAction->put_Arguments(variantParameters.bstrVal);
  88. pExecAction->Release();
  89. /* 创建触发器,实现用户登陆自启动 */
  90. ITriggerCollection *pTriggers = NULL;
  91. hr = pTaskDefinition->get_Triggers(&pTriggers);
  92. if (FAILED(hr))
  93. {
  94. ShowError("pTaskDefinition::get_Triggers", hr);
  95. return FALSE;
  96. }
  97. // 创建触发器
  98. ITrigger *pTrigger = NULL;
  99. hr = pTriggers->Create(TASK_TRIGGER_LOGON, &pTrigger);
  100. if (FAILED(hr))
  101. {
  102. ShowError("ITriggerCollection::Create", hr);
  103. return FALSE;
  104. }
  105. /* 注册任务计划 */
  106. IRegisteredTask *pRegisteredTask = NULL;
  107. CComVariant variantTaskName(NULL);
  108. variantTaskName = lpszTaskName;
  109. hr = m_lpRootFolder->RegisterTaskDefinition(variantTaskName.bstrVal,
  110. pTaskDefinition,
  111. TASK_CREATE_OR_UPDATE,
  112. _variant_t(),
  113. _variant_t(),
  114. TASK_LOGON_INTERACTIVE_TOKEN,
  115. _variant_t(""),
  116. &pRegisteredTask);
  117. if(FAILED(hr))
  118. {
  119. pTaskDefinition->Release();
  120. ShowError("ITaskFolder::RegisterTaskDefinition", hr);
  121. return FALSE;
  122. }
  123. pTaskDefinition->Release();
  124. pRegisteredTask->Release();
  125. return TRUE;
  126. }

删除任务计划

  1. BOOL CMyTaskSchedule::Delete(char *lpszTaskName)
  2. {
  3. if(NULL == m_lpRootFolder)
  4. {
  5. return FALSE;
  6. }
  7. CComVariant variantTaskName(NULL);
  8. variantTaskName = lpszTaskName;
  9. HRESULT hr = m_lpRootFolder->DeleteTask(variantTaskName.bstrVal, 0);
  10. if(FAILED(hr))
  11. {
  12. return FALSE;
  13. }
  14. return TRUE;
  15. }

程序测试

在 main 函数中调用上述封装好的函数,进行测试。main 函数为:

  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3. CMyTaskSchedule task;
  4. BOOL bRet = FALSE;
  5. // 创建 任务计划
  6. bRet = task.NewTask("520", "C:\\Users\\DemonGan\\Desktop\\520.exe", "", "");
  7. if (FALSE == bRet)
  8. {
  9. printf("Create Task Schedule Error!\n");
  10. }
  11. // 暂停
  12. printf("Create Task Schedule OK!\n");
  13. system("pause");
  14. // 卸载 任务计划
  15. bRet = task.Delete("520");
  16. if (FALSE == bRet)
  17. {
  18. printf("Delete Task Schedule Error!\n");
  19. }
  20. printf("Delete Task Schedule OK!\n");
  21. system("pause");
  22. return 0;
  23. }

测试结果:

“以管理员身份运行程序”方式打开程序,提示任务计划创建成功。

打开任务计划列表进行查看,发现“520”任务计划成功创建。

然后,删除创建的任务计划,程序提示删除成功。

查看任务计划列表,发现“520”任务计划已经成功删除。

所以,测试成功。

总结

这个功能的实现涉及到COM组件的相关知识,所以初学者对此可能感到陌生,这是很正常的。其实,对于这方面的理解我也没有什么好的建议,只有多动手练几遍,加深程序逻辑和印象吧。

注意的地方就是,创建任务计划,要求程序必须要有管机员权限才行。所以,测试的时候,不要忘记以管理员身份运行程序。

参考

参考自《Windows黑客编程技术详解》一书

上传的附件 cloud_download AutoRun_Task_Test.7z ( 160.47kb, 42次下载 )

发送私信

三观不同不适合做朋友

11
文章数
13
评论数
最近文章
eject