findlib.c 6.7 KB

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