memdump.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /* skape <mmiller@hick.org */
  2. /*
  3. * dumps all the mapped memory segments in a running process
  4. */
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <windows.h>
  8. #define PAGE_SIZE 4096
  9. typedef struct _MemoryRange
  10. {
  11. char *base;
  12. unsigned long length;
  13. char *file;
  14. struct _MemoryRange *next;
  15. } MemoryRange;
  16. BOOL createDumpDirectory(char *path);
  17. DWORD dumpSegments(HANDLE process, const char *dumpDirectory);
  18. int main(int argc, char **argv)
  19. {
  20. char *dumpDirectory = NULL;
  21. HANDLE process = NULL;
  22. DWORD pid = 0,
  23. segments = 0;
  24. int res = 1;
  25. do
  26. {
  27. // Validate arguments
  28. if ((argc == 1) ||
  29. (!(pid = atoi(argv[1]))))
  30. {
  31. printf("Usage: %s pid [dump directory]\n", argv[0]);
  32. break;
  33. }
  34. // If a dump directory is specified, use it, otherwise default
  35. // to the pid.
  36. if (argc >= 3)
  37. dumpDirectory = argv[2];
  38. else
  39. dumpDirectory = argv[1];
  40. // Create the dump directory (make sure it exists)
  41. printf("[*] Creating dump directory...%s\n", dumpDirectory);
  42. if (!createDumpDirectory(dumpDirectory))
  43. {
  44. printf("[-] Creation failed, %.8x.\n", GetLastError());
  45. break;
  46. }
  47. // Attach to the process
  48. printf("[*] Attaching to %lu...\n", pid);
  49. if (!(process = OpenProcess(PROCESS_VM_READ, FALSE, pid)))
  50. {
  51. printf("[-] Attach failed, %.8x.\n", GetLastError());
  52. break;
  53. }
  54. // Dump segments
  55. printf("[*] Dumping segments...\n");
  56. if (!(segments = dumpSegments(process, dumpDirectory)))
  57. {
  58. printf("[-] Dump failed, %.8x.\n", GetLastError());
  59. break;
  60. }
  61. printf("[*] Dump completed successfully, %lu segments.\n", segments);
  62. res = 0;
  63. } while (0);
  64. if (process)
  65. CloseHandle(process);
  66. return res;
  67. }
  68. /*
  69. * Create the directory specified by path, insuring that
  70. * all parents exist along the way.
  71. *
  72. * Just like MakeSureDirectoryPathExists, but portable.
  73. */
  74. BOOL createDumpDirectory(char *path)
  75. {
  76. char *slash = path;
  77. BOOL res = TRUE;
  78. do
  79. {
  80. slash = strchr(slash, '\\');
  81. if (slash)
  82. *slash = 0;
  83. if (!CreateDirectory(path, NULL))
  84. {
  85. if ((GetLastError() != ERROR_FILE_EXISTS) &&
  86. (GetLastError() != ERROR_ALREADY_EXISTS))
  87. {
  88. res = FALSE;
  89. break;
  90. }
  91. }
  92. if (slash)
  93. *slash++ = '\\';
  94. } while (slash);
  95. return res;
  96. }
  97. /*
  98. * Dump all mapped segments into the dump directory, one file per
  99. * each segment. Finally, create an index of all segments.
  100. */
  101. DWORD dumpSegments(HANDLE process, const char *dumpDirectory)
  102. {
  103. MemoryRange *ranges = NULL,
  104. *prevRange = NULL,
  105. *currentRange = NULL;
  106. char pbuf[PAGE_SIZE],
  107. rangeFileName[256];
  108. DWORD segments = 0,
  109. bytesRead = 0,
  110. cycles = 0;
  111. char *current = NULL;
  112. FILE *rangeFd = NULL;
  113. // Enumerate page by page
  114. for (current = 0;
  115. ;
  116. current += PAGE_SIZE, cycles++)
  117. {
  118. // If we've wrapped, break out.
  119. if (!current && cycles)
  120. break;
  121. // Invalid page? Cool, reset current range.
  122. if (!ReadProcessMemory(process, current, pbuf,
  123. sizeof(pbuf), &bytesRead))
  124. {
  125. if (currentRange)
  126. {
  127. prevRange = currentRange;
  128. currentRange = NULL;
  129. }
  130. if (rangeFd)
  131. {
  132. fclose(rangeFd);
  133. rangeFd = NULL;
  134. }
  135. continue;
  136. }
  137. // If the current range is not valid, we've hit a new range.
  138. if (!currentRange)
  139. {
  140. // Try to allocate storage for it, if we fail, bust out.
  141. if (!(currentRange = (MemoryRange *)malloc(sizeof(MemoryRange))))
  142. {
  143. printf("[-] Allocation failure\n");
  144. segments = 0;
  145. break;
  146. }
  147. currentRange->base = current;
  148. currentRange->length = 0;
  149. currentRange->next = NULL;
  150. if (prevRange)
  151. prevRange->next = currentRange;
  152. else
  153. ranges = currentRange;
  154. // Finally, open a file for this range
  155. _snprintf(rangeFileName, sizeof(rangeFileName) - 1, "%s\\%.8x.rng",
  156. dumpDirectory, current);
  157. if (!(rangeFd = fopen(rangeFileName, "wb")))
  158. {
  159. printf("[-] Could not open range file: %s\n", rangeFileName);
  160. segments = 0;
  161. break;
  162. }
  163. // Duplicate the file name for ease of access later
  164. currentRange->file = strdup(rangeFileName);
  165. // Increment the number of total segments
  166. segments++;
  167. }
  168. // Write to the range file
  169. fwrite(pbuf, 1, bytesRead, rangeFd);
  170. currentRange->length += bytesRead;
  171. }
  172. // Now that all the ranges are mapped, dump them to an index file
  173. _snprintf(rangeFileName, sizeof(rangeFileName) - 1, "%s\\index.rng",
  174. dumpDirectory);
  175. if ((rangeFd = fopen(rangeFileName, "w")))
  176. {
  177. char cwd[MAX_PATH];
  178. GetCurrentDirectory(sizeof(cwd), cwd);
  179. // Enumerate all of the ranges, dumping them into the index file
  180. for (currentRange = ranges;
  181. currentRange;
  182. currentRange = currentRange->next)
  183. {
  184. fprintf(rangeFd, "%.8x;%lu;%s\\%s\n",
  185. currentRange->base, currentRange->length, cwd,
  186. currentRange->file ? currentRange->file : "");
  187. }
  188. fclose(rangeFd);
  189. }
  190. else
  191. segments = 0;
  192. return segments;
  193. }