-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Importing memdump from the msf2 source
git-svn-id: file:///home/svn/framework3/trunk@4279 4d416f70-5f16-0410-b530-b9f4589650da
- Loading branch information
HD Moore
committed
Jan 17, 2007
1 parent
4d2e6eb
commit 1e64a64
Showing
3 changed files
with
251 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
This is the README file for memdump.exe. Memdump was written by | ||
Matt Miller <mmiller[at]hick.org> and is used to dump the entire | ||
memory of a running process. The directory created by memdump | ||
can be used with msfpescan to quickly find viable instructions | ||
and return addresses. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
/* 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; | ||
} |
Binary file not shown.