LIEF: Library to Instrument Executable Formats Version 0.17.0
Loading...
Searching...
No Matches
ChainedPointerAnalysis.hpp
Go to the documentation of this file.
1/* Copyright 2017 - 2025 R. Thomas
2 * Copyright 2017 - 2025 Quarkslab
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef LIEF_MACHO_CHAINED_PTR_ANALYSIS_H
17#define LIEF_MACHO_CHAINED_PTR_ANALYSIS_H
18#include <memory>
19#include <ostream>
20#include <functional>
21#include <cstring>
22
24#include "LIEF/errors.hpp"
25#include "LIEF/visibility.h"
26
27namespace LIEF {
28class BinaryStream;
29namespace MachO {
31 public:
32 // DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E
33 struct dyld_chained_ptr_arm64e_rebase_t
34 {
35 uint64_t target : 43,
36 high8 : 8,
37 next : 11,
38 bind : 1,
39 auth : 1;
40
41 friend LIEF_API
42 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_arm64e_rebase_t& chain);
43
44 uint64_t unpack_target() const {
45 return uint64_t(high8) | target;
46 }
47 };
48
49 // DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E
50 struct dyld_chained_ptr_arm64e_bind_t
51 {
52 uint64_t ordinal : 16,
53 zero : 16,
54 addend : 19,
55 next : 11,
56 bind : 1,
57 auth : 1;
58
59 friend LIEF_API
60 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_arm64e_bind_t& chain);
61 };
62
63 // DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E
64 struct dyld_chained_ptr_arm64e_auth_rebase_t
65 {
66 uint64_t target : 32,
67 diversity : 16,
68 addr_div : 1,
69 key : 2,
70 next : 11,
71 bind : 1,
72 auth : 1;
73
74 friend LIEF_API
75 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_arm64e_auth_rebase_t& chain);
76 };
77
78 // DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E
79 struct dyld_chained_ptr_arm64e_auth_bind_t
80 {
81 uint64_t ordinal : 16,
82 zero : 16,
83 diversity : 16,
84 addr_div : 1,
85 key : 2,
86 next : 11,
87 bind : 1,
88 auth : 1;
89
90 friend LIEF_API
91 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_arm64e_auth_bind_t& chain);
92 };
93
94 // DYLD_CHAINED_PTR_FORMAT::PTR_64 & DYLD_CHAINED_PTR_FORMAT::PTR_64_OFFSET
95 struct dyld_chained_ptr_64_rebase_t
96 {
97 uint64_t target : 36,
98 high8 : 8,
99 reserved : 7,
100 next : 12,
101 bind : 1;
102
103 friend LIEF_API
104 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_64_rebase_t& chain);
105
106 uint64_t unpack_target() const {
107 return uint64_t(high8) | target;
108 }
109 };
110
111 // DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_USERLAND24
112 struct dyld_chained_ptr_arm64e_bind24_t
113 {
114 uint64_t ordinal : 24,
115 zero : 8,
116 addend : 19,
117 next : 11,
118 bind : 1,
119 auth : 1;
120
121 friend LIEF_API
122 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_arm64e_bind24_t& chain);
123 };
124
125 // DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_USERLAND24
126 struct dyld_chained_ptr_arm64e_auth_bind24_t
127 {
128 uint64_t ordinal : 24,
129 zero : 8,
130 diversity : 16,
131 addr_div : 1,
132 key : 2,
133 next : 11,
134 bind : 1,
135 auth : 1;
136
137 friend LIEF_API
138 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_arm64e_auth_bind24_t& chain);
139 };
140
141 // DYLD_CHAINED_PTR_FORMAT::PTR_64
142 struct dyld_chained_ptr_64_bind_t
143 {
144 uint64_t ordinal : 24,
145 addend : 8,
146 reserved : 19,
147 next : 12,
148 bind : 1;
149
150 friend LIEF_API
151 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_64_bind_t& chain);
152 };
153
154 // DYLD_CHAINED_PTR_FORMAT::PTR_64_KERNEL_CACHE
155 struct dyld_chained_ptr_64_kernel_cache_rebase_t
156 {
157 uint64_t target : 30,
158 cache_level : 2,
159 diversity : 16,
160 addr_div : 1,
161 key : 2,
162 next : 12,
163 is_auth : 1;
164
165 friend LIEF_API
166 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_64_kernel_cache_rebase_t& chain);
167 };
168
169 // DYLD_CHAINED_PTR_FORMAT::PTR_32
170 struct dyld_chained_ptr_32_rebase_t
171 {
172 uint32_t target : 26,
173 next : 5,
174 bind : 1;
175
176 friend LIEF_API
177 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_32_rebase_t& chain);
178 };
179
180 // DYLD_CHAINED_PTR_FORMAT::PTR_32
181 struct dyld_chained_ptr_32_bind_t
182 {
183 uint32_t ordinal : 20,
184 addend : 6,
185 next : 5,
186 bind : 1;
187
188 friend LIEF_API
189 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_32_bind_t& chain);
190 };
191
192 // DYLD_CHAINED_PTR_FORMAT::PTR_32_CACHE
193 struct dyld_chained_ptr_32_cache_rebase_t
194 {
195 uint32_t target : 30,
196 next : 2;
197
198 friend LIEF_API
199 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_32_cache_rebase_t& chain);
200 };
201
202 // DYLD_CHAINED_PTR_FORMAT::PTR_32_FIRMWARE
203 struct dyld_chained_ptr_32_firmware_rebase_t
204 {
205 uint32_t target : 26,
206 next : 6;
207
208 friend LIEF_API
209 std::ostream& operator<<(std::ostream& os, const dyld_chained_ptr_32_firmware_rebase_t& chain);
210 };
211
212 enum class PTR_TYPE : uint64_t {
214 DYLD_CHAINED_PTR_ARM64E_REBASE,
215 DYLD_CHAINED_PTR_ARM64E_BIND,
216 DYLD_CHAINED_PTR_ARM64E_AUTH_REBASE,
217 DYLD_CHAINED_PTR_ARM64E_AUTH_BIND,
218 DYLD_CHAINED_PTR_64_REBASE,
219 DYLD_CHAINED_PTR_ARM64E_BIND24,
220 DYLD_CHAINED_PTR_ARM64E_AUTH_BIND24,
221 DYLD_CHAINED_PTR_64_BIND,
222 DYLD_CHAINED_PTR_64_KERNEL_CACHE_REBASE,
223 DYLD_CHAINED_PTR_32_REBASE,
224 DYLD_CHAINED_PTR_32_BIND,
225 DYLD_CHAINED_PTR_32_CACHE_REBASE,
226 DYLD_CHAINED_PTR_32_FIRMWARE_REBASE
227 };
228
229 static std::unique_ptr<ChainedPointerAnalysis> from_value(uint64_t value,
230 size_t size)
231 {
232 return std::unique_ptr<ChainedPointerAnalysis>(
233 new ChainedPointerAnalysis(value, size));
234 }
235
236 static size_t stride(DYLD_CHAINED_PTR_FORMAT fmt) {
237 switch (fmt) {
238 case DYLD_CHAINED_PTR_FORMAT::NONE:
239 return 0;
240 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E:
241 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_USERLAND:
242 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_USERLAND24:
243 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_SHARED_CACHE:
244 return 8;
245
246 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_KERNEL:
247 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_FIRMWARE:
248 case DYLD_CHAINED_PTR_FORMAT::PTR_32_FIRMWARE:
249 case DYLD_CHAINED_PTR_FORMAT::PTR_64:
250 case DYLD_CHAINED_PTR_FORMAT::PTR_64_OFFSET:
251 case DYLD_CHAINED_PTR_FORMAT::PTR_32:
252 case DYLD_CHAINED_PTR_FORMAT::PTR_32_CACHE:
253 case DYLD_CHAINED_PTR_FORMAT::PTR_64_KERNEL_CACHE:
254 return 4;
255
256 case DYLD_CHAINED_PTR_FORMAT::PTR_X86_64_KERNEL_CACHE:
257 return 1;
258 }
259 return 0;
260 }
261
262 static size_t ptr_size(DYLD_CHAINED_PTR_FORMAT fmt) {
263 switch (fmt) {
264 case DYLD_CHAINED_PTR_FORMAT::NONE:
265 return 0;
266 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E:
267 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_USERLAND:
268 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_USERLAND24:
269 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_KERNEL:
270 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_FIRMWARE:
271 case DYLD_CHAINED_PTR_FORMAT::PTR_64:
272 case DYLD_CHAINED_PTR_FORMAT::PTR_64_OFFSET:
273 case DYLD_CHAINED_PTR_FORMAT::PTR_64_KERNEL_CACHE:
274 case DYLD_CHAINED_PTR_FORMAT::PTR_X86_64_KERNEL_CACHE:
275 case DYLD_CHAINED_PTR_FORMAT::PTR_ARM64E_SHARED_CACHE:
276 return sizeof(uint64_t);
277
278 case DYLD_CHAINED_PTR_FORMAT::PTR_32_FIRMWARE:
279 case DYLD_CHAINED_PTR_FORMAT::PTR_32:
280 case DYLD_CHAINED_PTR_FORMAT::PTR_32_CACHE:
281 return sizeof(uint32_t);
282 }
283 return 0;
284 }
285
286 ChainedPointerAnalysis(uint64_t value, size_t size) :
287 value_(value),
288 size_(size)
289 {}
290
291 ChainedPointerAnalysis(const ChainedPointerAnalysis&) = default;
292 ChainedPointerAnalysis& operator=(const ChainedPointerAnalysis&) = default;
293
294 ChainedPointerAnalysis(ChainedPointerAnalysis&&) noexcept = default;
295 ChainedPointerAnalysis& operator=(ChainedPointerAnalysis&&) noexcept = default;
296
297 ~ChainedPointerAnalysis() = default;
298
299 uint64_t value() const {
300 return value_;
301 }
302
303 size_t size() const {
304 return size_;
305 }
306
307 const dyld_chained_ptr_arm64e_rebase_t dyld_chained_ptr_arm64e_rebase() const {
308 dyld_chained_ptr_arm64e_rebase_t result;
309 std::memcpy(&result, &value_, sizeof(result));
310 return result;
311 }
312
313 const dyld_chained_ptr_arm64e_bind_t dyld_chained_ptr_arm64e_bind() const {
314 dyld_chained_ptr_arm64e_bind_t result;
315 std::memcpy(&result, &value_, sizeof(result));
316 return result;
317 }
318
319 const dyld_chained_ptr_arm64e_auth_rebase_t dyld_chained_ptr_arm64e_auth_rebase() const {
320 dyld_chained_ptr_arm64e_auth_rebase_t result;
321 std::memcpy(&result, &value_, sizeof(result));
322 return result;
323 }
324
325 const dyld_chained_ptr_arm64e_auth_bind_t dyld_chained_ptr_arm64e_auth_bind() const {
326 dyld_chained_ptr_arm64e_auth_bind_t result;
327 std::memcpy(&result, &value_, sizeof(result));
328 return result;
329 }
330
331 const dyld_chained_ptr_64_rebase_t dyld_chained_ptr_64_rebase() const {
332 dyld_chained_ptr_64_rebase_t result;
333 std::memcpy(&result, &value_, sizeof(result));
334 return result;
335 }
336
337 const dyld_chained_ptr_arm64e_bind24_t dyld_chained_ptr_arm64e_bind24() const {
338 dyld_chained_ptr_arm64e_bind24_t result;
339 std::memcpy(&result, &value_, sizeof(result));
340 return result;
341 }
342
343 const dyld_chained_ptr_arm64e_auth_bind24_t dyld_chained_ptr_arm64e_auth_bind24() const {
344 dyld_chained_ptr_arm64e_auth_bind24_t result;
345 std::memcpy(&result, &value_, sizeof(result));
346 return result;
347 }
348
349 const dyld_chained_ptr_64_bind_t dyld_chained_ptr_64_bind() const {
350 dyld_chained_ptr_64_bind_t result;
351 std::memcpy(&result, &value_, sizeof(result));
352 return result;
353 }
354
355 const dyld_chained_ptr_64_kernel_cache_rebase_t dyld_chained_ptr_64_kernel_cache_rebase() const {
356 dyld_chained_ptr_64_kernel_cache_rebase_t result;
357 std::memcpy(&result, &value_, sizeof(result));
358 return result;
359 }
360
361 const dyld_chained_ptr_32_rebase_t dyld_chained_ptr_32_rebase() const {
362 dyld_chained_ptr_32_rebase_t result;
363 std::memcpy(&result, &value_, sizeof(result));
364 return result;
365 }
366
367 const dyld_chained_ptr_32_bind_t dyld_chained_ptr_32_bind() const {
368 dyld_chained_ptr_32_bind_t result;
369 std::memcpy(&result, &value_, sizeof(result));
370 return result;
371 }
372
373 const dyld_chained_ptr_32_cache_rebase_t dyld_chained_ptr_32_cache_rebase() const {
374 dyld_chained_ptr_32_cache_rebase_t result;
375 std::memcpy(&result, &value_, sizeof(result));
376 return result;
377 }
378
379 const dyld_chained_ptr_32_firmware_rebase_t dyld_chained_ptr_32_firmware_rebase() const {
380 dyld_chained_ptr_32_firmware_rebase_t result;
381 std::memcpy(&result, &value_, sizeof(result));
382 return result;
383 }
384
385 struct union_pointer_t {
386 PTR_TYPE type = PTR_TYPE::UNKNOWN;
387 union {
388 dyld_chained_ptr_arm64e_rebase_t arm64e_rebase;
389 dyld_chained_ptr_arm64e_bind_t arm64e_bind;
390 dyld_chained_ptr_arm64e_auth_rebase_t arm64e_auth_rebase;
391 dyld_chained_ptr_arm64e_auth_bind_t arm64e_auth_bind;
392 dyld_chained_ptr_64_rebase_t ptr_64_rebase;
393 dyld_chained_ptr_arm64e_bind24_t arm64e_bind24;
394 dyld_chained_ptr_arm64e_auth_bind24_t arm64e_auth_bind24;
395 dyld_chained_ptr_64_bind_t ptr_64_bind;
396 dyld_chained_ptr_64_kernel_cache_rebase_t ptr_64_kernel_cache_rebase;
397 dyld_chained_ptr_32_rebase_t ptr_32_rebase;
398 dyld_chained_ptr_32_bind_t ptr_32_bind;
399 dyld_chained_ptr_32_cache_rebase_t ptr_32_cache_rebase;
400 dyld_chained_ptr_32_firmware_rebase_t ptr_32_firmware_rebase;
401 uint64_t raw;
402 };
403 uint32_t next() const;
404
405 result<uint32_t> ordinal() const;
406 result<uint64_t> target() const;
407
408 bool is_bind() const {
409 return (bool)ordinal();
410 }
411 bool is_auth() const;
412
413 friend LIEF_API
414 std::ostream& operator<<(std::ostream& os, const union_pointer_t& ptr);
415 };
416
417 static_assert(sizeof(union_pointer_t) == 16);
418
419 union_pointer_t get_as(DYLD_CHAINED_PTR_FORMAT fmt) const;
420
421 static uint64_t walk_chain(
422 BinaryStream& stream, DYLD_CHAINED_PTR_FORMAT format,
423 const std::function<int(uint64_t, const union_pointer_t& ptr)>& callback);
424
425 private:
426 uint64_t value_ = 0;
427 size_t size_ = 0;
428};
429}
430}
431#endif
Class that is used to a read stream of data from different sources.
Definition BinaryStream.hpp:33
Definition ChainedPointerAnalysis.hpp:30
union_pointer_t get_as(DYLD_CHAINED_PTR_FORMAT fmt) const
ChainedPointerAnalysis(uint64_t value, size_t size)
Definition ChainedPointerAnalysis.hpp:286
const dyld_chained_ptr_32_bind_t dyld_chained_ptr_32_bind() const
Definition ChainedPointerAnalysis.hpp:367
const dyld_chained_ptr_64_bind_t dyld_chained_ptr_64_bind() const
Definition ChainedPointerAnalysis.hpp:349
const dyld_chained_ptr_64_rebase_t dyld_chained_ptr_64_rebase() const
Definition ChainedPointerAnalysis.hpp:331
size_t size() const
Definition ChainedPointerAnalysis.hpp:303
const dyld_chained_ptr_arm64e_rebase_t dyld_chained_ptr_arm64e_rebase() const
Definition ChainedPointerAnalysis.hpp:307
const dyld_chained_ptr_arm64e_auth_rebase_t dyld_chained_ptr_arm64e_auth_rebase() const
Definition ChainedPointerAnalysis.hpp:319
const dyld_chained_ptr_64_kernel_cache_rebase_t dyld_chained_ptr_64_kernel_cache_rebase() const
Definition ChainedPointerAnalysis.hpp:355
ChainedPointerAnalysis & operator=(const ChainedPointerAnalysis &)=default
const dyld_chained_ptr_arm64e_bind24_t dyld_chained_ptr_arm64e_bind24() const
Definition ChainedPointerAnalysis.hpp:337
const dyld_chained_ptr_32_rebase_t dyld_chained_ptr_32_rebase() const
Definition ChainedPointerAnalysis.hpp:361
static size_t stride(DYLD_CHAINED_PTR_FORMAT fmt)
Definition ChainedPointerAnalysis.hpp:236
const dyld_chained_ptr_32_firmware_rebase_t dyld_chained_ptr_32_firmware_rebase() const
Definition ChainedPointerAnalysis.hpp:379
const dyld_chained_ptr_arm64e_bind_t dyld_chained_ptr_arm64e_bind() const
Definition ChainedPointerAnalysis.hpp:313
const dyld_chained_ptr_arm64e_auth_bind_t dyld_chained_ptr_arm64e_auth_bind() const
Definition ChainedPointerAnalysis.hpp:325
ChainedPointerAnalysis(ChainedPointerAnalysis &&) noexcept=default
static std::unique_ptr< ChainedPointerAnalysis > from_value(uint64_t value, size_t size)
Definition ChainedPointerAnalysis.hpp:229
const dyld_chained_ptr_32_cache_rebase_t dyld_chained_ptr_32_cache_rebase() const
Definition ChainedPointerAnalysis.hpp:373
static size_t ptr_size(DYLD_CHAINED_PTR_FORMAT fmt)
Definition ChainedPointerAnalysis.hpp:262
ChainedPointerAnalysis(const ChainedPointerAnalysis &)=default
const dyld_chained_ptr_arm64e_auth_bind24_t dyld_chained_ptr_arm64e_auth_bind24() const
Definition ChainedPointerAnalysis.hpp:343
static uint64_t walk_chain(BinaryStream &stream, DYLD_CHAINED_PTR_FORMAT format, const std::function< int(uint64_t, const union_pointer_t &ptr)> &callback)
Namespace related to the LIEF's Mach-O module.
Definition Abstract/Header.hpp:36
@ UNKNOWN
Definition MachO/enums.hpp:24
LIEF namespace.
Definition Abstract/Binary.hpp:36
tl::expected< T, lief_errors > result
Wrapper that contains an Object (T) or an error.
Definition errors.hpp:75
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_32_bind_t &chain)
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_32_cache_rebase_t &chain)
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_32_firmware_rebase_t &chain)
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_32_rebase_t &chain)
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_64_bind_t &chain)
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_64_kernel_cache_rebase_t &chain)
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_64_rebase_t &chain)
uint64_t unpack_target() const
Definition ChainedPointerAnalysis.hpp:106
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_arm64e_auth_bind24_t &chain)
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_arm64e_auth_bind_t &chain)
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_arm64e_auth_rebase_t &chain)
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_arm64e_bind24_t &chain)
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_arm64e_bind_t &chain)
friend std::ostream & operator<<(std::ostream &os, const dyld_chained_ptr_arm64e_rebase_t &chain)
uint64_t unpack_target() const
Definition ChainedPointerAnalysis.hpp:44
friend std::ostream & operator<<(std::ostream &os, const union_pointer_t &ptr)
bool is_bind() const
Definition ChainedPointerAnalysis.hpp:408
#define LIEF_API
Definition visibility.h:41