findlib.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <tlhelp32.h>
  4. #include <psapi.h>
  5. #include <shlwapi.h>
  6. #include "findlib.h"
  7. #include "beacon.h"
  8. #pragma comment(lib, "ntdll.lib")
  9. #pragma comment(lib, "Shlwapi.lib")
  10. //Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
  11. HRESULT BeaconPrintToStreamW(_In_z_ LPCWSTR lpwFormat, ...) {
  12. HRESULT hr = S_FALSE;
  13. va_list argList;
  14. DWORD dwWritten = 0;
  15. if (g_lpStream <= (LPSTREAM)1) {
  16. hr = OLE32$CreateStreamOnHGlobal(NULL, TRUE, &g_lpStream);
  17. if (FAILED(hr)) {
  18. return hr;
  19. }
  20. }
  21. // For BOF we need to avoid large stack buffers, so put print buffer on heap.
  22. if (g_lpwPrintBuffer <= (LPWSTR)1) { // Allocate once and free in BeaconOutputStreamW.
  23. g_lpwPrintBuffer = (LPWSTR)MSVCRT$calloc(MAX_STRING, sizeof(WCHAR));
  24. if (g_lpwPrintBuffer == NULL) {
  25. hr = E_FAIL;
  26. goto CleanUp;
  27. }
  28. }
  29. va_start(argList, lpwFormat);
  30. if (!MSVCRT$_vsnwprintf_s(g_lpwPrintBuffer, MAX_STRING, MAX_STRING -1, lpwFormat, argList)) {
  31. hr = E_FAIL;
  32. goto CleanUp;
  33. }
  34. if (g_lpStream != NULL) {
  35. if (FAILED(hr = g_lpStream->lpVtbl->Write(g_lpStream, g_lpwPrintBuffer, (ULONG)MSVCRT$wcslen(g_lpwPrintBuffer) * sizeof(WCHAR), &dwWritten))) {
  36. goto CleanUp;
  37. }
  38. }
  39. hr = S_OK;
  40. CleanUp:
  41. if (g_lpwPrintBuffer != NULL) {
  42. MSVCRT$memset(g_lpwPrintBuffer, 0, MAX_STRING * sizeof(WCHAR)); // Clear print buffer.
  43. }
  44. va_end(argList);
  45. return hr;
  46. }
  47. //Code from: https://github.com/outflanknl/C2-Tool-Collection/blob/main/BOF/Psx/SOURCE/Psx.c
  48. VOID BeaconOutputStreamW() {
  49. STATSTG ssStreamData = { 0 };
  50. SIZE_T cbSize = 0;
  51. ULONG cbRead = 0;
  52. LARGE_INTEGER pos;
  53. LPWSTR lpwOutput = NULL;
  54. if (FAILED(g_lpStream->lpVtbl->Stat(g_lpStream, &ssStreamData, STATFLAG_NONAME))) {
  55. return;
  56. }
  57. cbSize = ssStreamData.cbSize.LowPart;
  58. lpwOutput = KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, cbSize + 1);
  59. if (lpwOutput != NULL) {
  60. pos.QuadPart = 0;
  61. if (FAILED(g_lpStream->lpVtbl->Seek(g_lpStream, pos, STREAM_SEEK_SET, NULL))) {
  62. goto CleanUp;
  63. }
  64. if (FAILED(g_lpStream->lpVtbl->Read(g_lpStream, lpwOutput, (ULONG)cbSize, &cbRead))) {
  65. goto CleanUp;
  66. }
  67. BeaconPrintf(CALLBACK_OUTPUT, "%ls", lpwOutput);
  68. }
  69. CleanUp:
  70. if (g_lpStream != NULL) {
  71. g_lpStream->lpVtbl->Release(g_lpStream);
  72. g_lpStream = NULL;
  73. }
  74. if (g_lpwPrintBuffer != NULL) {
  75. MSVCRT$free(g_lpwPrintBuffer); // Free print buffer.
  76. g_lpwPrintBuffer = NULL;
  77. }
  78. if (lpwOutput != NULL) {
  79. KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, lpwOutput);
  80. }
  81. return;
  82. }
  83. WCHAR ConvertToWCHAR(char input) {
  84. WCHAR output[100];
  85. KERNEL32$MultiByteToWideChar(CP_ACP, 0, input, -1, output, 100);
  86. return output;
  87. }
  88. BOOL ListModules(int pid, char *targetModName) {
  89. HANDLE hProcess;
  90. MEMORY_BASIC_INFORMATION mbi;
  91. char * base = NULL;
  92. BOOL foundModule = FALSE;
  93. hProcess = KERNEL32$OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
  94. if (hProcess == NULL) return foundModule;
  95. while (KERNEL32$VirtualQueryEx(hProcess, base, &mbi, sizeof(mbi)) == sizeof(MEMORY_BASIC_INFORMATION)) {
  96. char fqModPath[MAX_PATH];
  97. char modName[MAX_PATH];
  98. if(targetModName != NULL) {
  99. // only focus on the base address regions
  100. if ((mbi.AllocationBase == mbi.BaseAddress) && (mbi.AllocationBase != NULL)) {
  101. if (KERNEL32$K32GetModuleBaseNameA(hProcess, (HMODULE) mbi.AllocationBase, (LPSTR) modName, sizeof(modName) / sizeof(TCHAR))) {
  102. if(MSVCRT$strcmp(targetModName, modName) == 0) {
  103. WCHAR wFqModPath[100];
  104. KERNEL32$K32GetModuleFileNameExA(hProcess, (HMODULE) mbi.AllocationBase, (LPSTR) fqModPath, sizeof(fqModPath) / sizeof(TCHAR));
  105. KERNEL32$MultiByteToWideChar(CP_ACP, 0, fqModPath, -1, wFqModPath, 100);
  106. BeaconPrintToStreamW(L"\nModulePath:\t%s\nModuleAddr:\t%#llx\n", wFqModPath, mbi.AllocationBase);
  107. foundModule = TRUE;
  108. }
  109. }
  110. }
  111. // check the next region
  112. base += mbi.RegionSize;
  113. }
  114. else {
  115. // only focus on the base address regions
  116. if ((mbi.AllocationBase == mbi.BaseAddress) && (mbi.AllocationBase != NULL)) {
  117. if (KERNEL32$K32GetModuleFileNameExA(hProcess, (HMODULE) mbi.AllocationBase, (LPSTR) fqModPath, sizeof(fqModPath) / sizeof(TCHAR))) {
  118. WCHAR wFqModPath[100];
  119. KERNEL32$MultiByteToWideChar(CP_ACP, 0, fqModPath, -1, wFqModPath, 100);
  120. BeaconPrintToStreamW(L"ModulePath [%#llx]: %s\n", mbi.AllocationBase, wFqModPath);
  121. foundModule = TRUE;
  122. }
  123. }
  124. // check the next region
  125. base += mbi.RegionSize;
  126. }
  127. }
  128. KERNEL32$CloseHandle(hProcess);
  129. return foundModule;
  130. }
  131. BOOL FindProcess(char *targetModName) {
  132. int procID = 0;
  133. HANDLE currentProc = NULL;
  134. char procPath[MAX_PATH];
  135. BOOL foundProc = FALSE;
  136. BOOL res = FALSE;
  137. // resolve function address
  138. NtGetNextProcess_t pNtGetNextProcess = (NtGetNextProcess_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtGetNextProcess");
  139. // loop through all processes
  140. while (!pNtGetNextProcess(currentProc, MAXIMUM_ALLOWED, 0, 0, &currentProc)) {
  141. procID = KERNEL32$GetProcessId(currentProc);
  142. if(procID == 4) continue;
  143. if (procID == KERNEL32$GetCurrentProcessId()) continue;
  144. if (procID != 0) foundProc = ListModules(procID, targetModName);
  145. if(foundProc) {
  146. WCHAR wProcName[100];
  147. WCHAR wProcPath[256];
  148. KERNEL32$K32GetProcessImageFileNameA(currentProc, procPath, MAX_PATH);
  149. KERNEL32$MultiByteToWideChar(CP_ACP, 0, SHLWAPI$PathFindFileNameA(procPath), -1, wProcName, 100);
  150. KERNEL32$MultiByteToWideChar(CP_ACP, 0, procPath, -1, wProcPath, 256);
  151. BeaconPrintToStreamW(L"ProcName:\t%s\nProcID:\t\t%d\nProcPath:\tC:\%s\n", wProcName, procID, wProcPath);
  152. res = TRUE;
  153. }
  154. }
  155. return res;
  156. }
  157. int go(char *args, int len) {
  158. int pid = 0;
  159. BOOL res = NULL;
  160. CHAR *option;
  161. CHAR *targetModName;
  162. datap parser;
  163. BeaconDataParse(&parser, args, len);
  164. option = BeaconDataExtract(&parser, NULL);
  165. if (MSVCRT$strcmp(option, "list") == 0) {
  166. pid = BeaconDataInt(&parser);
  167. BeaconPrintf(CALLBACK_OUTPUT, "[*] Start enumerating loaded modules for PID: %d\n\n", pid);
  168. BeaconPrintToStreamW(L"[+] FOUND MODULES:\n==============================================================\n");
  169. res = ListModules(pid, NULL);
  170. }
  171. else if (MSVCRT$strcmp(option, "search") == 0) {
  172. targetModName = BeaconDataExtract(&parser, NULL);
  173. BeaconPrintf(CALLBACK_OUTPUT, "[*] Start enumerating processes that loaded module: %s\n[!] Can take some time..\n\n", targetModName);
  174. BeaconPrintToStreamW(L"[+] FOUND PROCESSES:\n==============================================================\n");
  175. res = FindProcess(targetModName);
  176. }
  177. else {
  178. BeaconPrintf(CALLBACK_ERROR, "This enumeration option isn't supported. Please specify one of the following enumeration options: search | list\n");
  179. return 0;
  180. }
  181. if(!res) BeaconPrintf(CALLBACK_ERROR, "No modules found for this search query!\n\n");
  182. else {
  183. BeaconOutputStreamW();
  184. BeaconPrintf(CALLBACK_OUTPUT, "\n[+] DONE");
  185. }
  186. return 0;
  187. }