Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/tools/memdump/memdump.c
Views: 11767
/* skape <[email protected] */12/*3* dumps all the mapped memory segments in a running process4*/5#include <stdlib.h>6#include <stdio.h>7#include <windows.h>89#define PAGE_SIZE 40961011typedef struct _MemoryRange12{1314char *base;15unsigned long length;16char *file;17struct _MemoryRange *next;1819} MemoryRange;2021BOOL createDumpDirectory(char *path);22DWORD dumpSegments(HANDLE process, const char *dumpDirectory);2324int main(int argc, char **argv)25{26char *dumpDirectory = NULL;27HANDLE process = NULL;28DWORD pid = 0,29segments = 0;30int res = 1;3132do33{34// Validate arguments35if ((argc == 1) ||36(!(pid = atoi(argv[1]))))37{38printf("Usage: %s pid [dump directory]\n", argv[0]);39break;40}4142// If a dump directory is specified, use it, otherwise default43// to the pid.44if (argc >= 3)45dumpDirectory = argv[2];46else47dumpDirectory = argv[1];4849// Create the dump directory (make sure it exists)50printf("[*] Creating dump directory...%s\n", dumpDirectory);5152if (!createDumpDirectory(dumpDirectory))53{54printf("[-] Creation failed, %.8x.\n", GetLastError());55break;56}5758// Attach to the process59printf("[*] Attaching to %lu...\n", pid);6061if (!(process = OpenProcess(PROCESS_VM_READ, FALSE, pid)))62{63printf("[-] Attach failed, %.8x.\n", GetLastError());64break;65}6667// Dump segments68printf("[*] Dumping segments...\n");6970if (!(segments = dumpSegments(process, dumpDirectory)))71{72printf("[-] Dump failed, %.8x.\n", GetLastError());73break;74}7576printf("[*] Dump completed successfully, %lu segments.\n", segments);7778res = 0;7980} while (0);8182if (process)83CloseHandle(process);8485return res;86}8788/*89* Create the directory specified by path, insuring that90* all parents exist along the way.91*92* Just like MakeSureDirectoryPathExists, but portable.93*/94BOOL createDumpDirectory(char *path)95{96char *slash = path;97BOOL res = TRUE;9899do100{101slash = strchr(slash, '\\');102103if (slash)104*slash = 0;105106if (!CreateDirectory(path, NULL))107{108if ((GetLastError() != ERROR_FILE_EXISTS) &&109(GetLastError() != ERROR_ALREADY_EXISTS))110{111res = FALSE;112break;113}114}115116if (slash)117*slash++ = '\\';118119} while (slash);120121return res;122}123124/*125* Dump all mapped segments into the dump directory, one file per126* each segment. Finally, create an index of all segments.127*/128DWORD dumpSegments(HANDLE process, const char *dumpDirectory)129{130MemoryRange *ranges = NULL,131*prevRange = NULL,132*currentRange = NULL;133char pbuf[PAGE_SIZE],134rangeFileName[256];135DWORD segments = 0,136bytesRead = 0,137cycles = 0;138char *current = NULL;139FILE *rangeFd = NULL;140141// Enumerate page by page142for (current = 0;143;144current += PAGE_SIZE, cycles++)145146{147// If we've wrapped, break out.148if (!current && cycles)149break;150151// Invalid page? Cool, reset current range.152if (!ReadProcessMemory(process, current, pbuf,153sizeof(pbuf), &bytesRead))154{155if (currentRange)156{157prevRange = currentRange;158currentRange = NULL;159}160161if (rangeFd)162{163fclose(rangeFd);164165rangeFd = NULL;166}167168continue;169}170171// If the current range is not valid, we've hit a new range.172if (!currentRange)173{174// Try to allocate storage for it, if we fail, bust out.175if (!(currentRange = (MemoryRange *)malloc(sizeof(MemoryRange))))176{177printf("[-] Allocation failure\n");178179segments = 0;180181break;182}183184currentRange->base = current;185currentRange->length = 0;186currentRange->next = NULL;187188if (prevRange)189prevRange->next = currentRange;190else191ranges = currentRange;192193// Finally, open a file for this range194_snprintf(rangeFileName, sizeof(rangeFileName) - 1, "%s\\%.8x.rng",195dumpDirectory, current);196197if (!(rangeFd = fopen(rangeFileName, "wb")))198{199printf("[-] Could not open range file: %s\n", rangeFileName);200201segments = 0;202203break;204}205206// Duplicate the file name for ease of access later207currentRange->file = strdup(rangeFileName);208209// Increment the number of total segments210segments++;211}212213// Write to the range file214fwrite(pbuf, 1, bytesRead, rangeFd);215216currentRange->length += bytesRead;217}218219// Now that all the ranges are mapped, dump them to an index file220_snprintf(rangeFileName, sizeof(rangeFileName) - 1, "%s\\index.rng",221dumpDirectory);222223if ((rangeFd = fopen(rangeFileName, "w")))224{225char cwd[MAX_PATH];226227GetCurrentDirectory(sizeof(cwd), cwd);228229// Enumerate all of the ranges, dumping them into the index file230for (currentRange = ranges;231currentRange;232currentRange = currentRange->next)233{234fprintf(rangeFd, "%.8x;%lu;%s\\%s\n",235currentRange->base, currentRange->length, cwd,236currentRange->file ? currentRange->file : "");237}238239fclose(rangeFd);240}241else242segments = 0;243244return segments;245}246247248