-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmemtool.c
More file actions
289 lines (259 loc) · 9.52 KB
/
Copy pathmemtool.c
File metadata and controls
289 lines (259 loc) · 9.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
// main.c
#include "memtool.h"
#ifdef PLATFORM_WINDOWS
#include <windows.h>
#include <winnt.h>
#include <psapi.h>
#endif
// Platform-specific process open
/**
* @brief Opens a process given its process ID.
*
* This function attempts to open a process associated with the specified process ID.
* It returns a pointer to a ProcessHandle structure if the process is successfully opened;
* otherwise, it returns NULL indicating failure.
*
* @param pid The unique identifier (process_id_t) of the target process.
*
* @return Pointer to the process handle on success, or NULL on failure.
*/
ProcessHandle* open_process(process_id_t pid) {
ProcessHandle* handle = malloc(sizeof(ProcessHandle));
if (!handle) {
perror("Failed to allocate memory for ProcessHandle");
return NULL;
}
#ifdef PLATFORM_WINDOWS // Windows-specific process open
handle->handle = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
FALSE,
pid
);
if (handle->handle == NULL) {
perror("Failed to open process");
free(handle);
return NULL;
}
#else // Linux-specific process open
handle->pid = pid;
char path[64];
snprintf(path, sizeof(path), "/proc/%d/mem", pid);
handle->mem_fd = open(path, O_RDWR);
if (handle->mem_fd == -1) {
perror("Failed to open process memory file");
free(handle);
return NULL;
}
#endif
return handle;
}
// Platform-specific process close
/**
* @brief Closes the process associated with the provided process handle.
*
* This function releases any resources tied to the process and performs
* necessary cleanup. It should be called when the process is no longer needed.
*
* @param handle Pointer to a ProcessHandle structure representing the process to be closed.
*/
void close_process(ProcessHandle* handle) {
if (!handle) return;
#ifdef PLATFORM_WINDOWS
if (handle->handle) CloseHandle(handle->handle);
#else
if (handle->mem_fd != -1) close(handle->mem_fd);
#endif
free(handle);
}
// Read process memory maps
/**
* @brief Reads the memory maps for the specified process.
*
* This function retrieves the memory layout information for a process
* identified by the given process id. It returns a pointer to a ProcessMap
* structure containing the memory map details.
*
* @param pid The unique identifier of the process whose memory maps are to be read.
* @return Pointer to a ProcessMap structure containing the process memory maps,
* or NULL if the operation fails.
*/
ProcessMap* read_process_maps(process_id_t pid) {
// Allocate memory for the process map
ProcessMap* map = malloc(sizeof(ProcessMap));
if (!map) {
perror("Failed to allocate memory for ProcessMap");
return NULL;
}
map->count = 0;
#ifdef PLATFORM_WINDOWS
// Open the target process
HANDLE hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
pid
);
if (hProcess == NULL) {
perror("Failed to open process");
free(map);
return NULL;
}
MEMORY_BASIC_INFORMATION mbi;
PVOID address = 0;
// Enumerate memory regions
while (VirtualQueryEx(hProcess, address, &mbi, sizeof(mbi)) == sizeof(mbi)) {
if (map->count >= MAX_REGIONS) break;
MemoryRegion* region = &map->regions[map->count];
region->BaseAddress = mbi.BaseAddress;
region->RegionSize = mbi.RegionSize;
region->Protection = mbi.Protect;
// Get module name if available
if (GetModuleFileNameExA(hProcess, NULL,
region->pathname, MAX_PATH_LEN) == 0) {
region->pathname[0] = '\0';
}
map->count++;
address = (PVOID)((DWORD_PTR)address + mbi.RegionSize);
}
CloseHandle(hProcess);
#else
char path[64];
snprintf(path, sizeof(path), "/proc/%d/maps", pid);
FILE* maps = fopen(path, "r");
if (!maps) {
perror("Failed to open process maps file");
free(map);
return NULL;
}
char line[1024];
while (fgets(line, sizeof(line), maps) && map->count < MAX_REGIONS) {
MemoryRegion* region = &map->regions[map->count];
// Parse maps line
unsigned long start, end;
char perms[5], pathname[MAX_PATH_LEN];
if (sscanf(line, "%lx-%lx %4s %*s %*s %*s %255s",
&start, &end, perms, pathname) >= 3) {
region->start = start;
region->end = end;
region->size = end - start;
strncpy(region->perms, perms, sizeof(region->perms));
strncpy(region->pathname, pathname, sizeof(region->pathname));
map->count++;
}
}
fclose(maps);
#endif
return map;
}
// Read process memory
size_t read_process_memory(ProcessHandle* handle, void* address,
void* buffer, size_t size) {
#ifdef PLATFORM_WINDOWS
SIZE_T bytes_read = 0;
if (ReadProcessMemory(handle->handle, address, buffer, size, &bytes_read)) {
return bytes_read;
}
return 0;
#else
ssize_t bytes_read = pread(handle->mem_fd, buffer, size, (off_t)address);
return bytes_read > 0 ? bytes_read : 0;
#endif
}
// Write process memory
size_t write_process_memory(ProcessHandle* handle, void* address,
void* buffer, size_t size) {
#ifdef PLATFORM_WINDOWS
SIZE_T bytes_written = 0;
if (WriteProcessMemory(handle->handle, address, buffer, size, &bytes_written)) {
return bytes_written;
}
return 0;
#else
ssize_t bytes_written = pwrite(handle->mem_fd, buffer, size, (off_t)address);
return bytes_written > 0 ? bytes_written : 0;
#endif
}
// Search for pattern in memory region
/**
* @brief Searches for a specific memory pattern within a given memory region.
*
* This function performs a scan of the memory region specified by @c region, using the
* process handle provided by @c handle to access the target process's memory. The search
* logic, which is implemented within this function, identifies occurrences of a particular
* pattern based on predetermined criteria.
*
* @param handle A pointer to the process's handle, used for accessing and manipulating
* the process's memory.
* @param region A pointer to a MemoryRegion structure that describes the memory area to be scanned.
*/
void search_pattern(ProcessHandle* handle, const MemoryRegion* region,
const char* pattern, size_t pattern_len) {
char* buffer = malloc(BUFFER_SIZE);
if (!buffer) return;
#ifdef PLATFORM_WINDOWS
SIZE_T offset = 0;
while (offset < region->RegionSize) {
size_t bytes_read = read_process_memory(handle,
(char*)region->BaseAddress + offset,
buffer, BUFFER_SIZE);
#else
size_t offset = 0;
while (offset < region->size) {
size_t bytes_read = read_process_memory(handle,
(void*)(region->start + offset),
buffer, BUFFER_SIZE);
#endif
if (bytes_read == 0) break;
for (size_t i = 0; i < bytes_read; i++) {
if (i + pattern_len > bytes_read) break;
if (memcmp(buffer + i, pattern, pattern_len) == 0) {
#ifdef PLATFORM_WINDOWS
printf("Pattern found at: %p\n",
(void*)((char*)region->BaseAddress + offset + i));
#else
printf("Pattern found at: 0x%lx\n",
(unsigned long)(region->start + offset + i));
#endif
}
}
offset += bytes_read;
}
free(buffer);
}
/**
* print_memory_map - Prints the memory layout of a process.
*
* This function takes a pointer to a ProcessMap structure, which contains the memory
* mapping information for a process, and outputs details that help visualize the
* process's memory segments. The details typically include segment starting addresses,
* sizes, and possibly permissions or other attributes.
*
* Parameters:
* @map: A constant pointer to a ProcessMap structure representing the process's memory map.
*
* Returns:
* void.
*
* Note:
* Ensure that the provided ProcessMap pointer is not NULL before invoking this function.
*/
void print_memory_map(const ProcessMap* map) {
printf("Memory regions:\n");
for (int i = 0; i < map->count; i++) {
#ifdef PLATFORM_WINDOWS
printf("%p - %p ",
map->regions[i].BaseAddress,
(char*)map->regions[i].BaseAddress + map->regions[i].RegionSize);
if (map->regions[i].Protection & PAGE_EXECUTE) printf("X");
if (map->regions[i].Protection & PAGE_READONLY) printf("R");
if (map->regions[i].Protection & PAGE_READWRITE) printf("W");
#else
printf("0x%lx - 0x%lx %s",
map->regions[i].start,
map->regions[i].end,
map->regions[i].perms);
#endif
if (map->regions[i].pathname[0])
printf(" %s", map->regions[i].pathname);
printf("\n");
}
}