Rizin
unix-like reverse engineering framework and cli tools
darwin.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2015 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #if __APPLE__
5 
6 kern_return_t mach_vm_region_recurse(
7  vm_map_t target_task,
8  mach_vm_address_t *address,
9  mach_vm_size_t *size,
10  natural_t *nesting_depth,
11  vm_region_recurse_info_t info,
12  mach_msg_type_number_t *infoCnt);
13 
14 static const char *unparse_inheritance(vm_inherit_t i) {
15  switch (i) {
16  case VM_INHERIT_SHARE: return "share";
17  case VM_INHERIT_COPY: return "copy";
18  case VM_INHERIT_NONE: return "none";
19  default: return "???";
20  }
21 }
22 
23 #if __LP64__
24 #define ADDR "%16lx"
25 #define HEADER_SIZE 0x1000
26 #define IMAGE_OFFSET 0x2000
27 #define KERNEL_LOWER 0xffffff8000000000
28 #else
29 #define ADDR "%8x"
30 #define HEADER_SIZE 0x1000
31 #define IMAGE_OFFSET 0x201000
32 #define KERNEL_LOWER 0x80000000
33 #endif
34 
35 vm_address_t get_kernel_base(task_t ___task) {
36  kern_return_t ret;
37  task_t task;
38  vm_region_submap_info_data_64_t info;
39  ut64 size;
40  mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
41  unsigned int depth = 0;
42  ut64 addr = KERNEL_LOWER; // lowest possible kernel base address
43  int count;
44 
45  ret = task_for_pid(mach_task_self(), 0, &task);
46  if (ret != KERN_SUCCESS)
47  return 0;
48  ut64 naddr;
49  eprintf("%d vs %d\n", task, ___task);
50  for (count = 128; count; count--) {
51  // get next memory region
52  naddr = addr;
53  ret = vm_region_recurse_64(task, (vm_address_t *)&naddr, (vm_size_t *)&size,
54  &depth, (vm_region_info_t)&info, &info_count);
55  if (ret != KERN_SUCCESS)
56  break;
57  if (size < 1)
58  break;
59  if (addr == naddr) {
60  addr += size;
61  continue;
62  }
63  eprintf("0x%08" PFMT64x " size 0x%08" PFMT64x " perm 0x%x\n", (ut64)addr, (ut64)size, info.max_protection);
64  // the kernel maps over a GB of RAM at the address where it maps
65  // itself so we use that fact to detect it's position
66  if (size > 1024 * 1024 * 1024) {
67  return addr + IMAGE_OFFSET;
68  }
69  addr += size;
70  }
71  return (vm_address_t)0;
72 }
73 
74 extern int proc_regionfilename(int pid, uint64_t address, void *buffer, uint32_t buffersize);
75 
76 static RzList *ios_dbg_maps(RzDebug *dbg) {
77  bool contiguous = false;
78  ut32 oldprot = UT32_MAX;
79  char buf[1024];
80  mach_vm_address_t address = MACH_VM_MIN_ADDRESS;
81  mach_vm_size_t size = (mach_vm_size_t)0;
82  mach_vm_size_t osize = (mach_vm_size_t)0;
83  natural_t depth = 0;
84  task_t task = pid_to_task(dbg->tid);
85  RzDebugMap *mr = NULL;
86  RzList *list = NULL;
87  int i = 0;
88 #if __arm64__ || __aarch64__
89  size = osize = 16384; // according to frida
90 #else
91  size = osize = 4096;
92 #endif
93 #if 0
94  if (dbg->pid == 0) {
95  vm_address_t base = get_kernel_base (task);
96  eprintf ("Kernel Base Address: 0x%"PFMT64x"\n", (ut64)base);
97  return NULL;
98  }
99 #endif
100 
101  kern_return_t kr;
102  for (;;) {
103  struct vm_region_submap_info_64 info;
104  mach_msg_type_number_t info_count;
105 
106  depth = VM_REGION_BASIC_INFO_64;
107  info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
108  memset(&info, 0, sizeof(info));
109  kr = mach_vm_region_recurse(task, &address, &size, &depth,
110  (vm_region_recurse_info_t)&info, &info_count);
111  if (kr != KERN_SUCCESS) {
112  // eprintf ("Cannot kern succ recurse\n");
113  break;
114  }
115  if (!list) {
116  list = rz_list_new();
117  // list->free = (RzListFree*)rz_debug_map_free;
118  }
119  if (mr) {
120  if (address == mr->addr + mr->size) {
121  if (oldprot != UT32_MAX && oldprot == info.protection) {
122  /* expand region */
123  mr->size += size;
124  contiguous = true;
125  } else {
126  contiguous = false;
127  }
128  } else {
129  contiguous = false;
130  }
131  } else
132  contiguous = false;
133  oldprot = info.protection;
134  if (info.max_protection != 0 && !contiguous) {
135  char module_name[1024];
136  module_name[0] = 0;
137 #ifndef __POWERPC__
138  int ret = proc_regionfilename(dbg->pid, address,
139  module_name, sizeof(module_name));
140 #else
141 #warning TODO: support proc_regionfilename on old OSX (ppc)
142  int ret = 0;
143 #endif
144  module_name[ret] = 0;
145 #define xwrz_testwx(x) ((x & 1) << 2) | (x & 2) | ((x & 4) >> 2)
146  // XXX: if its shared, it cannot be read?
147  snprintf(buf, sizeof(buf), "%s %02x %s%s%s%s%s %s depth=%d",
148  rz_str_rwx_i(xwrz_testwx(info.max_protection)), i,
149  unparse_inheritance(info.inheritance),
150  info.user_tag ? " user" : "",
151  info.is_submap ? " sub" : "",
152  info.inheritance ? " inherit" : "",
153  info.is_submap ? " submap" : "",
154  module_name, depth);
155  // info.shared ? "shar" : "priv",
156  // info.reserved ? "reserved" : "not-reserved",
157  //""); //module_name);
158  mr = rz_debug_map_new(buf, address, address + size,
159  xwrz_testwx(info.protection), 0);
160  if (!mr) {
161  eprintf("Cannot create rz_debug_map_new\n");
162  break;
163  }
164  mr->file = strdup(module_name);
165  i++;
167  }
168  if (size < 1)
169  size = osize;
170  address += size;
171  size = 0;
172  }
173  return list;
174 }
175 
176 #if 0
177 // TODO: this loop MUST be cleaned up
178 static RzList *osx_dbg_maps (RzDebug *dbg) {
179  RzDebugMap *mr;
180  char buf[1024];
181  int i, print;
182  kern_return_t kret;
183  vm_region_basic_info_data_64_t info, prev_info;
184  mach_vm_address_t prev_address;
185  mach_vm_size_t size, prev_size;
186  mach_port_t object_name;
187  mach_msg_type_number_t count;
188  int nsubregions = 0;
189  int num_printed = 0;
190  size_t address = 0;
191  task_t task = pid_to_task (dbg->pid);
192  RzList *list = rz_list_new ();
193  // XXX: wrong for 64bits
194 /*
195  count = VM_REGION_BASIC_INFO_COUNT_64;
196  kret = mach_vm_region (pid_to_task (dbg->pid), &address, &size, VM_REGION_BASIC_INFO_64,
197  (vm_region_info_t) &info, &count, &object_name);
198  if (kret != KERN_SUCCESS) {
199  printf("No memory regions.\n");
200  return;
201  }
202  memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
203 */
204 #if __arm64__ || __aarch64__
205  size = 16384; // according to frida
206 #else
207  size = 4096;
208 #endif
209  memset (&prev_info, 0, sizeof (prev_info));
210  prev_address = address;
211  prev_size = size;
212  nsubregions = 1;
213 
214  for (i=0; ; i++) {
215  int done = 0;
216 
217  address = prev_address + prev_size;
218  print = 0;
219 
220  if (prev_size==0)
221  break;
222  /* Check to see if address space has wrapped around. */
223  if (address == 0)
224  done = 1;
225 
226  if (!done) {
227  count = VM_REGION_BASIC_INFO_COUNT_64;
228  kret = mach_vm_region (task, (mach_vm_address_t *)&address,
229  &size, VM_REGION_BASIC_INFO_64,
230  (vm_region_info_t) &info, &count, &object_name);
231  if (kret != KERN_SUCCESS) {
232  size = 0;
233  print = done = 1;
234  }
235  }
236 
237  if (address != prev_address + prev_size)
238  print = 1;
239 
240  if ((info.protection != prev_info.protection)
241  || (info.max_protection != prev_info.max_protection)
242  || (info.inheritance != prev_info.inheritance)
243  || (info.shared != prev_info.reserved)
244  || (info.reserved != prev_info.reserved))
245  print = 1;
246 
247 //#if __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
248  {
249  char module_name[1024];
250  module_name[0] = 0;
251  int ret = proc_regionfilename (dbg->pid, address, module_name, sizeof (module_name));
252  module_name[ret] = 0;
253 
254 #define xwrz_testwx(x) ((x & 1) << 2) | (x & 2) | ((x & 4) >> 2)
255  if (print && size>0 && prev_info.inheritance != VM_INHERIT_SHARE) {
256  snprintf (buf, sizeof (buf), "%s %02x %s/%s/%s %s",
257  rz_str_rwx_i (xwrz_testwx (prev_info.max_protection)), i,
258  unparse_inheritance (prev_info.inheritance),
259  prev_info.shared ? "shar" : "priv",
260  prev_info.reserved ? "reserved" : "not-reserved",
261  module_name);
262  // TODO: MAPS can have min and max protection rules
263  // :: prev_info.max_protection
264  mr = rz_debug_map_new (buf, prev_address, prev_address+prev_size,
265  xwrz_testwx (prev_info.protection), 0);
266  if (!mr) {
267  eprintf ("Cannot create rz_debug_map_new\n");
268  break;
269  }
270  mr->file = strdup (module_name);
272  }
273 }
274 #if 0
275  if (1==0 && rest) { /* XXX never pritn this info here */
276  addr = 0LL;
277  addr = (ut64) (ut32) prev_address;
278  if (num_printed == 0)
279  fprintf(stderr, "Region ");
280  else fprintf(stderr, " ... ");
281  fprintf(stderr, " 0x%08llx - 0x%08llx %s (%s) %s, %s, %s",
282  addr, addr + prev_size,
283  unparse_protection (prev_info.protection),
284  unparse_protection (prev_info.max_protection),
285  unparse_inheritance (prev_info.inheritance),
286  prev_info.shared ? "shared" : " private",
287  prev_info.reserved ? "reserved" : "not-reserved");
288 
289  if (nsubregions > 1)
290  fprintf(stderr, " (%d sub-regions)", nsubregions);
291 
292  fprintf(stderr, "\n");
293 
294  prev_address = address;
295  prev_size = size;
296  memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
297  nsubregions = 1;
298 
299  num_printed++;
300  } else {
301 #endif
302 #if 0
303  prev_size += size;
304  nsubregions++;
305 #else
306  prev_address = address;
307  prev_size = size;
308  memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
309  nsubregions = 1;
310 
311  num_printed++;
312 #endif
313  // }
314  }
315  return list;
316 }
317 #endif
318 
319 static RzList *darwin_dbg_maps(RzDebug *dbg) {
320  // return osx_dbg_maps (dbg);
321  return ios_dbg_maps(dbg);
322 #if 0
323  const char *osname = dbg->analysis->syscall->os;
324  if (osname && !strcmp (osname, "ios")) {
325  return ios_dbg_maps (dbg);
326  }
327  return osx_dbg_maps (dbg);
328 #endif
329 }
330 
331 #endif
lzma_index ** i
Definition: index.h:629
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
static int mr(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len)
Definition: cmd_analysis.c:471
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
uint32_t ut32
RzDebug * dbg
Definition: desil.c:30
RZ_API RzDebugMap * rz_debug_map_new(char *name, ut64 addr, ut64 addr_end, int perm, int user)
Definition: dmap.c:7
struct tab * done
Definition: enough.c:233
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
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_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
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
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
Definition: sflib.h:64
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API const char * rz_str_rwx_i(int rwx)
Definition: str.c:332
#define PFMT64x
Definition: rz_types.h:393
#define UT32_MAX
Definition: rz_types_base.h:99
unsigned int uint32_t
Definition: sftypes.h:29
unsigned long uint64_t
Definition: sftypes.h:28
Definition: buffer.h:15
RzSyscall * syscall
Definition: rz_analysis.h:570
RzAnalysis * analysis
Definition: rz_debug.h:305
char * os
Definition: rz_syscall.h:41
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const char * unparse_inheritance(vm_inherit_t i)
Definition: xnu_debug.c:1020
int proc_regionfilename(int pid, uint64_t address, void *buffer, uint32_t buffersize)
kern_return_t mach_vm_region_recurse(vm_map_t target_task, mach_vm_address_t *address, mach_vm_size_t *size, natural_t *nesting_depth, vm_region_recurse_info_t info, mach_msg_type_number_t *infoCnt)
vm_address_t get_kernel_base(task_t ___task)
Definition: xnu_debug.c:1037
task_t pid_to_task(int pid)
Definition: xnu_debug.c:498
#define xwrz_testwx(x)
Definition: xnu_debug.c:571
#define KERNEL_LOWER
Definition: xnu_debug.h:122
#define IMAGE_OFFSET
Definition: xnu_debug.h:121
static int addr
Definition: z80asm.c:58