123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- /* skape <mmiller@hick.org */
- /*
- * dumps all the mapped memory segments in a running process
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <windows.h>
- #define PAGE_SIZE 4096
- typedef struct _MemoryRange
- {
- char *base;
- unsigned long length;
- char *file;
- struct _MemoryRange *next;
- } MemoryRange;
- BOOL createDumpDirectory(char *path);
- DWORD dumpSegments(HANDLE process, const char *dumpDirectory);
- int main(int argc, char **argv)
- {
- char *dumpDirectory = NULL;
- HANDLE process = NULL;
- DWORD pid = 0,
- segments = 0;
- int res = 1;
- do
- {
- // Validate arguments
- if ((argc == 1) ||
- (!(pid = atoi(argv[1]))))
- {
- printf("Usage: %s pid [dump directory]\n", argv[0]);
- break;
- }
- // If a dump directory is specified, use it, otherwise default
- // to the pid.
- if (argc >= 3)
- dumpDirectory = argv[2];
- else
- dumpDirectory = argv[1];
- // Create the dump directory (make sure it exists)
- printf("[*] Creating dump directory...%s\n", dumpDirectory);
- if (!createDumpDirectory(dumpDirectory))
- {
- printf("[-] Creation failed, %.8x.\n", GetLastError());
- break;
- }
- // Attach to the process
- printf("[*] Attaching to %lu...\n", pid);
- if (!(process = OpenProcess(PROCESS_VM_READ, FALSE, pid)))
- {
- printf("[-] Attach failed, %.8x.\n", GetLastError());
- break;
- }
- // Dump segments
- printf("[*] Dumping segments...\n");
- if (!(segments = dumpSegments(process, dumpDirectory)))
- {
- printf("[-] Dump failed, %.8x.\n", GetLastError());
- break;
- }
- printf("[*] Dump completed successfully, %lu segments.\n", segments);
- res = 0;
-
- } while (0);
- if (process)
- CloseHandle(process);
- return res;
- }
- /*
- * Create the directory specified by path, insuring that
- * all parents exist along the way.
- *
- * Just like MakeSureDirectoryPathExists, but portable.
- */
- BOOL createDumpDirectory(char *path)
- {
- char *slash = path;
- BOOL res = TRUE;
- do
- {
- slash = strchr(slash, '\\');
- if (slash)
- *slash = 0;
- if (!CreateDirectory(path, NULL))
- {
- if ((GetLastError() != ERROR_FILE_EXISTS) &&
- (GetLastError() != ERROR_ALREADY_EXISTS))
- {
- res = FALSE;
- break;
- }
- }
- if (slash)
- *slash++ = '\\';
- } while (slash);
- return res;
- }
- /*
- * Dump all mapped segments into the dump directory, one file per
- * each segment. Finally, create an index of all segments.
- */
- DWORD dumpSegments(HANDLE process, const char *dumpDirectory)
- {
- MemoryRange *ranges = NULL,
- *prevRange = NULL,
- *currentRange = NULL;
- char pbuf[PAGE_SIZE],
- rangeFileName[256];
- DWORD segments = 0,
- bytesRead = 0,
- cycles = 0;
- char *current = NULL;
- FILE *rangeFd = NULL;
- // Enumerate page by page
- for (current = 0;
- ;
- current += PAGE_SIZE, cycles++)
- {
- // If we've wrapped, break out.
- if (!current && cycles)
- break;
- // Invalid page? Cool, reset current range.
- if (!ReadProcessMemory(process, current, pbuf,
- sizeof(pbuf), &bytesRead))
- {
- if (currentRange)
- {
- prevRange = currentRange;
- currentRange = NULL;
- }
- if (rangeFd)
- {
- fclose(rangeFd);
- rangeFd = NULL;
- }
- continue;
- }
- // If the current range is not valid, we've hit a new range.
- if (!currentRange)
- {
- // Try to allocate storage for it, if we fail, bust out.
- if (!(currentRange = (MemoryRange *)malloc(sizeof(MemoryRange))))
- {
- printf("[-] Allocation failure\n");
-
- segments = 0;
-
- break;
- }
- currentRange->base = current;
- currentRange->length = 0;
- currentRange->next = NULL;
- if (prevRange)
- prevRange->next = currentRange;
- else
- ranges = currentRange;
- // Finally, open a file for this range
- _snprintf(rangeFileName, sizeof(rangeFileName) - 1, "%s\\%.8x.rng",
- dumpDirectory, current);
- if (!(rangeFd = fopen(rangeFileName, "wb")))
- {
- printf("[-] Could not open range file: %s\n", rangeFileName);
- segments = 0;
- break;
- }
- // Duplicate the file name for ease of access later
- currentRange->file = strdup(rangeFileName);
- // Increment the number of total segments
- segments++;
- }
- // Write to the range file
- fwrite(pbuf, 1, bytesRead, rangeFd);
- currentRange->length += bytesRead;
- }
- // Now that all the ranges are mapped, dump them to an index file
- _snprintf(rangeFileName, sizeof(rangeFileName) - 1, "%s\\index.rng",
- dumpDirectory);
- if ((rangeFd = fopen(rangeFileName, "w")))
- {
- char cwd[MAX_PATH];
- GetCurrentDirectory(sizeof(cwd), cwd);
- // Enumerate all of the ranges, dumping them into the index file
- for (currentRange = ranges;
- currentRange;
- currentRange = currentRange->next)
- {
- fprintf(rangeFd, "%.8x;%lu;%s\\%s\n",
- currentRange->base, currentRange->length, cwd,
- currentRange->file ? currentRange->file : "");
- }
- fclose(rangeFd);
- }
- else
- segments = 0;
-
- return segments;
- }
|