1 /*
2
3 Copyright(c) 2010. Victor M. Alvarez [plusvic@gmail.com] &
4 Stefan Buehlmann [stefan.buehlmann@joebox.org].
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 */
17
18
19
20 #ifdef WIN32
21
22 #include <windows.h>
23 #include "mem.h"
24 #include "proc.h"
25
get_process_memory(int pid,MEMORY_BLOCK ** first_block)26 int get_process_memory(int pid, MEMORY_BLOCK** first_block)
27 {
28 PVOID address;
29 SIZE_T read;
30
31 unsigned char* data;
32
33 SYSTEM_INFO si;
34 MEMORY_BASIC_INFORMATION mbi;
35
36 MEMORY_BLOCK* new_block;
37 MEMORY_BLOCK* current_block = NULL;
38
39 TOKEN_PRIVILEGES tokenPriv;
40 LUID luidDebug;
41 HANDLE hProcess;
42 HANDLE hToken;
43
44 if( OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) &&
45 LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug))
46 {
47 tokenPriv.PrivilegeCount = 1;
48 tokenPriv.Privileges[0].Luid = luidDebug;
49 tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
50
51 AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(tokenPriv), NULL, NULL);
52 }
53
54 hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid);
55
56 *first_block = NULL;
57
58 if (hProcess == NULL)
59 {
60 return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
61 }
62
63 GetSystemInfo(&si);
64
65 address = si.lpMinimumApplicationAddress;
66
67 while (address < si.lpMaximumApplicationAddress)
68 {
69 if (VirtualQueryEx(hProcess, address, &mbi, sizeof(mbi)) != 0)
70 {
71 if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS)
72 {
73 data = (unsigned char*) yr_malloc(mbi.RegionSize);
74
75 if (data == NULL)
76 return ERROR_INSUFICIENT_MEMORY;
77
78 if (ReadProcessMemory(hProcess, address, data, mbi.RegionSize, &read))
79 {
80 new_block = (MEMORY_BLOCK*) yr_malloc(sizeof(MEMORY_BLOCK));
81
82 if (new_block == NULL)
83 {
84 yr_free(data);
85 return ERROR_INSUFICIENT_MEMORY;
86 }
87
88 if (*first_block == NULL)
89 *first_block = new_block;
90
91 new_block->base = (size_t) mbi.BaseAddress;
92 new_block->size = mbi.RegionSize;
93 new_block->data = data;
94 new_block->next = NULL;
95
96 if (current_block != NULL)
97 current_block->next = new_block;
98
99 current_block = new_block;
100 }
101 else
102 {
103 yr_free(data);
104 }
105 }
106
107 address = (PVOID)((DWORD) mbi.BaseAddress + mbi.RegionSize);
108 }
109 }
110
111 return ERROR_SUCCESS;
112 }
113
114 #else
115
116 #include <fcntl.h>
117 #include <unistd.h>
118 #include <sys/types.h>
119 #include <sys/ptrace.h>
120 #include <sys/wait.h>
121
122 #include "mem.h"
123 #include "proc.h"
124
125 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__MACH__)
126 #define PTRACE_ATTACH PT_ATTACH
127 #define PTRACE_DETACH PT_DETACH
128 #endif
129
130 #if defined(__MACH__)
131
132 #include <mach/mach.h>
133 #include <mach/mach_vm.h>
134 #include <mach/vm_region.h>
135 #include <mach/vm_statistics.h>
136
get_process_memory(pid_t pid,MEMORY_BLOCK ** first_block)137 int get_process_memory(pid_t pid, MEMORY_BLOCK** first_block)
138 {
139 task_t task;
140 kern_return_t kr;
141
142 vm_size_t size = 0;
143 vm_address_t address = 0;
144 vm_region_basic_info_data_64_t info;
145 mach_msg_type_number_t info_count;
146 mach_port_t object;
147
148 unsigned char* data;
149
150 MEMORY_BLOCK* new_block;
151 MEMORY_BLOCK* current_block = NULL;
152
153 *first_block = NULL;
154
155 if ((kr = task_for_pid(mach_task_self(), pid, &task)) != KERN_SUCCESS)
156 {
157 return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
158 }
159
160 do {
161
162 info_count = VM_REGION_BASIC_INFO_COUNT_64;
163
164 kr = vm_region_64(task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t) &info, &info_count, &object);
165
166 if (kr == KERN_SUCCESS)
167 {
168 data = (unsigned char*) yr_malloc(size);
169
170 if (data == NULL)
171 return ERROR_INSUFICIENT_MEMORY;
172
173 if (vm_read_overwrite(task, address, size, (vm_address_t) data, &size) == KERN_SUCCESS)
174 {
175 new_block = (MEMORY_BLOCK*) yr_malloc(sizeof(MEMORY_BLOCK));
176
177 if (new_block == NULL)
178 {
179 yr_free(data);
180 return ERROR_INSUFICIENT_MEMORY;
181 }
182
183 if (*first_block == NULL)
184 *first_block = new_block;
185
186 new_block->base = address;
187 new_block->size = size;
188 new_block->data = data;
189 new_block->next = NULL;
190
191 if (current_block != NULL)
192 current_block->next = new_block;
193
194 current_block = new_block;
195 }
196
197 address += size;
198 }
199
200
201 } while (kr != KERN_INVALID_ADDRESS);
202
203 if (task != MACH_PORT_NULL)
204 {
205 mach_port_deallocate(mach_task_self(), task);
206 }
207
208 return ERROR_SUCCESS;
209 }
210
211 #else
212
213 #include <errno.h>
214
get_process_memory(pid_t pid,MEMORY_BLOCK ** first_block)215 int get_process_memory(pid_t pid, MEMORY_BLOCK** first_block)
216 {
217 char buffer[256];
218 unsigned char* data;
219 size_t begin, end, length;
220
221 MEMORY_BLOCK* new_block;
222 MEMORY_BLOCK* current_block = NULL;
223
224 *first_block = NULL;
225
226 sprintf(buffer, "/proc/%u/maps", pid);
227
228 FILE* maps = fopen(buffer, "r");
229
230 if (maps == NULL)
231 {
232 return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
233 }
234
235 sprintf(buffer, "/proc/%u/mem", pid);
236
237 int mem = open(buffer, O_RDONLY);
238
239 if (mem == -1)
240 {
241 fclose(maps);
242 return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
243 }
244
245 if (ptrace(PTRACE_ATTACH, pid, NULL, 0) == -1)
246 {
247 return ERROR_COULD_NOT_ATTACH_TO_PROCESS;
248 }
249
250 wait(NULL);
251
252 while (fgets(buffer, sizeof(buffer), maps) != NULL)
253 {
254 sscanf(buffer, "%lx-%lx", &begin, &end);
255
256 length = end - begin;
257
258 data = yr_malloc(length);
259
260 if (data == NULL)
261 return ERROR_INSUFICIENT_MEMORY;
262
263 if (pread(mem, data, length, begin) != -1)
264 {
265 new_block = (MEMORY_BLOCK*) yr_malloc(sizeof(MEMORY_BLOCK));
266
267 if (new_block == NULL)
268 {
269 yr_free(data);
270 return ERROR_INSUFICIENT_MEMORY;
271 }
272
273 if (*first_block == NULL)
274 *first_block = new_block;
275
276 new_block->base = begin;
277 new_block->size = length;
278 new_block->data = data;
279 new_block->next = NULL;
280
281 if (current_block != NULL)
282 current_block->next = new_block;
283
284 current_block = new_block;
285 }
286 }
287
288 ptrace(PTRACE_DETACH, pid, NULL, 0);
289
290 close(mem);
291 fclose(maps);
292
293 return ERROR_SUCCESS;
294 }
295
296 #endif
297 #endif
298
299