1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """Plugins for checking internal consistancy of pointers."""
19
20 __author__ = "Michael Cohen <scudette@google.com>"
21
22
23 from rekall import obj
24 from rekall import scan
25 from rekall.plugins.darwin import common
26 from rekall_lib import utils
30 """Find sysent by scanning around nsysent.
31
32 The production kernel no longer ships with the 'sysent' symbol,
33 which is the address of the syscall switch table. However, because
34 sysent and nsysent are initialized around the same time it works out that
35 they are always near each other.
36
37 This is an old technique, documented around the internet, for example here:
38 https://reverse.put.as/2010/11/27/a-semi-automated-way-to-find-sysent/
39 """
40
41 name = "sysent_scan"
42
43
44 SYSENT_REL_OFFSET = -0x1000 * 0x1000
45
46
47 LIMIT = 0x2000 * 0x1000
48
49 - def scan(self, start, limit):
50 scanner = scan.FastStructScanner(
51 session=self.session,
52 profile=self.session.profile,
53 type_name="sysent",
54 expected_values=[
55 {"sy_arg_bytes": 0, "sy_narg": 0},
56 {"sy_arg_bytes": 4, "sy_narg": 1},
57 {"sy_arg_bytes": 0, "sy_narg": 0},
58 {"sy_arg_bytes": 12, "sy_narg": 3}],
59 address_space=self.session.default_address_space)
60
61 for hit in scanner.scan(offset=start, maxlen=limit):
62 return hit
63
73
76 """Checks the syscall table."""
77
78 __name = "check_syscalls"
79
96
98 renderer.table_header(
99 [("Index", "index", "6"),
100 ("Address", "address", "[addrpad]"),
101 ("Target", "target", "[addrpad]"),
102 ("Symbol", "symbol", "")])
103
104 for i, (entry, call, symbol) in enumerate(self.CheckSyscallTables()):
105 renderer.table_row(i, entry, call, symbol)
106
109 - def __init__(self, oidp, names=None, numbers=None):
110 self.oidp = oidp
111 self._names = names or []
112 self._numbers = numbers or []
113 self.handler = None
114
116 oidp = self.oidp
117 while oidp:
118 if oidp.oid_name:
119 yield OIDInfo(oidp, self._names, self._numbers)
120
121 oidp = oidp.oid_link.sle_next
122
123 @utils.safe_property
125 return (("R" if self.oidp.oid_perms.CTLFLAG_RD else "-") +
126 ("W" if self.oidp.oid_perms.CTLFLAG_WR else "-") +
127 ("L" if self.oidp.oid_perms.CTLFLAG_LOCKED else "-"))
128
129 @utils.safe_property
131 """Decode the arg according to its type."""
132 if self.oidp.oid_kind_type == "CTLTYPE_NODE":
133 if self.oidp.oid_handler:
134 return "Node"
135 else:
136 names = self._names[:]
137 names.append(self.oidp.oid_name.deref())
138 numbers = self._numbers[:]
139 numbers.append(self.oidp.oid_number)
140
141 oid = self.oidp.oid_arg1.dereference_as("sysctl_oid_list")
142 return OIDInfo(oid.slh_first, names, numbers)
143
144 elif self.oidp.oid_kind_type == "CTLTYPE_INT":
145 return self.oidp.oid_arg1.dereference_as("int")
146
147 elif self.oidp.oid_kind_type == "CTLTYPE_STRING":
148 return self.oidp.oid_arg1.dereference_as("String")
149
150 elif self.oidp.oid_kind_type == "CTLTYPE_QUAD":
151 return self.oidp.oid_arg1.dereference_as("long long int")
152
153 elif self.oidp.oid_kind_type == "CTLTYPE_OPAQUE":
154 return self.oidp.oid_arg1.dereference_as("Void")
155
156 return obj.NoneObject("Unknown arg type")
157
158 @utils.safe_property
160 names = self._names[:]
161 names.append(self.oidp.oid_name.deref())
162 return ".".join(["%s" % x for x in names])
163
164 @utils.safe_property
166 numbers = self._numbers[:]
167 numbers.append(self.oidp.oid_number)
168 return ".".join(["%s" % x for x in numbers])
169
172 """Dumps the sysctl database.
173
174 On OSX the kernel is configured through the sysctl mechanism. This is
175 analogous to /proc or /sysfs on Linux. The configuration space is broken
176 into MIBs - or hierarchical namespace.
177
178 https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/sysctl.8.html
179
180 For example:
181
182 net.inet.ip.subnets_are_local
183 net.inet.ip.ttl
184 net.inet.ip.use_route_genid
185
186 This is implemented via a singly linked list of sysctl_oid structs. The
187 structs can be on the following types:
188
189 - CTLTYPE_INT means this MIB will handle an int.
190 - CTLTYPE_STRING means this MIB will handle a string.
191 - CTLTYPE_QUAD means this MIB will handle a long long int.
192 - CTLTYPE_NODE means this is a node which handles a sublevel of MIBs. It is
193 actually a pointer to a new sysctl_oid_list which handles the sublevel.
194
195 """
196
197 __name = "sysctl"
198
200 sysctrl_list = self.profile.get_constant_object(
201 "_sysctl__children", "sysctl_oid_list")
202
203 oidinfo = OIDInfo(sysctrl_list.slh_first)
204 for oid in self._process(oidinfo):
205 yield oid
206
208
209 for oid in sorted(oidinfo, key=lambda x: x.name):
210 if isinstance(oid.arg, OIDInfo):
211 for x in self._process(oid.arg):
212 yield x
213 else:
214 yield oid
215
216 table_header = [
217 dict(name="name", width=45),
218 dict(name="mib", width=16),
219 dict(name="perms", width=6),
220 dict(name="handler", style="address"),
221 dict(name="symbol", width=40),
222 dict(name="value")
223 ]
224
233
235 for oid in self.CheckSysctl():
236
237 value = oid.arg
238 if isinstance(value, obj.Pointer):
239 value = "@ 0x%X" % int(value)
240
241 elif not value == None:
242 try:
243 value = int(value)
244 value = "0x%X (%d)" % (value, value)
245 except (ValueError, AttributeError):
246 pass
247
248 yield (oid.name,
249 oid.number,
250 oid.perms,
251 oid.oidp.oid_handler,
252 utils.FormattedAddress(
253 self.session.address_resolver,
254 oid.oidp.oid_handler),
255 value)
256
259 """Checks the traps table for hooks."""
260
261 __name = "check_trap_table"
262
293
310
312 renderer.table_header([
313 ("Index", "index", "[addr]"),
314 ("Address", "address", "[addrpad]"),
315 ("Target", "target", "[addrpad]"),
316 ("Symbol", "symbol", "")])
317
318 for i, entry, call, sym_name in self.CheckTrapTables():
319 if call == None:
320 continue
321
322 renderer.table_row(i, entry, call, sym_name or "Unknown",
323 highlight=None if sym_name else "important")
324