CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

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