enumtaskscheduler.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <taskschd.h>
  4. #include <combaseapi.h>
  5. #include "enumtaskscheduler.h"
  6. #include "beacon.h"
  7. //START TrustedSec BOF print code: https://github.com/trustedsec/CS-Situational-Awareness-BOF/blob/master/src/common/base.c
  8. #ifndef bufsize
  9. #define bufsize 8192
  10. #endif
  11. char *output = 0;
  12. WORD currentoutsize = 0;
  13. HANDLE trash = NULL;
  14. int bofstart();
  15. void internal_printf(const char* format, ...);
  16. void printoutput(BOOL done);
  17. int bofstart() {
  18. output = (char*)MSVCRT$calloc(bufsize, 1);
  19. currentoutsize = 0;
  20. return 1;
  21. }
  22. void internal_printf(const char* format, ...){
  23. int buffersize = 0;
  24. int transfersize = 0;
  25. char * curloc = NULL;
  26. char* intBuffer = NULL;
  27. va_list args;
  28. va_start(args, format);
  29. buffersize = MSVCRT$vsnprintf(NULL, 0, format, args);
  30. va_end(args);
  31. if (buffersize == -1) return;
  32. char* transferBuffer = (char*)KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, bufsize);
  33. intBuffer = (char*)KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, buffersize);
  34. va_start(args, format);
  35. MSVCRT$vsnprintf(intBuffer, buffersize, format, args);
  36. va_end(args);
  37. if(buffersize + currentoutsize < bufsize)
  38. {
  39. MSVCRT$memcpy(output+currentoutsize, intBuffer, buffersize);
  40. currentoutsize += buffersize;
  41. } else {
  42. curloc = intBuffer;
  43. while(buffersize > 0)
  44. {
  45. transfersize = bufsize - currentoutsize;
  46. if(buffersize < transfersize)
  47. {
  48. transfersize = buffersize;
  49. }
  50. MSVCRT$memcpy(output+currentoutsize, curloc, transfersize);
  51. currentoutsize += transfersize;
  52. if(currentoutsize == bufsize)
  53. {
  54. printoutput(FALSE);
  55. }
  56. MSVCRT$memset(transferBuffer, 0, transfersize);
  57. curloc += transfersize;
  58. buffersize -= transfersize;
  59. }
  60. }
  61. KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, intBuffer);
  62. KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, transferBuffer);
  63. }
  64. void printoutput(BOOL done) {
  65. char * msg = NULL;
  66. BeaconOutput(CALLBACK_OUTPUT, output, currentoutsize);
  67. currentoutsize = 0;
  68. MSVCRT$memset(output, 0, bufsize);
  69. if(done) {MSVCRT$free(output); output=NULL;}
  70. }
  71. //END TrustedSec BOF print code.
  72. BOOL EnumScheduledTasks(wchar_t * host) {
  73. HRESULT hr = S_OK;
  74. hr = OLE32$CoInitializeEx(NULL, COINIT_MULTITHREADED);
  75. if (FAILED(hr)) return FALSE;
  76. IID CTaskScheduler = {0x0f87369f, 0xa4e5, 0x4cfc, {0xbd,0x3e,0x73,0xe6,0x15,0x45,0x72,0xdd}};
  77. IID IIDITaskService = {0x2faba4c7, 0x4da9, 0x4013, {0x96, 0x97, 0x20, 0xcc, 0x3f, 0xd4, 0x0f, 0x85}};
  78. ITaskService *pTaskService = NULL;
  79. hr = OLE32$CoCreateInstance(&CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, &IIDITaskService, (void**)&pTaskService);
  80. if (FAILED(hr)) {
  81. return FALSE;
  82. }
  83. VARIANT Vhost;
  84. VARIANT VNull;
  85. OLEAUT32$VariantInit(&Vhost);
  86. OLEAUT32$VariantInit(&VNull);
  87. Vhost.vt = VT_BSTR;
  88. Vhost.bstrVal = OLEAUT32$SysAllocString(host);
  89. hr = pTaskService->lpVtbl->Connect(pTaskService, Vhost, VNull, VNull, VNull);
  90. if (FAILED(hr)) {
  91. goto cleanup;
  92. }
  93. ITaskFolder* pRootFolder = NULL;
  94. hr = pTaskService->lpVtbl->GetFolder(pTaskService, L"\\", &pRootFolder);
  95. if (FAILED(hr)) {
  96. goto cleanup;
  97. }
  98. IRegisteredTaskCollection* pTaskCollection = NULL;
  99. hr = pRootFolder->lpVtbl->GetTasks(pRootFolder, 0, &pTaskCollection);
  100. if (FAILED(hr)) {
  101. goto cleanup;
  102. }
  103. long numTasks = 0;
  104. hr = pTaskCollection->lpVtbl->get_Count(pTaskCollection, &numTasks);
  105. internal_printf("[+] Scheduled tasks in root folder:\n");
  106. internal_printf("=======================================================\n\n");
  107. for (long i = 1; i <= numTasks; i++) {
  108. IRegisteredTask* pRegisteredTask = NULL;
  109. VARIANT index;
  110. index.vt = VT_I4;
  111. index.lVal = i;
  112. hr = pTaskCollection->lpVtbl->get_Item(pTaskCollection, index, &pRegisteredTask);
  113. if (SUCCEEDED(hr)) {
  114. BSTR taskName = NULL;
  115. hr = pRegisteredTask->lpVtbl->get_Name(pRegisteredTask, &taskName);
  116. if (SUCCEEDED(hr)) {
  117. internal_printf("Task Name: %ls\n", taskName);
  118. OLEAUT32$SysFreeString(taskName);
  119. }
  120. ITaskDefinition* pTaskDef = NULL;
  121. hr = pRegisteredTask->lpVtbl->get_Definition(pRegisteredTask, &pTaskDef);
  122. if (SUCCEEDED(hr)) {
  123. // Fetching the Principal information and print the user account
  124. IPrincipal* pPrincipal = NULL;
  125. hr = pTaskDef->lpVtbl->get_Principal(pTaskDef, &pPrincipal);
  126. if (SUCCEEDED(hr)) {
  127. BSTR userId = NULL;
  128. hr = pPrincipal->lpVtbl->get_UserId(pPrincipal, &userId);
  129. if (SUCCEEDED(hr)) {
  130. internal_printf("- Task running as: %ls\n", userId);
  131. OLEAUT32$SysFreeString(userId);
  132. }
  133. pPrincipal->lpVtbl->Release(pPrincipal);
  134. }
  135. // Fetching Action Information
  136. ITaskDefinition* pTaskDef = NULL;
  137. hr = pRegisteredTask->lpVtbl->get_Definition(pRegisteredTask, &pTaskDef);
  138. if (SUCCEEDED(hr)) {
  139. IActionCollection* pActionColl = NULL;
  140. hr = pTaskDef->lpVtbl->get_Actions(pTaskDef, &pActionColl);
  141. if (SUCCEEDED(hr)) {
  142. long actionCount = 0;
  143. hr = pActionColl->lpVtbl->get_Count(pActionColl, &actionCount);
  144. if (SUCCEEDED(hr)) {
  145. for (long j = 1; j <= actionCount; j++) {
  146. IAction* pAction = NULL;
  147. long actionIndex = j;
  148. hr = pActionColl->lpVtbl->get_Item(pActionColl, actionIndex, &pAction);
  149. if (SUCCEEDED(hr)) {
  150. TASK_ACTION_TYPE actionType;
  151. hr = pAction->lpVtbl->get_Type(pAction, &actionType);
  152. if (SUCCEEDED(hr)) {
  153. WCHAR* actionTypes[] = {
  154. L"Start a program",
  155. L"Send an e-mail (Deprecated)",
  156. L"Display a message (Deprecated)"
  157. };
  158. WCHAR* actionTypeName = actionTypes[actionType]; // Using actionType as an index
  159. internal_printf("- Action type: %ls\n", actionTypeName);
  160. if (actionType == TASK_ACTION_EXEC) {
  161. IExecAction* pExecAction = (IExecAction*) pAction;
  162. BSTR execPath;
  163. hr = pExecAction->lpVtbl->get_Path(pExecAction, &execPath);
  164. if (SUCCEEDED(hr)) {
  165. internal_printf("- Executable path: %ls\n", execPath);
  166. OLEAUT32$SysFreeString(execPath);
  167. }
  168. }
  169. }
  170. pAction->lpVtbl->Release(pAction);
  171. }
  172. }
  173. }
  174. }
  175. }
  176. // Fetching Trigger Information
  177. ITriggerCollection* pTriggerColl = NULL;
  178. hr = pTaskDef->lpVtbl->get_Triggers(pTaskDef, &pTriggerColl);
  179. if (SUCCEEDED(hr)) {
  180. long triggerCount = 0;
  181. hr = pTriggerColl->lpVtbl->get_Count(pTriggerColl, &triggerCount);
  182. if (SUCCEEDED(hr)) {
  183. for (long j = 1; j <= triggerCount; j++) {
  184. ITrigger* pTrigger = NULL;
  185. long triggerIndex = j;
  186. hr = pTriggerColl->lpVtbl->get_Item(pTriggerColl, triggerIndex, &pTrigger);
  187. if (SUCCEEDED(hr)) {
  188. TASK_TRIGGER_TYPE2 triggerType;
  189. hr = pTrigger->lpVtbl->get_Type(pTrigger, &triggerType);
  190. if (SUCCEEDED(hr)) {
  191. static const WCHAR* triggerTypeNames[] = {
  192. L"On an event", // 1
  193. L"On a schedule", // 2
  194. L"Daily", // 3
  195. L"Weekly", // 4
  196. L"Monthly", // 5
  197. L"MonthlyDOW", // 6
  198. L"On idle", // 7
  199. L"At task creation/modification", // 8
  200. L"At startup", // 9
  201. L"At log on", // 10
  202. L"SessionStateChange (lock/unlock/connection)", // 11
  203. L"SessionStateChange (lock/unlock/connection)" // 12
  204. };
  205. const WCHAR* triggerTypeName = (triggerType >= 0 && triggerType < sizeof(triggerTypeNames) / sizeof(triggerTypeNames[0]))
  206. ? triggerTypeNames[triggerType]
  207. : L"Unknown";
  208. internal_printf("- Trigger type: %ls\n", triggerTypeName);
  209. }
  210. pTrigger->lpVtbl->Release(pTrigger);
  211. }
  212. }
  213. }
  214. pTriggerColl->lpVtbl->Release(pTriggerColl);
  215. }
  216. pTaskDef->lpVtbl->Release(pTaskDef);
  217. }
  218. if (pRegisteredTask) {
  219. pRegisteredTask->lpVtbl->Release(pRegisteredTask);
  220. }
  221. }
  222. internal_printf("----------------------------------------------------\n\n");
  223. }
  224. cleanup:
  225. if (pTaskCollection) {
  226. pTaskCollection->lpVtbl->Release(pTaskCollection);
  227. }
  228. if (pRootFolder) {
  229. pRootFolder->lpVtbl->Release(pRootFolder);
  230. }
  231. if (pTaskService) {
  232. pTaskService->lpVtbl->Release(pTaskService);
  233. }
  234. OLEAUT32$VariantClear(&Vhost);
  235. OLE32$CoUninitialize();
  236. return TRUE;
  237. }
  238. int go(char *args, int len) {
  239. BOOL res = NULL;
  240. datap parser;
  241. WCHAR *hostName = L"";
  242. BeaconDataParse(&parser, args, len);
  243. hostName = BeaconDataExtract(&parser, NULL);
  244. if(!bofstart()) return;
  245. res = EnumScheduledTasks(hostName);
  246. if(!res) BeaconPrintf(CALLBACK_ERROR, "Failed to enumerate scheduled tasks.\n");
  247. else {
  248. printoutput(TRUE);
  249. BeaconPrintf(CALLBACK_OUTPUT, "[+] Finished enumerating!\n");
  250. }
  251. return 0;
  252. }