1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 Darwin Process collectors.
21 """
22
23 __author__ = "Adam Sindelar <adamsh@google.com>"
24
25 from rekall import plugin
26 from rekall_lib import registry
27
28 from rekall.plugins import core
29 from rekall.plugins.darwin import common
30 from rekall.plugins.common import memmap
31
32
33 -class DarwinPslist(common.ProcessFilterMixin,
34 common.AbstractDarwinCommand):
35 name = "pslist"
36
37 table_header = [
38 dict(width=40, name="proc", type="proc"),
39 dict(width=8, name="alive"),
40 dict(name="ppid", width=6),
41 dict(name="uid", width=6),
42 dict(name="is64bit", width=6),
43 dict(name="start_time", width=30, style="short"),
44 dict(name="cr3", width=15, style="address")
45 ]
46
58
59
60 -class DarwinPsxView(common.ProcessFilterMixin,
61 common.AbstractDarwinCommand):
62 name = "psxview"
63
64
65 @registry.classproperty
66 @registry.memoize
74
83
86 name = "pstree"
87
88 table_header = [
89 dict(name="depth", type="DepthIndicator", width=10),
90 dict(name="pid", width=6),
91 dict(name="ppid", width=6),
92 dict(name="uid", width=6),
93 dict(name="name", width=30)
94 ]
95
102
104 if proc.validate():
105 yield proc, depth
106 for child in proc.p_children.lh_first.p_sibling:
107 for subproc, subdepth in self.recurse_proc(child, depth + 1):
108 yield subproc, subdepth
109
110
111 -class DarwinMaps(common.ProcessFilterMixin, common.AbstractDarwinCommand):
112 """Display the process maps."""
113
114 __name = "maps"
115
117 renderer.table_header([
118 dict(name="vm_map_entry", style="address"),
119 dict(name="Proc", width=40),
120 ("Start", "start", "[addrpad]"),
121 ("End", "end", "[addrpad]"),
122 ("Protection", "protection", "6"),
123 dict(name="Map Name", wrap=False),
124 ])
125
126 for proc in self.filter_processes():
127 for map in proc.task.map.hdr.walk_list(
128 "links.next", include_current=False):
129
130
131 protection = (
132 ("r" if map.protection.VM_PROT_READ else "-") +
133 ("w" if map.protection.VM_PROT_WRITE else "-") +
134 ("x" if map.protection.VM_PROT_EXECUTE else "-"))
135
136
137 vnode = map.find_vnode_object()
138
139 renderer.table_row(
140 map,
141 proc,
142 map.links.start,
143 map.links.end,
144 protection,
145 "sub_map" if map.is_sub_map else vnode.path,
146 )
147
148
149 -class DarwinVadDump(core.DirectoryDumperMixin, common.ProcessFilterMixin,
150 common.AbstractDarwinCommand):
151 """Dump the VMA memory for a process."""
152
153 __name = "vaddump"
154
156 for proc in self.filter_processes():
157 if not proc.task.map.pmap:
158 continue
159
160 renderer.format("Pid: {0:6}\n", proc.p_pid)
161
162
163 task_space = proc.get_process_address_space()
164 name = proc.p_comm
165
166 for vma in proc.task.map.hdr.walk_list(
167 "links.next", include_current=False):
168 filename = "{0}.{1}.{2:08x}-{3:08x}.dmp".format(
169 name, proc.p_pid, vma.links.start, vma.links.end)
170
171 renderer.format(u"Writing {0}, pid {1} to {2}\n",
172 proc.p_comm, proc.p_pid, filename)
173
174 with renderer.open(directory=self.dump_dir,
175 filename=filename,
176 mode='wb') as fd:
177 self.CopyToFile(task_space, vma.links.start,
178 vma.links.end, fd)
179
180
181 -class DarwinPSAUX(common.ProcessFilterMixin, common.AbstractDarwinCommand):
182 """List processes with their commandline."""
183
184 __name = "psaux"
185
187 renderer.table_header([
188 ("Pid", "pid", "8"),
189 ("Name", "name", "20"),
190 ("Stack", "stack", "[addrpad]"),
191 ("Length", "length", "8"),
192 ("Argc", "argc", "8"),
193 ("Arguments", "argv", "[wrap:80]")])
194
195 for proc in self.filter_processes():
196 renderer.table_row(
197 proc.p_pid,
198 proc.p_comm,
199 proc.user_stack,
200 proc.p_argslen,
201 proc.p_argc,
202 " ".join(proc.argv))
203
204
205 -class DarwinMemMap(memmap.MemmapMixIn, common.ProcessFilterMixin,
206 common.AbstractDarwinCommand):
207 """Prints the memory map for darwin tasks."""
208 __name = "memmap"
209
211 return 0x800000000000
212
213
214 -class DarwinMemDump(memmap.MemDumpMixin, common.ProcessFilterMixin,
215 common.AbstractDarwinCommand):
216 """Dumps the memory map for darwin tasks."""
217
223 """List all processes by following the _allproc list head."""
224
225 name = "allproc"
226
233
236 """List all processes by following the _allproc list head."""
237
238 name = "tasks"
239
241 """List processes using the processor tasks queue.
242
243 See
244 /osfmk/kern/processor.c (processor_set_things)
245 """
246 seen = set()
247
248 tasks = self.session.profile.get_constant_object(
249 "_tasks",
250 target="queue_entry",
251 vm=self.session.kernel_address_space)
252
253 for task in tasks.list_of_type("task", "tasks"):
254 proc = task.bsd_info.deref()
255 if proc:
256 seen.add(proc.obj_offset)
257
258 return seen
259
262 """List all processes by following the _allproc list head."""
263
264 name = "pgrphash"
265
267 """Process groups are organized in a hash chain.
268
269 xnu-1699.26.8/bsd/sys/proc_internal.h
270 """
271 seen = set()
272
273
274
275
276
277
278
279
280
281
282
283
284
285 pgr_hash_table = self.session.profile.get_constant_object(
286 "_pgrphashtbl",
287 target="Pointer",
288 target_args=dict(
289 target="Array",
290 target_args=dict(
291 target="pgrphashhead",
292 count=self.session.profile.get_constant_object(
293 "_pgrphash", "unsigned long") + 1
294 )
295 )
296 )
297
298 for slot in pgr_hash_table.deref():
299 for pgrp in slot.lh_first.walk_list("pg_hash.le_next"):
300 for proc in pgrp.pg_members.lh_first.walk_list(
301 "p_pglist.le_next"):
302 seen.add(proc.obj_offset)
303
304 return seen
305
308 """List all processes by following the _allproc list head."""
309
310 name = "pidhash"
311
313 """Lists processes using pid hash tables.
314
315 xnu-1699.26.8/bsd/kern/kern_proc.c:834:
316 pfind_locked(pid_t pid)
317 """
318 seen = set()
319
320
321
322
323
324
325
326
327
328
329
330
331
332 pid_hash_table = self.session.profile.get_constant_object(
333 "_pidhashtbl",
334 target="Pointer",
335 target_args=dict(
336 target="Array",
337 target_args=dict(
338 target="pidhashhead",
339 count=self.session.profile.get_constant_object(
340 "_pidhash", "unsigned long") + 1
341 )
342 )
343 )
344
345 for plist in pid_hash_table.deref():
346 for proc in plist.lh_first.walk_list("p_hash.le_next"):
347 if proc:
348 seen.add(proc.obj_offset)
349
350 return seen
351
356
361
366
371