enumtaskscheduler.c 9.2 KB

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