enumfiles.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdbool.h>
  4. #include "enumfiles.h"
  5. #include "beacon.h"
  6. #define MAX_PREVIEW_LENGTH 200
  7. //START TrustedSec BOF print code: https://github.com/trustedsec/CS-Situational-Awareness-BOF/blob/master/src/common/base.c
  8. #ifndef bufsize
  9. #define bufsize 8192
  10. #endif
  11. char *output = 0;
  12. WORD currentoutsize = 0;
  13. HANDLE trash = NULL;
  14. int bofstart();
  15. void internal_printf(const char* format, ...);
  16. void printoutput(BOOL done);
  17. int bofstart() {
  18. output = (char*)MSVCRT$calloc(bufsize, 1);
  19. currentoutsize = 0;
  20. return 1;
  21. }
  22. void internal_printf(const char* format, ...){
  23. int buffersize = 0;
  24. int transfersize = 0;
  25. char * curloc = NULL;
  26. char* intBuffer = NULL;
  27. va_list args;
  28. va_start(args, format);
  29. buffersize = MSVCRT$vsnprintf(NULL, 0, format, args);
  30. va_end(args);
  31. if (buffersize == -1) return;
  32. char* transferBuffer = (char*)KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, bufsize);
  33. intBuffer = (char*)KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, buffersize);
  34. va_start(args, format);
  35. MSVCRT$vsnprintf(intBuffer, buffersize, format, args);
  36. va_end(args);
  37. if(buffersize + currentoutsize < bufsize)
  38. {
  39. MSVCRT$memcpy(output+currentoutsize, intBuffer, buffersize);
  40. currentoutsize += buffersize;
  41. } else {
  42. curloc = intBuffer;
  43. while(buffersize > 0)
  44. {
  45. transfersize = bufsize - currentoutsize;
  46. if(buffersize < transfersize)
  47. {
  48. transfersize = buffersize;
  49. }
  50. MSVCRT$memcpy(output+currentoutsize, curloc, transfersize);
  51. currentoutsize += transfersize;
  52. if(currentoutsize == bufsize)
  53. {
  54. printoutput(FALSE);
  55. }
  56. MSVCRT$memset(transferBuffer, 0, transfersize);
  57. curloc += transfersize;
  58. buffersize -= transfersize;
  59. }
  60. }
  61. KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, intBuffer);
  62. KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, transferBuffer);
  63. }
  64. void printoutput(BOOL done) {
  65. char * msg = NULL;
  66. BeaconOutput(CALLBACK_OUTPUT, output, currentoutsize);
  67. currentoutsize = 0;
  68. MSVCRT$memset(output, 0, bufsize);
  69. if(done) {MSVCRT$free(output); output=NULL;}
  70. }
  71. //END TrustedSec BOF print code.
  72. bool keywordMatches(const char* content, const char* keyword) {
  73. size_t keywordLen = MSVCRT$strlen(keyword);
  74. // If keyword is "*example*"
  75. if (keyword[0] == '*' && keyword[keywordLen - 1] == '*') {
  76. char tempKeyword[MAX_PATH];
  77. MSVCRT$strncpy(tempKeyword, keyword + 1, keywordLen - 2);
  78. tempKeyword[keywordLen - 2] = '\0';
  79. if (MSVCRT$strstr(content, tempKeyword)) {
  80. return true;
  81. }
  82. }
  83. // If keyword is "example*"
  84. else if (keyword[keywordLen - 1] == '*') {
  85. char tempKeyword[MAX_PATH];
  86. MSVCRT$strncpy(tempKeyword, keyword, keywordLen - 1);
  87. tempKeyword[keywordLen - 1] = '\0';
  88. if (MSVCRT$strncmp(content, tempKeyword, keywordLen - 1) == 0) {
  89. return true;
  90. }
  91. }
  92. // If keyword is "*example"
  93. else if (keyword[0] == '*') {
  94. if (MSVCRT$strlen(content) >= keywordLen - 1 &&
  95. MSVCRT$strcmp(content + MSVCRT$strlen(content) - (keywordLen - 1), keyword + 1) == 0) {
  96. return true;
  97. }
  98. }
  99. // If keyword is "example"
  100. else if (MSVCRT$strstr(content, keyword)) {
  101. return true;
  102. }
  103. return false;
  104. }
  105. bool SearchFileForKeyword(const char* filePath, const char* keyword) {
  106. FILE *file = MSVCRT$fopen(filePath, "rb");
  107. if (!file) {
  108. BeaconPrintf(CALLBACK_ERROR, "Failed to open file: %s\n", filePath);
  109. return false;
  110. }
  111. MSVCRT$fseek(file, 0, SEEK_END);
  112. long fileSize = MSVCRT$ftell(file);
  113. MSVCRT$fseek(file, 0, SEEK_SET);
  114. char* fileContents = (char*)MSVCRT$malloc(fileSize + 1);
  115. if(!fileContents) {
  116. BeaconPrintf(CALLBACK_ERROR, "Failed to allocate memory for file: %s\n", filePath);
  117. MSVCRT$fclose(file);
  118. return false;
  119. }
  120. MSVCRT$fread(fileContents, 1, fileSize, file);
  121. fileContents[fileSize] = '\0';
  122. MSVCRT$fclose(file);
  123. // Convert file contents to lowercase
  124. for (long i = 0; i < fileSize; i++) {
  125. fileContents[i] = MSVCRT$tolower(fileContents[i]);
  126. }
  127. // Convert keyword to lowercase
  128. char* lowerKeyword = MSVCRT$_strdup(keyword);
  129. if (!lowerKeyword) {
  130. MSVCRT$free(fileContents);
  131. return false;
  132. }
  133. for (int i = 0; lowerKeyword[i]; i++) {
  134. lowerKeyword[i] = MSVCRT$tolower(lowerKeyword[i]);
  135. }
  136. //match line with keyword and return pattern if true
  137. char* line = MSVCRT$strtok(fileContents, "\n");
  138. bool found = false;
  139. bool firstPrint = true;
  140. char preview[MAX_PREVIEW_LENGTH + 1];
  141. while (line) {
  142. if (keywordMatches(line, lowerKeyword)) {
  143. found = true;
  144. int lineLength = MSVCRT$strlen(line);
  145. if (lineLength > MAX_PREVIEW_LENGTH) {
  146. MSVCRT$strncpy(preview, line, MAX_PREVIEW_LENGTH);
  147. preview[MAX_PREVIEW_LENGTH] = '\0';
  148. } else {
  149. MSVCRT$strcpy(preview, line);
  150. }
  151. if (firstPrint) {
  152. internal_printf("\n[+] Keyword '%s' found in file: %s\n", keyword, filePath);
  153. firstPrint = false;
  154. }
  155. internal_printf("\t- Matched on pattern: %s\n", preview);
  156. // break; // Uncomment to stop after the first match
  157. }
  158. line = MSVCRT$strtok(NULL, "\n");
  159. }
  160. MSVCRT$free(fileContents);
  161. MSVCRT$free(lowerKeyword);
  162. return found;
  163. }
  164. void SearchFilesRecursive(const char* lpFolder, const char* lpSearchPattern, const char* keyword) {
  165. WIN32_FIND_DATAA findFileData;
  166. HANDLE hFind = INVALID_HANDLE_VALUE;
  167. char szDir[MAX_PATH];
  168. DWORD dwError;
  169. // Build search path for files in the current directory
  170. MSVCRT$strcpy(szDir, lpFolder);
  171. MSVCRT$strcat(szDir, "\\");
  172. MSVCRT$strcat(szDir, lpSearchPattern);
  173. // Search for files
  174. hFind = KERNEL32$FindFirstFileA(szDir, &findFileData);
  175. if (hFind != INVALID_HANDLE_VALUE) {
  176. do {
  177. if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  178. char fullPath[MAX_PATH];
  179. MSVCRT$sprintf(fullPath, "%s\\%s", lpFolder, findFileData.cFileName);
  180. if (*keyword) {
  181. SearchFileForKeyword(fullPath, keyword);
  182. } else if (!*keyword) {
  183. internal_printf("[+] File found: %s\n", fullPath);
  184. }
  185. }
  186. } while (KERNEL32$FindNextFileA(hFind, &findFileData) != 0);
  187. dwError = KERNEL32$GetLastError();
  188. if (dwError != ERROR_NO_MORE_FILES) {
  189. BeaconPrintf(CALLBACK_ERROR, "Error searching for next file: %d\n", dwError);
  190. }
  191. KERNEL32$FindClose(hFind);
  192. }
  193. //search for subdirectories and recurse into them
  194. MSVCRT$strcpy(szDir, lpFolder);
  195. MSVCRT$strcat(szDir, "\\*");
  196. hFind = KERNEL32$FindFirstFileA(szDir, &findFileData);
  197. if (hFind != INVALID_HANDLE_VALUE) {
  198. do {
  199. if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
  200. MSVCRT$strcmp(findFileData.cFileName, ".") != 0 &&
  201. MSVCRT$strcmp(findFileData.cFileName, "..") != 0) {
  202. // Build path for the subdirectory
  203. char subDir[MAX_PATH];
  204. MSVCRT$strcpy(subDir, lpFolder);
  205. MSVCRT$strcat(subDir, "\\");
  206. MSVCRT$strcat(subDir, findFileData.cFileName);
  207. SearchFilesRecursive(subDir, lpSearchPattern, keyword);
  208. }
  209. } while (KERNEL32$FindNextFileA(hFind, &findFileData) != 0);
  210. dwError = KERNEL32$GetLastError();
  211. if (dwError != ERROR_NO_MORE_FILES) {
  212. BeaconPrintf(CALLBACK_ERROR, "Error searching for next file: %d\n", dwError);
  213. }
  214. KERNEL32$FindClose(hFind);
  215. }
  216. }
  217. int go(char *args, int len) {
  218. datap parser;
  219. CHAR *lpDirectory = "";
  220. CHAR *lpSearchPattern = "";
  221. CHAR *keyword = ""; // If not empty, SearchFileForKeyword is called to verify if the keyword is in the text file
  222. BeaconDataParse(&parser, args, len);
  223. lpDirectory = BeaconDataExtract(&parser, NULL);
  224. lpSearchPattern = BeaconDataExtract(&parser, NULL);
  225. keyword = BeaconDataExtract(&parser, NULL);
  226. if(!bofstart()) return;
  227. internal_printf("====================FILE SEARCH RESULTS====================\n");
  228. SearchFilesRecursive(lpDirectory, lpSearchPattern, keyword);
  229. printoutput(TRUE);
  230. BeaconPrintf(CALLBACK_OUTPUT, "[+] Finished searching!\n");
  231. return 0;
  232. }