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