Rizin
unix-like reverse engineering framework and cli tools
windows_maps.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2019 GustavoLCR <gugulcr@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "windows_maps.h"
5 #include "../windows/windows_debug.h"
6 
7 typedef struct {
9  IMAGE_SECTION_HEADER *sect_hdr;
11 } RWinModInfo;
12 
13 static char *get_map_type(MEMORY_BASIC_INFORMATION *mbi) {
14  char *type;
15  switch (mbi->Type) {
16  case MEM_IMAGE:
17  type = "IMAGE";
18  break;
19  case MEM_MAPPED:
20  type = "MAPPED";
21  break;
22  case MEM_PRIVATE:
23  type = "PRIVATE";
24  break;
25  default:
26  type = "UNKNOWN";
27  }
28  return type;
29 }
30 
31 static RzDebugMap *add_map(RzList *list, const char *name, ut64 addr, ut64 len, MEMORY_BASIC_INFORMATION *mbi) {
32  int perm;
33  char *map_type = get_map_type(mbi);
34 
35  switch (mbi->Protect) {
36  case PAGE_EXECUTE:
37  perm = RZ_PERM_X;
38  break;
39  case PAGE_EXECUTE_READ:
40  perm = RZ_PERM_RX;
41  break;
42  case PAGE_EXECUTE_READWRITE:
43  perm = RZ_PERM_RWX;
44  break;
45  case PAGE_READONLY:
46  perm = RZ_PERM_R;
47  break;
48  case PAGE_READWRITE:
49  perm = RZ_PERM_RW;
50  break;
51  case PAGE_WRITECOPY:
52  perm = RZ_PERM_W;
53  break;
54  case PAGE_EXECUTE_WRITECOPY:
55  perm = RZ_PERM_X;
56  break;
57  default:
58  perm = 0;
59  }
60  char *map_name = rz_str_newf("%-8s %s", map_type, name);
61  if (!map_name) {
62  return NULL;
63  }
64  RzDebugMap *mr = rz_debug_map_new(map_name, addr, addr + len, perm, mbi->Type == MEM_PRIVATE);
65  free(map_name);
66  if (mr) {
68  }
69  return mr;
70 }
71 
72 static inline RzDebugMap *add_map_reg(RzList *list, const char *name, MEMORY_BASIC_INFORMATION *mbi) {
73  return add_map(list, name, (ut64)(size_t)mbi->BaseAddress, (ut64)mbi->RegionSize, mbi);
74 }
75 
77  if (dbg->pid == -1) {
78  return NULL;
79  }
80  MODULEENTRY32 me;
82  DWORD flags = TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32;
83  HANDLE h_mod_snap = CreateToolhelp32Snapshot(flags, dbg->pid);
84 
85  if (h_mod_snap == INVALID_HANDLE_VALUE) {
86  // Suppress if process is still initializing
87  if (GetLastError() != ERROR_PARTIAL_COPY || rz_list_length(dbg->threads) > 1) {
88  rz_sys_perror("rz_w32_dbg_modules/CreateToolhelp32Snapshot");
89  }
90  goto err_w32_dbg_modules;
91  }
92  me.dwSize = sizeof(MODULEENTRY32);
93  if (!Module32First(h_mod_snap, &me)) {
94  rz_sys_perror("rz_w32_dbg_modules/Module32First");
95  goto err_w32_dbg_modules;
96  }
97  do {
98  ut64 baddr = (ut64)(size_t)me.modBaseAddr;
99  char *mod_name = rz_sys_conv_win_to_utf8(me.szModule);
100  RzDebugMap *dbgmap = rz_debug_map_new(mod_name, baddr, baddr + me.modBaseSize, 0, 0);
101  free(mod_name);
102  if (dbgmap) {
103  dbgmap->file = rz_sys_conv_win_to_utf8(me.szExePath);
104  if (dbgmap->file) {
105  rz_list_append(list, dbgmap);
106  }
107  }
108  } while (Module32Next(h_mod_snap, &me));
109 err_w32_dbg_modules:
110  if (h_mod_snap && h_mod_snap != INVALID_HANDLE_VALUE) {
111  CloseHandle(h_mod_snap);
112  }
113  return list;
114 }
115 
116 static bool is_pe_hdr(unsigned char *pe_hdr) {
117  IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *)pe_hdr;
118  IMAGE_NT_HEADERS *nt_headers;
119 
120  if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) {
121  nt_headers = (IMAGE_NT_HEADERS *)((char *)dos_header + dos_header->e_lfanew);
122  // TODO: Check boundaries first, before the dereference
123  if (nt_headers->Signature == IMAGE_NT_SIGNATURE)
124  return true;
125  }
126  return false;
127 }
128 
129 static int set_mod_inf(HANDLE h_proc, RzDebugMap *map, RWinModInfo *mod) {
130  IMAGE_DOS_HEADER *dos_hdr;
131  IMAGE_NT_HEADERS *nt_hdrs;
132  IMAGE_NT_HEADERS32 *nt_hdrs32;
133  IMAGE_SECTION_HEADER *sect_hdr;
134  ut8 pe_hdr[0x1000];
135  SIZE_T len;
136  int mod_inf_fill;
137 
138  len = 0;
139  sect_hdr = NULL;
140  mod_inf_fill = -1;
141  ReadProcessMemory(h_proc, (LPCVOID)(size_t)map->addr, (LPVOID)pe_hdr, sizeof(pe_hdr), &len);
142  if (len == (SIZE_T)sizeof(pe_hdr) && is_pe_hdr(pe_hdr)) {
143  dos_hdr = (IMAGE_DOS_HEADER *)pe_hdr;
144  nt_hdrs = (IMAGE_NT_HEADERS *)((char *)dos_hdr + dos_hdr->e_lfanew);
145  if (nt_hdrs->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) { // check for x32 pefile
146  nt_hdrs32 = (IMAGE_NT_HEADERS32 *)((char *)dos_hdr + dos_hdr->e_lfanew);
147  mod->sect_count = nt_hdrs32->FileHeader.NumberOfSections;
148  sect_hdr = (IMAGE_SECTION_HEADER *)((char *)nt_hdrs32 + sizeof(IMAGE_NT_HEADERS32));
149  } else {
150  mod->sect_count = nt_hdrs->FileHeader.NumberOfSections;
151  sect_hdr = (IMAGE_SECTION_HEADER *)((char *)nt_hdrs + sizeof(IMAGE_NT_HEADERS));
152  }
153  if ((char *)sect_hdr + (sizeof(IMAGE_SECTION_HEADER) * mod->sect_count) < ((char *)pe_hdr + sizeof(pe_hdr))) {
154  mod->sect_hdr = (IMAGE_SECTION_HEADER *)malloc(sizeof(IMAGE_SECTION_HEADER) * mod->sect_count);
155  if (mod->sect_hdr) {
156  memcpy(mod->sect_hdr, sect_hdr, sizeof(IMAGE_SECTION_HEADER) * mod->sect_count);
157  mod_inf_fill = 0;
158  } else {
159  perror("malloc set_mod_inf()");
160  }
161  }
162  }
163  if (mod_inf_fill == -1) {
164  RZ_FREE(mod->sect_hdr);
165  }
166  return mod_inf_fill;
167 }
168 
169 static void proc_mem_img(HANDLE h_proc, RzList *map_list, RzList *mod_list, RWinModInfo *mod, SYSTEM_INFO *si, MEMORY_BASIC_INFORMATION *mbi) {
170  ut64 addr = (ut64)(size_t)mbi->BaseAddress;
171  ut64 len = (ut64)mbi->RegionSize;
172  if (!mod->map || addr < mod->map->addr || (addr + len) > mod->map->addr_end) {
173  RzListIter *iter;
174  RzDebugMap *map;
175 
176  free(mod->sect_hdr);
177  memset(mod, 0, sizeof(RWinModInfo));
178  rz_list_foreach (mod_list, iter, map) {
179  if (addr >= map->addr && addr <= map->addr_end) {
180  mod->map = map;
181  set_mod_inf(h_proc, map, mod);
182  break;
183  }
184  }
185  }
186  if (mod->map && mod->sect_hdr && mod->sect_count > 0) {
187  int sect_count;
188  int i, p_mask;
189 
190  sect_count = 0;
191  p_mask = si->dwPageSize - 1;
192  for (i = 0; i < mod->sect_count; i++) {
193  IMAGE_SECTION_HEADER *sect_hdr = &mod->sect_hdr[i];
194  ut64 sect_addr = mod->map->addr + (ut64)sect_hdr->VirtualAddress;
195  ut64 sect_len = (((ut64)sect_hdr->Misc.VirtualSize) + p_mask) & ~p_mask;
196  int sect_found = 0;
197 
198  /* section in memory region? */
199  if (sect_addr >= addr && (sect_addr + sect_len) <= (addr + len)) {
200  sect_found = 1;
201  /* memory region in section? */
202  } else if (addr >= sect_addr && (addr + len) <= (sect_addr + sect_len)) {
203  sect_found = 2;
204  }
205  if (sect_found) {
206  char *map_name = rz_str_newf("%s | %.8s", mod->map->name, sect_hdr->Name);
207  if (!map_name) {
208  perror("rz_str_newf");
209  return;
210  }
211  if (sect_found == 1) {
212  add_map(map_list, map_name, sect_addr, sect_len, mbi);
213  } else {
214  add_map_reg(map_list, map_name, mbi);
215  }
216  free(map_name);
217  sect_count++;
218  }
219  }
220  if (sect_count == 0) {
221  add_map_reg(map_list, mod->map->name, mbi);
222  }
223  } else {
224  if (!mod->map) {
225  add_map_reg(map_list, "", mbi);
226  } else {
227  add_map_reg(map_list, mod->map->name, mbi);
228  }
229  }
230 }
231 
232 static void proc_mem_map(HANDLE h_proc, RzList *map_list, MEMORY_BASIC_INFORMATION *mbi) {
233  WCHAR f_name[MAX_PATH + 1];
234 
235  DWORD len = GetMappedFileNameW(h_proc, mbi->BaseAddress, f_name, MAX_PATH);
236  if (len > 0) {
237  char *f_name_ = rz_utf16_to_utf8(f_name);
238  add_map_reg(map_list, f_name_, mbi);
239  free(f_name_);
240  } else {
241  add_map_reg(map_list, "", mbi);
242  }
243 }
244 
246  if (dbg->pid == -1) {
247  return NULL;
248  }
249  SYSTEM_INFO si = { 0 };
250  LPVOID cur_addr;
251  MEMORY_BASIC_INFORMATION mbi;
252  RWinModInfo mod_inf = { 0 };
253  RzList *map_list = rz_list_newf((RzListFree)rz_debug_map_free), *mod_list = NULL;
254  W32DbgWInst *wrap = dbg->plugin_data;
255 
256  GetSystemInfo(&si);
257  cur_addr = si.lpMinimumApplicationAddress;
258  /* get process modules list */
259  mod_list = rz_w32_dbg_modules(dbg);
260  /* process memory map */
261  while (cur_addr < si.lpMaximumApplicationAddress &&
262  VirtualQueryEx(wrap->pi.hProcess, cur_addr, &mbi, sizeof(mbi)) != 0) {
263  if (mbi.State != MEM_FREE) {
264  switch (mbi.Type) {
265  case MEM_IMAGE:
266  proc_mem_img(wrap->pi.hProcess, map_list, mod_list, &mod_inf, &si, &mbi);
267  break;
268  case MEM_MAPPED:
269  proc_mem_map(wrap->pi.hProcess, map_list, &mbi);
270  break;
271  default:
272  add_map_reg(map_list, "", &mbi);
273  }
274  }
275  cur_addr = (LPVOID)(size_t)((ut64)(size_t)mbi.BaseAddress + mbi.RegionSize);
276  }
277  free(mod_inf.sect_hdr);
278  rz_list_free(mod_list);
279  return map_list;
280 }
size_t len
Definition: 6502dis.c:15
map_type
Definition: aarch64-dis.c:40
si
lzma_index ** i
Definition: index.h:629
static ut64 baddr(RzBinFile *bf)
Definition: bin_any.c:58
static int mr(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len)
Definition: cmd_analysis.c:471
#define RZ_API
#define NULL
Definition: cris-opc.c:27
int mod(int a, int b)
Definition: crypto_rot.c:8
RzDebug * dbg
Definition: desil.c:30
RZ_API void rz_debug_map_free(RzDebugMap *map)
Definition: dmap.c:77
RZ_API RzDebugMap * rz_debug_map_new(char *name, ut64 addr, ut64 addr_end, int perm, int user)
Definition: dmap.c:7
size_t map(int syms, int left, int len)
Definition: enough.c:237
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
#define INVALID_HANDLE_VALUE
Definition: iowin32.c:21
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * malloc(size_t size)
Definition: malloc.c:123
int type
Definition: mipsasm.c:17
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define rz_sys_perror(x)
Definition: rz_types.h:336
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_PERM_RW
Definition: rz_types.h:96
#define RZ_PERM_W
Definition: rz_types.h:94
#define RZ_PERM_X
Definition: rz_types.h:95
#define RZ_PERM_RX
Definition: rz_types.h:97
#define RZ_PERM_RWX
Definition: rz_types.h:98
#define RZ_FREE(x)
Definition: rz_types.h:369
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
IMAGE_SECTION_HEADER * sect_hdr
Definition: windows_maps.c:9
RzDebugMap * map
Definition: windows_maps.c:8
PROCESS_INFORMATION pi
Definition: w32dbg_wrap.h:40
Definition: z80asm.h:102
char * file
Definition: rz_debug.h:142
RzList * threads
Definition: rz_debug.h:251
void * plugin_data
Definition: rz_debug.h:296
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
DWORD * HANDLE
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
DWORD
static char * get_map_type(MEMORY_BASIC_INFORMATION *mbi)
Definition: windows_maps.c:13
static RzDebugMap * add_map_reg(RzList *list, const char *name, MEMORY_BASIC_INFORMATION *mbi)
Definition: windows_maps.c:72
static void proc_mem_img(HANDLE h_proc, RzList *map_list, RzList *mod_list, RWinModInfo *mod, SYSTEM_INFO *si, MEMORY_BASIC_INFORMATION *mbi)
Definition: windows_maps.c:169
RZ_API RzList * rz_w32_dbg_maps(RzDebug *dbg)
Definition: windows_maps.c:245
RZ_API RzList * rz_w32_dbg_modules(RzDebug *dbg)
Definition: windows_maps.c:76
static int set_mod_inf(HANDLE h_proc, RzDebugMap *map, RWinModInfo *mod)
Definition: windows_maps.c:129
static void proc_mem_map(HANDLE h_proc, RzList *map_list, MEMORY_BASIC_INFORMATION *mbi)
Definition: windows_maps.c:232
static bool is_pe_hdr(unsigned char *pe_hdr)
Definition: windows_maps.c:116
static RzDebugMap * add_map(RzList *list, const char *name, ut64 addr, ut64 len, MEMORY_BASIC_INFORMATION *mbi)
Definition: windows_maps.c:31
static int addr
Definition: z80asm.c:58