├── _config.yml
├── fix_swift
├── llvm
│ └── Config
│ │ ├── abi-breaking.h
│ │ └── llvm-config.h
└── swift
│ └── Runtime
│ └── CMakeConfig.h
├── docs
└── _config.yml
├── media
├── swift.png
└── vmmap.png
├── compiled
├── dsdump_beta.zip
└── dsdump_compiled.zip
├── dsdump
├── binaries
│ ├── some_app
│ └── arm_hello.out
├── libswiftDemangling.a
├── XRMachOLibrary+PID_Info.h
├── Bind Symbols
│ ├── XRMachOLibrary+Opcode.h
│ ├── XRBindSymbol.h
│ ├── XRBindSymbol.m
│ └── XRMachOLibrary+Opcode.mm
├── XRMachOLibrary+Disassemble.h
├── XRMachOLibrary+Swift.h
├── TaskPath.h
├── XRMachOLibrary_cplus.h
├── Ripped off
│ ├── objc-layout.h
│ ├── objc-typeencoding.mm
│ └── objc_.h
├── XRSymbolEntry.m
├── Protocols.h
├── Properties.h
├── XRMachOLibrary+SymbolDumper.h
├── XRMachOLibrary+ObjectiveC.h
├── Methods.h
├── XRSymbolEntry.h
├── FAT
│ ├── XRMachOLibrary+FAT.h
│ └── XRMachOLibrary+FAT.mm
├── payload.cpp
├── XRMachOLibrary+FileManagement.m
├── statusbar.h
├── TestSwift.swift
├── objc_.mm
├── miscellaneous.h
├── statusbar.c
├── progressbar.h
├── XRMachOLibraryCplusHelpers.h
├── Methods.mm
├── XRMachOLibrary.h
├── dsdump.1
├── XRMachOLibrary+Disassemble.mm
├── dyld_process_info_internal.h
├── Protocols.mm
├── miscellaneous.mm
├── TaskPath.mm
├── progressbar.c
├── payload.hpp
├── main.m
├── XRMachOLibrary+SymbolDumper.mm
├── DSXRLibrary+PID_Info.m
├── Properties.mm
└── XRMachOLibrary+ObjectiveC.mm
├── .gitmodules
├── dsdump.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcshareddata
│ │ ├── WorkspaceSettings.xcsettings
│ │ └── IDEWorkspaceChecks.plist
│ └── xcuserdata
│ │ └── lolgrep.xcuserdatad
│ │ └── WorkspaceSettings.xcsettings
├── xcuserdata
│ ├── derekselander.xcuserdatad
│ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── lolgrep.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
└── xcshareddata
│ └── xcschemes
│ ├── Generate Build.xcscheme
│ └── dsdump.xcscheme
├── dsdump.rb
├── .gitignore
└── README.md
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/fix_swift/llvm/Config/abi-breaking.h:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fix_swift/llvm/Config/llvm-config.h:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fix_swift/swift/Runtime/CMakeConfig.h:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/media/swift.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DerekSelander/dsdump/HEAD/media/swift.png
--------------------------------------------------------------------------------
/media/vmmap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DerekSelander/dsdump/HEAD/media/vmmap.png
--------------------------------------------------------------------------------
/compiled/dsdump_beta.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DerekSelander/dsdump/HEAD/compiled/dsdump_beta.zip
--------------------------------------------------------------------------------
/dsdump/binaries/some_app:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DerekSelander/dsdump/HEAD/dsdump/binaries/some_app
--------------------------------------------------------------------------------
/compiled/dsdump_compiled.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DerekSelander/dsdump/HEAD/compiled/dsdump_compiled.zip
--------------------------------------------------------------------------------
/dsdump/libswiftDemangling.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DerekSelander/dsdump/HEAD/dsdump/libswiftDemangling.a
--------------------------------------------------------------------------------
/dsdump/binaries/arm_hello.out:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DerekSelander/dsdump/HEAD/dsdump/binaries/arm_hello.out
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "capstone"]
2 | path = capstone
3 | url = https://derekselander@github.com/aquynh/capstone.git
4 |
--------------------------------------------------------------------------------
/dsdump.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/dsdump.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/dsdump.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/dsdump/XRMachOLibrary+PID_Info.h:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary+PID_Info.h
3 | // xref
4 | //
5 | // Created by Derek Selander on 5/3/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import "XRMachOLibrary.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface XRMachOLibrary (PID_Info)
14 |
15 | @end
16 |
17 | NS_ASSUME_NONNULL_END
18 |
--------------------------------------------------------------------------------
/dsdump/Bind Symbols/XRMachOLibrary+Opcode.h:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary+Opcode.h
3 | // xref
4 | //
5 | // Created by Derek Selander on 4/21/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import "XRMachOLibrary.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 |
14 | @interface XRMachOLibrary (Opcode)
15 | - (void)parseDYLDExports;
16 | - (void)parseDYLDOpcodes;
17 |
18 | @end
19 |
20 |
21 | NS_ASSUME_NONNULL_END
22 |
--------------------------------------------------------------------------------
/dsdump.rb:
--------------------------------------------------------------------------------
1 | class dsdump < Formula
2 | desc "An improved nm + Objective-C & Swift class-dump"
3 | homepage "https://github.com/DerekSelander/dsdump"
4 | version "0.1.0"
5 | sha256 "83eebd025b43b58a486235e1bec70a3239995be409605e3ff19bdae07adff917"
6 |
7 |
8 | url "https://github.com/DerekSelander/dsdump/blob/master/compiled/dsdump.zip", :using => :curl
9 |
10 |
11 | def install
12 | bin.install "selander/dsdump"
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/dsdump/XRMachOLibrary+Disassemble.h:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary+Disassemble.h
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 9/27/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 |
12 | #import "XRMachOLibrary.h"
13 |
14 | NS_ASSUME_NONNULL_BEGIN
15 |
16 | @interface XRMachOLibrary (Disassemble)
17 |
18 | - (uintptr_t *)resolveMetadataFromCode:(uintptr_t)address;
19 |
20 | @end
21 |
22 | NS_ASSUME_NONNULL_END
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /xref.xcodeproj/xcuserdata/derekselander.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
2 | /xref.xcodeproj/project.xcworkspace/xcuserdata/derekselander.xcuserdatad/UserInterfaceState.xcuserstate
3 | /xref.xcodeproj/xcuserdata/lolgrep.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
4 | /xref.xcodeproj/project.xcworkspace/xcuserdata/lolgrep.xcuserdatad/UserInterfaceState.xcuserstate
5 | *.xcuserstate
6 | *.xcbkptlist
7 | Breakpoints_v2.xcbkptlist
8 | /.DS_Store
9 | /dsdump/.DS_Store
10 | .DS_Store
11 | xcuserdata
12 | swift-source
13 |
--------------------------------------------------------------------------------
/dsdump/XRMachOLibrary+Swift.h:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary+Swift.h
3 | // xref
4 | //
5 | // Created by Derek Selander on 5/18/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import "XRMachOLibrary.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface XRMachOLibrary (Swift)
14 |
15 | - (void)dumpSwiftTypes;
16 | - (BOOL)preparseSwiftTypes;
17 | - (void)dumpSwiftProtocols;
18 | - (void)preparseSwiftProtocols;
19 | @end
20 |
21 | #define FAST_IS_SWIFT_LEGACY 1 // < 5
22 | #define FAST_IS_SWIFT_STABLE 2 // 5.X
23 |
24 | NS_ASSUME_NONNULL_END
25 |
--------------------------------------------------------------------------------
/dsdump/TaskPath.h:
--------------------------------------------------------------------------------
1 | //
2 | // TaskPath.hpp
3 | // xref
4 | //
5 | // Created by Derek Selander on 5/7/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #ifndef TaskPath_hpp
10 | #define TaskPath_hpp
11 |
12 | #include
13 | #include
14 |
15 | //typedef enum _LibraryTaskError {
16 | // LibraryTaskErrorDyldVersion = 0,
17 | //} LibraryTaskError;
18 |
19 | // BOOL FindLibraryInTask(pid_t task, char *search_string, LibraryTaskError* err) ;
20 | void DumpProcessesContainingLibrary(const char *lib_name, uuid_t uuid);
21 |
22 | #endif /* TaskPath_hpp */
23 |
--------------------------------------------------------------------------------
/dsdump.xcodeproj/xcuserdata/derekselander.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | xref.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | A66A9CBA22316CF3006602AB
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/dsdump/XRMachOLibrary_cplus.h:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary_cplus.h
3 | // xref
4 | //
5 | // Created by Derek Selander on 5/21/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #ifndef XRMachOLibrary_cplus_h
10 | #define XRMachOLibrary_cplus_h
11 |
12 | #import "XRMachOLibrary.h"
13 | #import
14 |
15 | // Dealing with the c++
16 | @interface XRMachOLibrary (Opcode_Private)
17 | @property (nonatomic, assign) std::unordered_map exports;
18 | @end
19 |
20 | @implementation XRMachOLibrary (Opcode_Private)
21 | @dynamic exports; // Defined in XRMachOLibrary.mm
22 | @end
23 |
24 | #endif /* XRMachOLibrary_cplus_h */
25 |
--------------------------------------------------------------------------------
/dsdump/Ripped off/objc-layout.h:
--------------------------------------------------------------------------------
1 | //
2 | // objc-layout.h
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 4/30/20.
6 | // Copyright © 2020 Selander. All rights reserved.
7 | //
8 |
9 | #ifndef objc_layout_h
10 | #define objc_layout_h
11 |
12 | char *scan_ivar_type_for_layout(char *type, long offset, long bits_size, unsigned char *bits, long *next_offset);
13 | char *scan_basic_ivar_type(char *type, long *size, long *alignment, bool *is_reference);
14 |
15 | char *skip_ivar_type_name(char *type);
16 | char *skip_ivar_struct_name(char *type);
17 |
18 | char *scan_ivar_type_for_layout(char *type, long offset, long bits_size, unsigned char *bits, long *next_offset);
19 | #endif /* objc_layout_h */
20 |
--------------------------------------------------------------------------------
/dsdump.xcodeproj/project.xcworkspace/xcuserdata/lolgrep.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildLocationStyle
6 | UseAppPreferences
7 | CustomBuildLocationType
8 | RelativeToDerivedData
9 | DerivedDataLocationStyle
10 | Default
11 | EnabledFullIndexStoreVisibility
12 |
13 | IssueFilterStyle
14 | ShowActiveSchemeOnly
15 | LiveSourceIssuesEnabled
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/dsdump/XRSymbolEntry.m:
--------------------------------------------------------------------------------
1 | //
2 | // XRSymbolEntry.m
3 | // xref
4 | //
5 | // Created by Derek Selander on 5/22/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import "XRSymbolEntry.h"
10 | #import "XRMachOLibrary.h"
11 |
12 | @implementation XRSymbolEntry
13 |
14 | -(instancetype)initWithSymbol:(struct nlist_64 *)symbol machoLibrary:(XRMachOLibrary*)lib {
15 | if (self = [super init]) {
16 | _name = (const char*)&lib.str_symbols[symbol->n_un.n_strx];
17 | if (strlen(_name) == 0) {
18 | _name = NULL;
19 | }
20 | _address = symbol->n_value;
21 | }
22 | return self;
23 | }
24 |
25 | - (NSString *)debugDescription {
26 | return [NSString stringWithFormat:@"%p, name: %s addr:%p", self, _name, (void*)_address];
27 | }
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/dsdump/Protocols.h:
--------------------------------------------------------------------------------
1 | //
2 | // Protocols.hpp
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 4/29/20.
6 | // Copyright © 2020 Selander. All rights reserved.
7 | //
8 |
9 | #ifndef Protocols_hpp
10 | #define Protocols_hpp
11 |
12 | #include
13 | #import "string.h"
14 | #import "XRMachOLibrary+Swift.h"
15 | #import "XRSymbolEntry.h"
16 | #import "objc_.h"
17 | #import "XRMachOLibrary+ObjectiveC.h"
18 | #import "XRMachOLibraryCplusHelpers.h"
19 | #import "XRMachOLibrary+Disassemble.h"
20 | #import "XRMachOLibraryCplusHelpers.h"
21 |
22 | #import "XRMachOLibrary+ObjectiveC.h"
23 | #import "XRMachOLibrary+SymbolDumper.h"
24 | #import "objc_.h"
25 | #import "Methods.h"
26 | #import "Properties.h"
27 |
28 | #endif /* Protocols_hpp */
29 |
30 | void dumpObjectiveCProtocols(void);
31 | BOOL listProtocolsForObjectiveCClass(swift_class* cls);
32 |
--------------------------------------------------------------------------------
/dsdump/Bind Symbols/XRBindSymbol.h:
--------------------------------------------------------------------------------
1 | //
2 | // DSXRObjCClass.h
3 | // xref
4 | //
5 | // Created by Derek Selander on 4/22/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /// Used for dyld opcode bind mapping
14 | @interface XRBindSymbol : NSObject
15 |
16 | @property (nonatomic, assign) NSNumber *address;
17 | @property (nonatomic, assign) int symidx;
18 | @property (nonatomic, copy) NSString *name;
19 | @property (nonatomic, readonly) NSString *shortName;
20 | @property (nonatomic, assign) uint64_t addend;
21 | @property (nonatomic, assign) uint64_t libOrdinal;
22 |
23 | - (instancetype)initWithAddress:(NSNumber *)address symbol:(NSString *)symbol libord:(uint64_t)ordinal addend:(uint64_t)addend;
24 |
25 | @end
26 |
27 |
28 | NS_ASSUME_NONNULL_END
29 |
--------------------------------------------------------------------------------
/dsdump/Properties.h:
--------------------------------------------------------------------------------
1 | //
2 | // Properties.hpp
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 4/28/20.
6 | // Copyright © 2020 Selander. All rights reserved.
7 | //
8 |
9 | #ifndef Properties_hpp
10 | #define Properties_hpp
11 |
12 | #include
13 | #import "string.h"
14 | #import "XRMachOLibrary+Swift.h"
15 | #import "XRSymbolEntry.h"
16 | #import "objc_.h"
17 | #import "XRMachOLibrary+ObjectiveC.h"
18 | #import "XRMachOLibraryCplusHelpers.h"
19 | #import "XRMachOLibrary+Disassemble.h"
20 | #import "XRMachOLibraryCplusHelpers.h"
21 |
22 | #import "XRMachOLibrary+ObjectiveC.h"
23 | #import "XRMachOLibrary+SymbolDumper.h"
24 | #import "objc_.h"
25 |
26 |
27 | void dumpObjCPropertiesWithResolvedAddress(protocol_t* prtl);
28 | void dumpObjCPropertiesWithResolvedAddress(swift_class* cls);
29 | void dumpObjCPropertiesWithResolvedAddress(property_list_t* propertiesList) ;
30 |
31 | #endif /* Properties_hpp */
32 |
--------------------------------------------------------------------------------
/dsdump/XRMachOLibrary+SymbolDumper.h:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary+SymbolDumper.h
3 | // xref
4 | //
5 | // Created by Derek Selander on 4/22/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 | #import "XRMachOLibrary.h"
9 |
10 | NS_ASSUME_NONNULL_BEGIN
11 |
12 |
13 | #ifdef __cplusplus
14 | extern "C" {
15 | #endif
16 |
17 | OS_ALWAYS_INLINE
18 | char* demangleCPP(char* mangledSym);
19 |
20 | void print_symbol(XRMachOLibrary *object, struct nlist_64 * _Nonnull sym, uintptr_t * _Nullable override_addr);
21 |
22 | #ifdef __cplusplus
23 | } // extern c
24 | #endif
25 |
26 |
27 | @interface XRMachOLibrary (SymbolDumper)
28 |
29 | - (void)dumpSymbols;
30 | - (void)dumpExternalSymbols;
31 | - (XRBindSymbol *)objCSuperClassFromSymbol:(struct nlist_64 * _Nonnull)sym;
32 |
33 | @end
34 |
35 |
36 |
37 | NS_ASSUME_NONNULL_END
38 |
39 |
40 |
41 | #define OBJC_CLASS_LENGTH (strlen("_OBJC_CLASS_$_"))
42 |
43 |
44 |
--------------------------------------------------------------------------------
/dsdump/XRMachOLibrary+ObjectiveC.h:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary+ObjectiveC.h
3 | // xref
4 | //
5 | // Created by Derek Selander on 4/29/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import "XRMachOLibrary.h"
10 |
11 | #define FILE_OFFSET_UNKNOWN ((intptr_t)-1)
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 |
16 |
17 |
18 | typedef struct {
19 | uint16_t mod_off : 16;
20 | uint16_t mod_len : 16;
21 | uint16_t cls_off : 16;
22 | // uint16_t cls_len : 10;
23 | BOOL success : 1;
24 | } d_offsets;
25 |
26 | // https://github.com/RetVal/objc-runtime/blob/master/runtime/objc-runtime-new.h#L478
27 | #define FAST_IS_SWIFT_LEGACY 1
28 | #define FAST_IS_SWIFT_STABLE 2
29 |
30 | BOOL demangleSwiftName(const char *name, d_offsets *f);
31 |
32 | @interface XRMachOLibrary (ObjectiveC)
33 |
34 | - (void)dumpObjectiveCClasses;
35 | - (void)dumpObjectiveCCategories;
36 |
37 |
38 |
39 | @end
40 |
41 | NS_ASSUME_NONNULL_END
42 |
--------------------------------------------------------------------------------
/dsdump/Methods.h:
--------------------------------------------------------------------------------
1 | //
2 | // Methods.hpp
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 4/29/20.
6 | // Copyright © 2020 Selander. All rights reserved.
7 | //
8 |
9 | #ifndef Methods_hpp
10 | #define Methods_hpp
11 |
12 | #import
13 | #import "string.h"
14 | #import "XRMachOLibrary+Swift.h"
15 | #import "XRSymbolEntry.h"
16 | #import "objc_.h"
17 | #import "XRMachOLibrary+ObjectiveC.h"
18 | #import "XRMachOLibraryCplusHelpers.h"
19 | #import "XRMachOLibrary+Disassemble.h"
20 | #import "XRMachOLibraryCplusHelpers.h"
21 |
22 | #import "XRMachOLibrary+ObjectiveC.h"
23 | #import "XRMachOLibrary+SymbolDumper.h"
24 | #import "objc_.h"
25 |
26 | #endif /* Methods_hpp */
27 |
28 | /// iOS 14 adds a __TEXT.__objc_methlist for int32_t offsets to methods, doesn't apply to protocols
29 | void dumpObjectiveCMethods(method_list_t* methodList, const char *name, bool isMeta, bool isProtocol = false, const char * overrideColor = NULL);
30 |
31 | const char* translate_method_type_to_string(char *typeString);
32 |
--------------------------------------------------------------------------------
/dsdump/XRSymbolEntry.h:
--------------------------------------------------------------------------------
1 | //
2 | // XRSymbolEntry.h
3 | // xref
4 | //
5 | // Created by Derek Selander on 5/22/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 | @class XRMachOLibrary;
14 |
15 | @protocol TestProto
16 | @property (nonatomic, assign) uint64_t address;
17 |
18 | @end
19 |
20 | // Used to reference symbols by address, originates from the symbol table
21 | @interface XRSymbolEntry : NSObject
22 |
23 | @property (nonatomic, assign) const char* name;
24 | @property (nonatomic, assign) uint64_t address;
25 | @property (nonatomic, assign) uint64_t flags;
26 | @property (nonatomic, assign) uint64_t other;
27 | @property (nonatomic, assign) const char* importName;
28 | @property (nonatomic, assign) BOOL visited;
29 |
30 | - (instancetype)initWithSymbol:(struct nlist_64 *)symbol machoLibrary:(XRMachOLibrary*)lib;
31 |
32 | @end
33 |
34 | NS_ASSUME_NONNULL_END
35 |
--------------------------------------------------------------------------------
/dsdump/Bind Symbols/XRBindSymbol.m:
--------------------------------------------------------------------------------
1 | //
2 | // DSXRObjCClass.m
3 | // xref
4 | //
5 | // Created by Derek Selander on 4/22/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import "XRBindSymbol.h"
10 | #import "XRMachOLibrary+SymbolDumper.h"
11 |
12 | @implementation XRBindSymbol
13 |
14 | - (instancetype)initWithAddress:(NSNumber *)address symbol:(NSString *)symbol libord:(uint64_t)ordinal addend:(uint64_t)addend {
15 | if (self = [super init]) {
16 | self.name = symbol;
17 | self.address = address;
18 | self.libOrdinal = ordinal;
19 | self.addend = addend;
20 | }
21 | return self;
22 | }
23 |
24 | - (NSString *)shortName {
25 | NSInteger index = [self.name rangeOfString:@"_$_"].location;
26 | if (index != NSNotFound) {
27 | return [self.name substringFromIndex:index + 3];
28 | }
29 | return self.name;
30 | }
31 |
32 | - (NSString *)description {
33 | return [NSString stringWithFormat:@"%p %@: <%p>", self.address.pointerValue, _name, self];
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/dsdump/FAT/XRMachOLibrary+FAT.h:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary+FAT.h
3 | // xref
4 | //
5 | // Created by Derek Selander on 5/1/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import "XRMachOLibrary.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface XRMachOLibrary (FAT)
14 |
15 | /// Architecture can't be found
16 | #define FAT_OFFSET_BAD_NAME -1
17 |
18 | /// Convenience for dealing with archs and endianness
19 | #define FIX_ENDIAN(name) (((fat->nfat_arch) < (htonl(fat->nfat_arch))) ? (name) : (htonl(name)))
20 |
21 | /// Used to display info if no arch is present and FAT
22 | -(NSString*)printAllArchitectures;
23 |
24 | /// Get offset for arch, returns FAT_OFFSET_BAD_NAME if can't find it
25 | - (intptr_t)offsetForArchitecture:(NSString *)architecture size:(size_t* _Nullable )size;
26 |
27 | /// Default arch name
28 | - (NSString *)defaultArchitectureName;
29 |
30 | /// Get default offset
31 | - (intptr_t)offsetForDefaultArchitecture;
32 |
33 | /// Return name for cpu/subcpu type
34 | -(NSString *)nameForCPU:(cpu_type_t)cputype subtype:(cpu_subtype_t)subtype;
35 | @end
36 |
37 | NS_ASSUME_NONNULL_END
38 |
--------------------------------------------------------------------------------
/dsdump.xcodeproj/xcuserdata/lolgrep.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Generate Build.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 2
11 |
12 | Generate Manpage.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 6
16 |
17 | dsdump.xcscheme_^#shared#^_
18 |
19 | orderHint
20 | 0
21 |
22 |
23 | SuppressBuildableAutocreation
24 |
25 | 3F50D7802315765B0017A20A
26 |
27 | primary
28 |
29 |
30 | 3FDE7B992314BF6800715685
31 |
32 | primary
33 |
34 |
35 | A66A9CBA22316CF3006602AB
36 |
37 | primary
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/dsdump/payload.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // payload.cpp
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 6/10/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #include "payload.hpp"
10 |
11 |
12 | // Likely from LLVM cmake
13 | namespace llvm {
14 | int DisableABIBreakingChecks = 0;
15 | };
16 |
17 | // Holds the executable data
18 | namespace payload {
19 | uint8_t *data;
20 | uintptr_t size;
21 | std::vector sections;
22 | uintptr_t offset;
23 | std::map sectionsDict;
24 | std::unordered_set filters;
25 |
26 | uintptr_t Offset2Virtual(uintptr_t f) {
27 | auto r = ARM64E_POINTER(f);
28 | for (auto &sec : payload::sections) {
29 | if (sec->offset <= (r) && (r) < (sec->offset + sec->size)) {
30 | return r + sec->addr - sec->offset;
31 | }
32 | }
33 |
34 | printf( "WARNING: couldn't find offset 0x%lx in binary!\n", r);
35 | return 0;
36 | }
37 |
38 | uintptr_t Virtual2Offset(uintptr_t f) {
39 | auto r = ARM64E_POINTER(f);
40 | for (auto i = 0; i < payload::sections.size(); i++) {
41 | struct section_64 *sec = payload::sections[i];
42 | if (sec->offset <= (r) && (r) < (sec->offset + sec->size)) {
43 | return r + sec->addr - sec->offset;
44 | }
45 | }
46 |
47 | printf( "WARNING: couldn't find offset 0x%lx in binary!\n", r);
48 | return 0;
49 | }
50 |
51 |
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/dsdump/XRMachOLibrary+FileManagement.m:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary+FileManagement.m
3 | // xref
4 | //
5 | // Created by Derek Selander on 4/10/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import "XRMachOLibrary.h"
10 | #import
11 |
12 | //#define PAYLOAD_FILE_SIZE(c) (sizeof(long) + (sizeof(cs_insn) * (c)) + (sizeof(cs_detail) * (c)))
13 |
14 |
15 | @implementation XRMachOLibrary (FileManagement)
16 |
17 |
18 | ////////////////////////////////////////////////////////////////
19 | // Public methods
20 | ////////////////////////////////////////////////////////////////
21 |
22 |
23 | - (NSString *)translateUUID {
24 | char uuid_output[37];
25 | for (int cur = 0, i = 0; i < 16; i++) {
26 | char c = self.uuid_cmd->uuid[i];
27 | char lower = c & 0xf;
28 | char upper = (c & 0xf0) >> 4;
29 |
30 | if (upper < 10) {
31 | upper += 48;
32 | } else {
33 | upper += 55;
34 | }
35 |
36 | if (lower < 10) {
37 | lower += 48;
38 | } else {
39 | lower += 55;
40 | }
41 | uuid_output[cur++] = upper;
42 | uuid_output[cur++] = lower;
43 | if (i == 3 || i == 5 || i == 7 || i == 9) {
44 | uuid_output[cur++] = '-';
45 | }
46 | uuid_output[cur] = '\x00';
47 | }
48 |
49 | return [NSString stringWithUTF8String:uuid_output];
50 | }
51 |
52 | - (NSString *)analysisSavePath {
53 | return [NSString stringWithFormat:@"/tmp/%@.%@", [self.path lastPathComponent], [self translateUUID]];
54 | }
55 |
56 |
57 | @end
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/dsdump/statusbar.h:
--------------------------------------------------------------------------------
1 | /**
2 | * \file
3 | * \author Trevor Fountain
4 | * \author Johannes Buchner
5 | * \author Erik Garrison
6 | * \date 2010-2014
7 | * \copyright BSD 3-Clause
8 | *
9 | * statusbar -- a C class (by convention) for displaying indefinite progress
10 | * on the command line (to stderr).
11 | */
12 |
13 | #ifndef STATUSBAR_H
14 | #define STATUSBAR_H
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | #ifdef __cplusplus
22 | extern "C" {
23 | #endif
24 |
25 | /**
26 | * Statusbar data structure (do not modify or create directly)
27 | */
28 | typedef struct _statusbar_t
29 | {
30 | unsigned int start_time;
31 | const char *label;
32 | int format_index;
33 | int format_length;
34 | char *format;
35 | int last_printed;
36 | } statusbar;
37 |
38 | /// Create a new statusbar with the specified label and format string
39 | statusbar *statusbar_new_with_format(const char *label, const char *format);
40 |
41 | /// Create a new statusbar with the specified label
42 | statusbar *statusbar_new(const char *label);
43 |
44 | /// Free an existing progress bar. Don't call this directly; call *statusbar_finish* instead.
45 | void statusbar_free(statusbar *bar);
46 |
47 | /// Increment the given statusbar.
48 | void statusbar_inc(statusbar *bar);
49 |
50 | /// Finalize (and free!) a statusbar. Call this when you're done.
51 | void statusbar_finish(statusbar *bar);
52 |
53 | /// Draw a statusbar to the screen. Don't call this directly,
54 | /// as it's called internally by *statusbar_inc*.
55 | void statusbar_draw(statusbar *bar);
56 |
57 | #ifdef __cplusplus
58 | }
59 | #endif
60 |
61 | #endif
62 |
--------------------------------------------------------------------------------
/dsdump/TestSwift.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TestSwift.swift
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 8/26/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Cocoa
11 | // swiftc /Users/lolgrep/code/dsdump/dsdump/TestSwift.swift -sdk `xcrun --show-sdk-path -sdk iphoneos` -target arm64e-apple-ios99.99.99.99 -o /tmp/TestSwift
12 | protocol AProtocol {
13 | func yay()
14 | // func hey()
15 | }
16 |
17 | enum FFF {
18 | case yo
19 | }
20 |
21 | public class SomeVC : NSViewController, AProtocol {
22 | public var someview : NSView!
23 | let h : SomeVC? = nil
24 | let jj : Int32 = 3
25 | var someStr : NSString = "yay some string"
26 | override public func viewDidLoad() {
27 | super.viewDidLoad()
28 | self.someview = NSView()
29 |
30 | }
31 |
32 | override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) {
33 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
34 | }
35 |
36 | required init?(coder: NSCoder) {
37 | fatalError("init(coder:) has not been implemented")
38 | }
39 |
40 | public func yay() {
41 |
42 | }
43 | }
44 |
45 |
46 | /*
47 | private class PrivateClass {
48 |
49 | }
50 |
51 | public enum WootYeah {
52 | case some
53 | case test
54 | }
55 |
56 | @_cdecl("do_stuff")
57 | public func meh() {
58 | let a = SomeTest()
59 | print("\(a)")
60 |
61 | }
62 |
63 | public class SomeTest {
64 | // var blah : String!
65 | var numa : Int = 0
66 | var numb : Int = 2
67 | var numc : Int = 4
68 |
69 | func somefunc() {}
70 | public func yay() {
71 | print("do stuff")
72 |
73 | }
74 | func hey() { }
75 |
76 | }
77 |
78 | extension SomeTest: AProtocol {
79 |
80 | func extensionTest() {
81 | print("\(#function)")
82 | }
83 | }
84 | */
85 |
--------------------------------------------------------------------------------
/dsdump/objc_.mm:
--------------------------------------------------------------------------------
1 | //
2 | // objc_.cpp
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 7/4/20.
6 | // Copyright © 2020 Selander. All rights reserved.
7 | //
8 | #import
9 | #import "objc_.h"
10 |
11 | static bool useRelativeMethUsage(void) {
12 | static dispatch_once_t onceToken;
13 | static bool useRelativeMeth = false;
14 | dispatch_once(&onceToken, ^{
15 | auto section = payload::sectionsDict["__TEXT.__objc_methlist"];
16 | if (section) {
17 | useRelativeMeth = true;
18 | }
19 | });
20 | return useRelativeMeth;
21 | }
22 |
23 | payload::LoadToDiskTranslator* method_t::getName() {
24 |
25 | if (useRelativeMethUsage()) {
26 | auto typeOffsets = payload::DiskWrapper::Cast(this->disk());
27 | auto resolvedAddress = ((intptr_t)typeOffsets[0].disk() + *typeOffsets[0].disk());
28 |
29 | auto cur = payload::CastToDisk(resolvedAddress);
30 | return cur->disk()->name;
31 | }
32 | return this->name;
33 | }
34 | payload::LoadToDiskTranslator* method_t::getTypes() {
35 | if (useRelativeMethUsage()) {
36 | auto typeOffsets = payload::DiskWrapper::Cast(this->disk());
37 | auto resolvedAddress = ((intptr_t)typeOffsets[1].disk() + *typeOffsets[1].disk());
38 | auto cur = payload::CastToDisk(resolvedAddress);
39 | return cur;
40 | }
41 | return this->types;
42 | }
43 | payload::LoadToDiskTranslator* method_t::getImp() {
44 | if (useRelativeMethUsage()) {
45 | auto typeOffsets = payload::DiskWrapper::Cast(this->disk());
46 |
47 | auto resolvedAddress = ((intptr_t)typeOffsets[2].disk() + *typeOffsets[2].disk());
48 |
49 | auto impPointer = reinterpret_cast*>(resolvedAddress);
50 | return impPointer;
51 | }
52 | return this->imp;
53 | }
54 |
55 | method_t* method_list::GetMethod(int i, bool isProtocol) {
56 | auto startAddress = &this->first_method;
57 | if (!isProtocol && useRelativeMethUsage()) {
58 |
59 | // TODO This is for 64 bit only, probably would never get to 32 bit... : ]
60 | auto addr = reinterpret_cast(startAddress) + (i * (sizeof(int32_t) * 3));
61 | return reinterpret_cast(addr);
62 | }
63 | return &startAddress[i];
64 | }
65 |
--------------------------------------------------------------------------------
/dsdump/miscellaneous.h:
--------------------------------------------------------------------------------
1 | //
2 | // miscellaneous.h
3 | // xref
4 | //
5 | // Created by Derek Selander on 3/7/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 |
10 | #ifndef MISCELLANEOUS_H
11 | #define MISCELLANEOUS_H
12 |
13 | #import
14 | #import
15 | #import
16 |
17 | #ifdef __cplusplus
18 |
19 | extern "C" {
20 | #endif
21 |
22 | /// Usage deets
23 | void print_manpage(void);
24 | void print_usage(void);
25 |
26 | __attribute__((weak)) unsigned char __manpage_deets;
27 | /********************************************************************************
28 | /// Globals for exploring multiple references
29 | ********************************************************************************/
30 |
31 | typedef NS_OPTIONS(NSUInteger, DSCOLOR) {
32 | DSCOLOR_CYAN,
33 | DSCOLOR_YELLOW,
34 | DSCOLOR_MAGENTA,
35 | DSCOLOR_RED,
36 | DSCOLOR_PURPLE,
37 | DSCOLOR_BLUE,
38 | DSCOLOR_GRAY,
39 | DSCOLOR_GREEN,
40 | DSCOLOR_DARK_GREEN,
41 | DSCOLOR_BOLD,
42 | DSCOLOR_CYAN_UNDERLINE,
43 | DSCOLOR_PURPLE_BOLD,
44 | DSCOLOR_CYAN_LIGHT,
45 | DSCOLOR_YELLOW_LIGHT,
46 | DSCOLOR_STRONG_RED,
47 | DSCOLOR_LIGHT_BLUE
48 | };
49 | char const* dcolor(DSCOLOR c);
50 |
51 | /// Ends the color option if the DSCOLOR env var is set
52 | char const* color_end(void);
53 |
54 | /// Different levels to logging, opted for a "codesign -vvvv" style
55 | #define VERBOSE_NONE 0
56 | #define VERBOSE_1 1
57 | #define VERBOSE_2 2
58 | #define VERBOSE_3 3
59 | #define VERBOSE_4 4
60 | #define VERBOSE_5 5
61 |
62 | typedef struct {
63 | int verbose;
64 | int undefined;
65 | int objectiveC_mode;
66 | int swift_mode;
67 | int symbol_mode;
68 | int all_symbols;
69 | int defined;
70 | int color;
71 | int use_regex;
72 | int external;
73 | int analyze;
74 | uintptr_t file_offset;
75 | uintptr_t virtual_address;
76 | int virtual_address_count;
77 | int library;
78 | char * arch;
79 | int debug;
80 | int help;
81 | int opcodes;
82 | int demangle_mode;
83 | } xref_options_t;
84 |
85 | extern xref_options_t xref_options;
86 |
87 |
88 | /// Read unsigned leb128 coding
89 | const uint8_t *r_uleb128_decode(uint8_t *data, int *datalen, uint64_t *v);
90 |
91 | /// Read signed leb128 coding
92 | const uintptr_t r_sleb128_decode(uint8_t *byte, uintptr_t* shift, uint64_t *v);
93 |
94 | /// Used to check for class filtering
95 | BOOL ContainsFilteredWords(const char *word);
96 |
97 | /// Used to input filters for checking for filtering
98 | void AddFilter(char * filter);
99 |
100 | /// Only print when DEBUG env var is set
101 | void warn_debug(const char *format, ...);
102 |
103 | #ifdef __cplusplus
104 | }
105 | #endif
106 |
107 | /// sizeof pointer, 64 bit only
108 | #define PTR_SIZE sizeof(void*)
109 |
110 | /// Only print if DEBUG flag is set
111 | #define DEBUG_PRINT(fmt, args...) if (xref_options.opcodes) { printf(fmt, ## args); }
112 |
113 | #endif // MISCELLANEOUS_H
114 |
--------------------------------------------------------------------------------
/dsdump/statusbar.c:
--------------------------------------------------------------------------------
1 | /**
2 | * \file
3 | * \author Trevor Fountain
4 | * \author Johannes Buchner
5 | * \author Erik Garrison
6 | * \date 2010-2014
7 | * \copyright BSD 3-Clause
8 | *
9 | * statusbar -- a C class (by convention) for displaying progress
10 | * on the command line (to stderr).
11 | */
12 | #include "statusbar.h"
13 |
14 | statusbar *statusbar_new_with_format(const char *label, const char *format)
15 | {
16 | statusbar *new = malloc(sizeof(statusbar));
17 | if(new == NULL) {
18 | return NULL;
19 | }
20 |
21 | new->label = label;
22 | new->start_time = (unsigned int)time(0);
23 | new->format_length = (unsigned int)strlen(format);
24 | new->format = malloc( sizeof(char) * (new->format_length + 1) );
25 | if(new->format == NULL) {
26 | free(new);
27 | return NULL;
28 | }
29 |
30 | strncpy(new->format, format, new->format_length);
31 | new->format_index = 0;
32 | new->last_printed = 0;
33 |
34 | return new;
35 | }
36 |
37 | statusbar *statusbar_new(const char *label)
38 | {
39 | return statusbar_new_with_format(label, "-\\|/");
40 | }
41 |
42 | void statusbar_free(statusbar *bar)
43 | {
44 | // We malloc'd a string, so let's be sure to free it...
45 | free(bar->format);
46 | // ...before we free the struct itself.
47 | free(bar);
48 |
49 | return;
50 | }
51 |
52 | void statusbar_inc(statusbar *bar)
53 | {
54 | bar->format_index++;
55 | if (bar->format_index >= bar->format_length) {
56 | bar->format_index = 0;
57 | }
58 | statusbar_draw(bar);
59 |
60 | return;
61 | }
62 |
63 | void statusbar_draw(statusbar *bar)
64 | {
65 | // Erase the last draw. If anything else has been printed to stderr,
66 | // things are going to look mighty interesting...
67 | for(int i=0; i < bar->last_printed; i++) {
68 | fprintf(stderr,"\b");
69 | }
70 |
71 | fprintf(
72 | stderr,
73 | "%s: %c%n",
74 | bar->label,
75 | bar->format[bar->format_index],
76 | &(bar->last_printed)
77 | );
78 |
79 | return;
80 | }
81 |
82 | void statusbar_finish(statusbar *bar)
83 | {
84 | // Draw one more time, with the actual time to completion.
85 | unsigned int offset = (unsigned int)(time(0) - (bar->start_time));
86 |
87 | // Convert the time to display into HHH:MM:SS
88 | unsigned int h = offset/3600;
89 | offset -= h*3600;
90 | unsigned int m = offset/60;
91 | offset -= m*60;
92 | unsigned int s = offset;
93 |
94 | // Erase the last draw
95 | for(int i=0; i < bar->last_printed; i++) {
96 | fprintf(stderr,"\b");
97 | }
98 |
99 | // Calculate number of spaces for right-justified time to completion
100 | fprintf(stderr,"%s: %3d:%02d:%02d%n",bar->label,h,m,s,&(bar->last_printed));
101 | for(int i=0; i < bar->last_printed; i++) {
102 | fprintf(stderr,"\b");
103 | }
104 |
105 | // Print right-justified
106 | fprintf(stderr,"%s: ",bar->label);
107 | for(int i=0; i < (80 - (bar->last_printed)); i++) {
108 | fprintf(stderr," ");
109 | }
110 | fprintf(stderr,"%3d:%02d:%02d\n",h,m,s);
111 |
112 | // We've finished with this statusbar, so go ahead and free it.
113 | statusbar_free(bar);
114 |
115 | return;
116 | }
117 |
--------------------------------------------------------------------------------
/dsdump.xcodeproj/xcshareddata/xcschemes/Generate Build.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
70 |
76 |
77 |
78 |
79 |
81 |
82 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/dsdump/progressbar.h:
--------------------------------------------------------------------------------
1 | /**
2 | * \file
3 | * \author Trevor Fountain
4 | * \author Johannes Buchner
5 | * \author Erik Garrison
6 | * \date 2010-2014
7 | * \copyright BSD 3-Clause
8 | *
9 | * progressbar -- a C class (by convention) for displaying progress
10 | * on the command line (to stderr).
11 | */
12 |
13 | #ifndef PROGRESSBAR_H
14 | #define PROGRESSBAR_H
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 |
21 | #ifdef __cplusplus
22 | extern "C" {
23 | #endif
24 |
25 | /**
26 | * Progressbar data structure (do not modify or create directly)
27 | */
28 | typedef struct _progressbar_t
29 | {
30 | /// maximum value
31 | unsigned long max;
32 | /// current value
33 | unsigned long value;
34 |
35 | /// time progressbar was started
36 | time_t start;
37 |
38 | /// label
39 | const char *label;
40 |
41 | /// characters for the beginning, filling and end of the
42 | /// progressbar. E.g. |### | has |#|
43 | struct {
44 | char begin;
45 | char fill;
46 | char end;
47 | } format;
48 | } progressbar;
49 |
50 | /// Create a new progressbar with the specified label and number of steps.
51 | ///
52 | /// @param label The label that will prefix the progressbar.
53 | /// @param max The number of times the progressbar must be incremented before it is considered complete,
54 | /// or, in other words, the number of tasks that this progressbar is tracking.
55 | ///
56 | /// @return A progressbar configured with the provided arguments. Note that the user is responsible for disposing
57 | /// of the progressbar via progressbar_finish when finished with the object.
58 | progressbar *progressbar_new(const char *label, unsigned long max);
59 |
60 | /// Create a new progressbar with the specified label, number of steps, and format string.
61 | ///
62 | /// @param label The label that will prefix the progressbar.
63 | /// @param max The number of times the progressbar must be incremented before it is considered complete,
64 | /// or, in other words, the number of tasks that this progressbar is tracking.
65 | /// @param format The format of the progressbar. The string provided must be three characters, and it will
66 | /// be interpretted with the first character as the left border of the bar, the second
67 | /// character of the bar and the third character as the right border of the bar. For example,
68 | /// "<->" would result in a bar formatted like "<------ >".
69 | ///
70 | /// @return A progressbar configured with the provided arguments. Note that the user is responsible for disposing
71 | /// of the progressbar via progressbar_finish when finished with the object.
72 | progressbar *progressbar_new_with_format(const char *label, unsigned long max, const char *format);
73 |
74 | /// Free an existing progress bar. Don't call this directly; call *progressbar_finish* instead.
75 | void progressbar_free(progressbar *bar);
76 |
77 | /// Increment the given progressbar. Don't increment past the initialized # of steps, though.
78 | void progressbar_inc(progressbar *bar);
79 |
80 | /// Set the current status on the given progressbar.
81 | void progressbar_update(progressbar *bar, unsigned long value);
82 |
83 | /// Set the label of the progressbar. Note that no rendering is done. The label is simply set so that the next
84 | /// rendering will use the new label. To immediately see the new label, call progressbar_draw.
85 | /// Does not update display or copy the label
86 | void progressbar_update_label(progressbar *bar, const char *label);
87 |
88 | /// Finalize (and free!) a progressbar. Call this when you're done, or if you break out
89 | /// partway through.
90 | void progressbar_finish(progressbar *bar);
91 |
92 | #ifdef __cplusplus
93 | }
94 | #endif
95 |
96 | #endif
97 |
--------------------------------------------------------------------------------
/dsdump/XRMachOLibraryCplusHelpers.h:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibraryCplusHelpers.h
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 6/4/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #ifndef XRMachOLibraryCplusHelpers_h
10 | #define XRMachOLibraryCplusHelpers_h
11 |
12 | #import "XRMachOLibrary.h"
13 | #import "payload.hpp"
14 |
15 | #pragma clang diagnostic push
16 | #pragma clang diagnostic ignored "-Weverything"
17 |
18 | //#define protected public
19 | //#define private public
20 | //#define class struct
21 |
22 | #import "swift/Demangling/Demangler.h"
23 |
24 | //#undef protected
25 | //#undef private
26 | //#undef class
27 |
28 |
29 | #pragma clang diagnostic pop
30 |
31 |
32 | namespace dshelpers {
33 | extern swift::Demangle::DemangleOptions simplifiedOptions;
34 | extern Context context;
35 |
36 | const char *simple_demangle(const char *mangled, std::string &strout_ref, swift::Demangle::DemangleOptions options = dshelpers::simplifiedOptions);
37 | bool canDemangle(StringRef mangled);
38 | const char *simple_demangle(char *mangled, std::string &strout_ref, swift::Demangle::DemangleOptions options = dshelpers::simplifiedOptions);
39 | const char *simple_demangle(StringRef mangled, std::string &strout_ref, swift::Demangle::DemangleOptions options = dshelpers::simplifiedOptions);
40 |
41 | // Compact mode: display module names or implicit self types in addition to demangled names
42 | const char *compact_demangle(char *mangled, std::string &strout_ref);
43 |
44 | // const char *simple_type(StringRef type);
45 | const char *simple_type(StringRef type, std::string &strout_ref);
46 | const char *simple_type(char* type, std::string &strout_ref);
47 | const char *simple_type(const char* type, std::string &strout_ref);
48 |
49 |
50 | template
51 | T LoadToOffsetDeref(XRMachOLibrary *library, T* t) {
52 | uintptr_t loadAddress = reinterpret_cast(t);
53 | uintptr_t fileOff = [library translateLoadAddressToFileOffset:loadAddress useFatOffset:YES];
54 | T retT = *reinterpret_cast(&payload::data[fileOff]);
55 | return retT;
56 | }
57 |
58 | template
59 | T LoadToOffset(XRMachOLibrary *library, T t) {
60 | uintptr_t loadAddress = *reinterpret_cast(&t); // TODO find a better way than this...
61 | uintptr_t fileOff = [library translateLoadAddressToFileOffset:(loadAddress) useFatOffset:YES];
62 | T retT = reinterpret_cast(&payload::data[fileOff]);
63 | return retT;
64 | }
65 |
66 | template
67 | T OffsetToLoad(XRMachOLibrary *library, T t) {
68 | uintptr_t offset = *reinterpret_cast(&t);
69 | uintptr_t loadAddress = [library translateOffsetToLoadAddress:offset - (uintptr_t)&payload::data[0]];
70 | T retT = *reinterpret_cast(&loadAddress);
71 | return retT;
72 | }
73 |
74 |
75 |
76 |
77 | // template (t);
80 | //
81 | // uintptr_t fileOff = [library translateLoadAddressToFileOffset:loadAddress useFatOffset:YES];
82 | // T retT = reinterpret_cast(&library.data[fileOff]);
83 | // return retT;
84 | // }
85 |
86 | // ValueTy diskOff(uint8_t *data) {
87 | // DAT
88 | }
89 |
90 |
91 |
92 | #define TODISK(addr) dshelpers::LoadToOffset(self, addr)
93 |
94 | #define TODISKDEREF(addr) dshelpers::LoadToOffsetDeref(self, addr)
95 |
96 | #define FROMDISK(addr) dshelpers::OffsetToLoad(self, addr)
97 |
98 | //#define FROM(addr) dshelpers::LoadToOffsetDeref(self, addr)
99 |
100 | #endif /* XRMachOLibraryCplusHelpers_h */
101 |
--------------------------------------------------------------------------------
/dsdump/Methods.mm:
--------------------------------------------------------------------------------
1 | //
2 | // Methods.cpp
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 4/29/20.
6 | // Copyright © 2020 Selander. All rights reserved.
7 | //
8 |
9 | #include "Methods.h"
10 | char *
11 | encoding_copyArgumentType(const char *t, unsigned int index);
12 |
13 | char *
14 | encoding_copyReturnType(const char *t);
15 |
16 | void
17 | encoding_getArgumentType(const char *t, unsigned int index,
18 | char *dst, size_t dst_len);
19 |
20 | void
21 | encoding_getReturnType(const char *t, char *dst, size_t dst_len);
22 |
23 | unsigned int
24 | encoding_getArgumentInfo(const char *typedesc, unsigned int arg,
25 | const char **type, int *offset);
26 |
27 | unsigned
28 | encoding_getSizeOfArguments(const char *typedesc);
29 |
30 | unsigned int
31 | encoding_getNumberOfArguments(const char *typedesc);
32 |
33 | extern NSDictionary *blacklistedSelectors;
34 |
35 | void dumpObjectiveCMethods(method_list_t* methodList, const char *name, bool isMeta, bool isProtocol, const char * overrideColor) {
36 |
37 | if (methodList == nullptr) {
38 | return;
39 | }
40 |
41 | auto methodListDisk = methodList->disk();
42 | auto count = methodListDisk->count;
43 | if (xref_options.verbose > VERBOSE_2) {
44 | printf(" %s// %s methods%s\n", dcolor(DSCOLOR_GRAY), isMeta ? "class" : "instance", color_end());
45 | }
46 |
47 | for (int i = 0; i < count; i++) {
48 | auto method = methodListDisk->GetMethod(i, isProtocol); //&methods[i];
49 |
50 | auto methodName = isProtocol ? method->name->disk() : method->getName()->disk();
51 | if (blacklistedSelectors[[NSString stringWithUTF8String:methodName]]) {
52 | continue;
53 | }
54 |
55 | uintptr_t methodAddress = isProtocol ? method->imp->strip_PAC() : (uintptr_t)method->getImp()->load();
56 | auto types = isProtocol ? method->types->disk() : method->getTypes()->disk();
57 | auto numArguments = encoding_getNumberOfArguments(types);
58 |
59 | char path[1024];
60 | encoding_getReturnType(types, path, 1024);
61 |
62 | putchar(' ');
63 | if (xref_options.verbose > VERBOSE_2 && !isProtocol) {
64 | printf(" %s0x%011lx%s ", overrideColor ? overrideColor: dcolor(DSCOLOR_GRAY), (unsigned long)methodAddress, color_end());
65 | }
66 |
67 | if (xref_options.verbose <= VERBOSE_4) {
68 | printf("%s%c[%s %s]%s\n", overrideColor? overrideColor : dcolor(DSCOLOR_BOLD), "-+"[isMeta ? 1 : 0], name, methodName, color_end());
69 | continue;
70 | }
71 | printf("%c(%s%s%s)", "-+"[isMeta ? 1 : 0], overrideColor? overrideColor : dcolor(DSCOLOR_BOLD), translate_method_type_to_string(path), color_end());
72 |
73 | // if (isProtocol) {
74 | // printf("\t%s%c[%s %s\n", dcolor(DSCOLOR_BOLD), "-+"[isMeta ? 1 : 0], name, color_end());
75 | // } else {
76 | // printf("%s%c[%s %s]%s\n", dcolor(DSCOLOR_BOLD), "-+"[isMeta ? 1 : 0], name, methodName, color_end());
77 | // }
78 | long index = 0; // (int)(h - methodName);
79 | auto len = strlen(methodName);
80 | for (int i = 0; i < numArguments && index < len; i++) {
81 | auto found = strchr(&methodName[index], ':');
82 | if (!found) { // hit end of str or no args
83 | printf("%s%s%s", overrideColor ? overrideColor : dcolor(DSCOLOR_BOLD), &methodName[index], color_end());
84 | break;
85 | }
86 | found++;
87 | auto cur = (found - &methodName[index]);
88 | char dest[1024] = {};
89 | encoding_getArgumentType(types, i, dest, 1024);
90 | printf("%s%.*s(%s)%sarg%d", overrideColor ? overrideColor : dcolor(DSCOLOR_BOLD), (int)cur, &methodName[index], translate_method_type_to_string(dest), color_end(), i+1);
91 | index = (found - methodName);
92 | if (i < numArguments - 1) {
93 | putchar(' ');
94 | }
95 | }
96 | putchar('\n');
97 | }
98 |
99 | if (xref_options.verbose > VERBOSE_2) {
100 | putchar('\n');
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/dsdump/XRMachOLibrary.h:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary.h
3 | // xref
4 | //
5 | // Created by Derek Selander on 3/7/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 |
10 | #import "miscellaneous.h"
11 | #import "XRMachOLibrary.h"
12 | #import "XRBindSymbol.h"
13 |
14 | #import
15 | #import
16 | #import
17 | #import
18 |
19 | #define DATABUF(offset) ((void*)&payload::data[(offset)])
20 |
21 | NS_ASSUME_NONNULL_BEGIN
22 |
23 | extern NSMutableSet *pathsSet;
24 | extern NSMutableSet *exploredSet;
25 | extern NSMutableSet *rpathSet;
26 |
27 | @class XRSymbolEntry;
28 |
29 | /// Deal with 32/64 in one value
30 | typedef union {
31 | struct mach_header_64 h64;
32 | struct mach_header h;
33 | } macho_generic_header;
34 |
35 |
36 | typedef struct {
37 | long count;
38 | uint32_t *indirect_sym;
39 | } indirect_symbols_t;
40 |
41 | // An authenticated pointer is:
42 | typedef struct {
43 | // {
44 | int32_t addend;
45 | uint16_t diversityData;
46 | uint16_t hasAddressDiversity : 1;
47 | uint16_t key : 2;
48 | uint16_t zeroes : 11;
49 | uint16_t zero : 1;
50 | uint16_t authenticated : 1;
51 | } PACPointer;
52 |
53 | #ifdef __cplusplus
54 | extern "C" {
55 | #endif
56 |
57 |
58 | #ifdef __cplusplus
59 | }
60 | #endif
61 |
62 |
63 | @interface XRMachOLibrary : NSObject {
64 | size_t _instructions_count;
65 | }
66 |
67 | /// Library dependencies
68 | @property (nonatomic, strong) NSMutableArray *depdencies;
69 | @property (nonatomic, copy) NSString *path;
70 |
71 |
72 |
73 | /// File descriptor
74 | @property (nonatomic, assign) int fd;
75 |
76 |
77 | @property (nonatomic, assign) struct mach_header_64* header;
78 |
79 | @property (nonatomic, strong) NSMutableDictionary *stringObjCDictionary;
80 | @property (nonatomic, strong) NSMutableDictionary *addressObjCDictionary;
81 | @property (nonatomic, strong) NSMutableArray * threadedHolder;
82 |
83 | @property (nonatomic, strong) NSMutableDictionary *addressSymbolDictionary;
84 | @property (nonatomic, strong) NSMutableDictionary *externalObjectiveClassesDict;
85 |
86 | /// The initial MachO command to dictate the file, other ivars will reference offsets of this
87 | //@property (nonatomic, assign) void *load_cmd_buffer;
88 |
89 |
90 | /// Offsets into each load command struct section
91 | @property (nonatomic, strong) NSMutableArray * sectionCommandsArray;
92 | @property (nonatomic, strong) NSMutableArray * segmentCommandsArray;
93 |
94 | @property (nonatomic, strong) NSMutableDictionary * segmentCommandsDictionary;
95 |
96 |
97 | @property (nonatomic, assign) struct build_version_command *build_cmd;
98 | @property (nonatomic, assign) struct version_min_command *version_cmd;
99 | @property (nonatomic, assign) struct uuid_command *uuid_cmd;
100 |
101 | @property (nonatomic, assign) struct symtab_command *symtab;
102 | @property (nonatomic, assign) struct dysymtab_command *dysymtab;
103 | @property (nonatomic, assign) struct nlist_64 *symbols;
104 | @property (nonatomic, assign) char *str_symbols;
105 |
106 | @property (nonatomic, strong) NSMutableDictionary*symbolEntry;
107 |
108 |
109 |
110 | ///
111 | @property (nonatomic, assign) struct linkedit_data_command *function_starts_cmd;
112 |
113 | /// __DATA.__la_symbol_ptr Mach-O section
114 | @property (nonatomic, assign) struct section_64 *lazy_ptr_section;
115 |
116 |
117 | @property (nonatomic, assign) struct dyld_info_command *dyldInfo;
118 |
119 | /// The indirect symbol table *int that points to actual symbols
120 | @property (nonatomic, assign) indirect_symbols_t indirect_symbols;
121 |
122 | - (instancetype)initWithPath:(NSString*)path;
123 | - (NSString *)realizedPath;
124 | - (uintptr_t)translateLoadAddressToFileOffset:(uintptr_t)loadAddress useFatOffset:(BOOL)useFatOffset;
125 | - (uintptr_t)translateOffsetToLoadAddress:(uintptr_t)offset;
126 |
127 | @end
128 |
129 |
130 | /// File handling logic
131 | @interface XRMachOLibrary (FileManagement)
132 |
133 |
134 | @end
135 |
136 | NS_ASSUME_NONNULL_END
137 |
--------------------------------------------------------------------------------
/dsdump/dsdump.1:
--------------------------------------------------------------------------------
1 | .Dd __DATE__
2 | .Dt dsdump 1
3 | .Os Darwin
4 | .Sh NAME
5 | .Nm dsdump
6 | .Nd An improved nm + objc/swift class-dump
7 | .Sh SYNOPSIS
8 | .Nm
9 | .Op option...
10 | .Ar
11 | .Sh DESCRIPTION
12 | Provides an "nm-improved" experience when working with Mach-O executables. dsdump has 6 "primary" modes: Symbol table (--sym), Objective-C (--objc), Swift (--swift, -s), File Offset => Virtual Address (--offset, -F), Virtual Address => File Offset (--virtual, -A), Library reference (--library, -l). Omitting all of these options will default to the symbol table mode.
13 | .Sh OPTIONS
14 | .Bl -tag -width indent
15 | .It Fl c, -color
16 | Adds color to output
17 | .It Fl l, -library
18 | Instead of dumping symbols, search all procs for library
19 | .It Fl A, -virtual Ar VirtualAddress(hex)
20 | Converts to the virtual address to the file offset
21 | .It Fl F, -offset Ar FileOffset(hex)
22 | Converts to the file offset to the virtual address
23 | .It Fl O, -opcs
24 | Dump the DYLD opcodes used to bind external symbols at load time
25 | .It Fl f, -filter Ar FilterWord
26 | Specify classes to filter by (case insensitive, can be used multiple times)
27 | .It Fl a, -arch Ar architecture
28 | Specify the arichtecture if file is FAT. Understands x86_64h, x86_64, arm64, arm64e
29 | .It Fl u, -undefined
30 | Only display undefined (externally referenced) symbols or classes
31 | .It Fl U, -defined
32 | Only display defined (internally implemented) symbols or classes
33 | .It Fl v, -verbose
34 | Specifies the verbosity level. The -v option can be used multiple times, while the long argument sets the exact level 0-5. Kind of like codesign(1)'s verbosity that everyone complains about...
35 | .It Fl -objc
36 | Dump the Objective-C classes
37 | .It Fl -swift
38 | Dump the Swift type descriptors (classes, structs, enums)
39 | .It Fl s
40 | Sets mode to Swift mode and verbosity to level 4
41 | .It Fl h, -help
42 | Print out this beautiful, helpful document
43 | .El
44 | .Sh EXAMPLES
45 | List ObjC internal/external classes referenced/implemented by vmmap:
46 | .Dl dsdump --objc $(which vmmap)
47 | .Pp
48 | List all alive processes that have the MobileDevice loaded
49 | .Dl sudo dsdump -l /S*/L*/P*/MobileDevice.framework/MobileDevice
50 | .Pp
51 | List the Objective-C external classes called by vmmap:
52 | .Dl dsdump --objc $(which vmmap) -u
53 | .Pp
54 | List the Objective-C internal classes implemented by vmmap:
55 | .Dl dsdump --objc $(which vmmap) -U
56 | .Pp
57 | Perform an Objective-C "class-dump" in color of vmmap
58 | .Dl dsdump --objc $(which vmmap) -U -vvvc
59 | .Pp
60 | Thoroughly dump the Swift content in color in the Console app
61 | .Dl dsdump --swift /Applications/Utilities/Console.app/Contents/MacOS/Console -cvvvv
62 | .Pp
63 | .Sh VERBOSITY
64 | dsdump can output a range of verbosity between the 3 different modes (--sym, --swift, --objc). The verbosity level can be set by the long form (--verbose=3) or by specifying a count via short form (-vvv). The breakdown of these levels are shown below:
65 | .Pp
66 | --sym:
67 | .Dl 0. Print symbol
68 | .Dl 1. 0 + library path or Mach-O section
69 | .Dl 2. 1 + fullpath to library
70 | .Dl 3. 2 + nlist struct output
71 | .Dl 4. Same as 3... for now
72 | .Dl 5. Same as 3... for now
73 | .Pp
74 | --swift:
75 | .Dl 0. List swift types
76 | .Dl 1. 0 + Parent classes
77 | .Dl 2. 1 + Protocols
78 | .Dl 3. 2 + Swift "type dump"
79 | .Dl 4. 3 + Extended type dump, ObjC bridge methods
80 | .Dl 5. 4 + Commenting in methods
81 | .Pp
82 | --objc:
83 | .Dl 0. List Objective-C classes
84 | .Dl 1. 0 + Parent classes & library basename for external
85 | .Dl 2. 1 + Fullpath to libraries for external + protocols
86 | .Dl 3. 2 + Objective-C "class dump"
87 | .Dl 4. 3 + Print properties
88 | .Dl 5. 4 + Print ivars & offsets
89 | .Pp
90 | .Sh ENVIRONMENT
91 | .Pp
92 | .Bl -tag -width indent
93 | .Ev DSCOLOR
94 | Enables color. Alternatively, use -c
95 | .Pp
96 | .Ev ARCH
97 | .Ar
98 | Specify the architecture if inspecting a FAT executable, Alternatively use --arch
99 | .El
100 | .Sh SEE ALSO
101 | .Xr nm 1 ,
102 | .Xr objdump 1 ,
103 | .Xr vmmap 1
104 | .Sh BUGS
105 | There's a situation where occassionally dsdump will think the parent class is a RO_ROOT where it will in fact won't be. I'll print this out for now so I can hunt it down
106 | .Pp
107 | ARM64e still needs some luv, especially on the Swift side, especially with Protocols... and not crashing
108 | .Sh AUTHORS
109 | .An "Derek Selander"
110 | .Mt @LOLgrep
111 |
--------------------------------------------------------------------------------
/dsdump/XRMachOLibrary+Disassemble.mm:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary+Disassemble.m
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 9/27/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import "XRMachOLibrary+Disassemble.h"
10 |
11 | /////////////////////////////////////////////////////////
12 | // muwahahahahahaha going to hell for this...
13 | #pragma clang diagnostic push
14 | #pragma clang diagnostic ignored "-Weverything"
15 | #import "capstone.h"
16 | #pragma clang diagnostic pop
17 | //
18 |
19 | #import
20 |
21 |
22 | @implementation XRMachOLibrary (Disassemble)
23 |
24 | - (uintptr_t *)resolveMetadataFromCode:(uintptr_t)address {
25 |
26 | cs_arch arch = self.header->cputype == CPU_TYPE_ARM64? CS_ARCH_ARM64 : CS_ARCH_X86;
27 | cs_mode mode = self.header->cputype == CPU_TYPE_ARM64? CS_MODE_LITTLE_ENDIAN : CS_MODE_64;
28 | static csh handle = 0;
29 | static uint8_t *buffer = NULL;
30 | static dispatch_once_t onceToken;
31 | dispatch_once(&onceToken, ^{
32 | int err = cs_open(arch, mode, &handle);
33 | if (err != CS_ERR_OK) {
34 | assert(NO);
35 | }
36 | buffer = (uint8_t*)calloc(1000, sizeof(char)); // some high amount to be safe, particularly for variable ins x86
37 | cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
38 | });
39 |
40 | if (!address) {
41 | return NULL;
42 | }
43 |
44 | cs_insn *instructions = NULL;
45 | cs_disasm(handle, (const uint8_t *)address, 200, address, 20, &instructions);
46 |
47 | // x86_64
48 | if (self.header->cputype == CPU_TYPE_X86_64) {
49 | for (int i = 0; i < 20; i++) {
50 | cs_insn insn = instructions[i];
51 | cs_x86_op *ops = insn.detail->x86.operands;
52 | auto opcount = insn.detail->x86.op_count;
53 | if (opcount == 2 && // Is there 2 operands?
54 | ops[0].type == X86_OP_REG && ops[0].reg == X86_REG_RAX && // is the first operand setting RAX?
55 | ops[1].type == X86_OP_MEM && ops[1].mem.base == X86_REG_RIP) {// is the second operand grabing memory from RIP?
56 | auto displacement = ops[1].mem.disp + insn.size;
57 | auto resolved = displacement + insn.address;
58 | return reinterpret_cast(resolved);
59 | }
60 | }
61 | // ARM64(e)
62 | } else if (self.header->cputype == CPU_TYPE_ARM64 && (self.header->cpusubtype & CPU_SUBTYPE_ARM64E)) {
63 | for (int i = 1; i < 20; i++) {
64 | auto insnADD = instructions[i];
65 | auto insnADRP = instructions[i - 1];
66 |
67 | if (insnADD.detail == nullptr || insnADRP.detail == nullptr) {
68 | if (xref_options.debug) {
69 | printf("DEBUG swift pointer AccessFunction %p\n", (void*)address);
70 | }
71 | continue;
72 | }
73 |
74 | auto insnADDCount = insnADD.detail->arm64.op_count;
75 | auto insnADRPCount = insnADRP.detail->arm64.op_count;
76 |
77 | // Is it ADRP/ADD?
78 | if (insnADD.id != ARM64_INS_ADD && insnADRP.id != ARM64_INS_ADRP) {
79 | continue;
80 | }
81 |
82 | // Does this have the telltale since of the usual ADRP/ADD combo count?
83 | if (insnADDCount != 3 && insnADRPCount != 2) {
84 | continue;
85 | }
86 |
87 | // adrp "x8, #0x400008000"
88 | cs_arm64_op *opsADRP = insnADRP.detail->arm64.operands;
89 | if (opsADRP[0].type != ARM64_OP_REG && opsADRP[1].type != ARM64_OP_IMM) {
90 | continue;
91 | }
92 |
93 | // add "x8, x8, #0x98"
94 | cs_arm64_op *opsADD = insnADD.detail->arm64.operands;
95 | if (opsADD[1].type != ARM64_OP_REG && opsADD[2].type != ARM64_OP_IMM) {
96 | continue;
97 | }
98 |
99 | // does the ADD instruction in use equal the same ADRP register?
100 | if (opsADD[1].reg != opsADRP[0].reg) {
101 | continue;
102 | }
103 |
104 | return (uintptr_t*)(opsADRP[1].imm + opsADD[2].imm);
105 | }
106 | }
107 | return NULL;
108 | }
109 |
110 | @end
111 |
--------------------------------------------------------------------------------
/dsdump/dyld_process_info_internal.h:
--------------------------------------------------------------------------------
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 | *
3 | * Copyright (c) 2016 Apple Inc. All rights reserved.
4 | *
5 | * @APPLE_LICENSE_HEADER_START@
6 | *
7 | * This file contains Original Code and/or Modifications of Original Code
8 | * as defined in and that are subject to the Apple Public Source License
9 | * Version 2.0 (the 'License'). You may not use this file except in
10 | * compliance with the License. Please obtain a copy of the License at
11 | * http://www.opensource.apple.com/apsl/ and read it before using this
12 | * file.
13 | *
14 | * The Original Code and all software distributed under the License are
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 | * Please see the License for the specific language governing rights and
20 | * limitations under the License.
21 | *
22 | * @APPLE_LICENSE_HEADER_END@
23 | */
24 |
25 | #ifndef _DYLD_PROCESS_INFO_INTERNAL_H_
26 | #define _DYLD_PROCESS_INFO_INTERNAL_H_
27 |
28 | #define VIS_HIDDEN __attribute__((visibility("hidden")))
29 |
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 |
38 | struct dyld_all_image_infos_64 {
39 | uint32_t version;
40 | uint32_t infoArrayCount;
41 | std::atomic infoArray;
42 | uint64_t notification;
43 | bool processDetachedFromSharedRegion;
44 | bool libSystemInitialized;
45 | uint32_t paddingToMakeTheSizeCorrectOn32bitAndDoesntAffect64b; // NOT PART OF DYLD_ALL_IMAGE_INFOS!
46 | uint64_t dyldImageLoadAddress;
47 | uint64_t jitInfo;
48 | uint64_t dyldVersion;
49 | uint64_t errorMessage;
50 | uint64_t terminationFlags;
51 | uint64_t coreSymbolicationShmPage;
52 | uint64_t systemOrderFlag;
53 | uint64_t uuidArrayCount;
54 | uint64_t uuidArray;
55 | uint64_t dyldAllImageInfosAddress;
56 | uint64_t initialImageCount;
57 | uint64_t errorKind;
58 | uint64_t errorClientOfDylibPath;
59 | uint64_t errorTargetDylibPath;
60 | uint64_t errorSymbol;
61 | uint64_t sharedCacheSlide;
62 | std::array sharedCacheUUID;
63 | uint64_t sharedCacheBaseAddress;
64 | std::atomic infoArrayChangeTimestamp;
65 | uint64_t dyldPath;
66 | uint32_t notifyMachPorts[8];
67 | uint64_t reserved[9];
68 | uint64_t compact_dyld_image_info_addr;
69 | uint64_t compact_dyld_image_info_size;
70 | };
71 |
72 | struct dyld_image_info_32 {
73 | uint32_t imageLoadAddress;
74 | uint32_t imageFilePath;
75 | uint32_t imageFileModDate;
76 | };
77 | struct dyld_image_info_64 {
78 | uint64_t imageLoadAddress;
79 | uint64_t imageFilePath;
80 | uint64_t imageFileModDate;
81 | };
82 |
83 | #define DYLD_PROCESS_INFO_NOTIFY_MAX_BUFFER_SIZE (32*1024)
84 | #define DYLD_PROCESS_INFO_NOTIFY_LOAD_ID 0x1000
85 | #define DYLD_PROCESS_INFO_NOTIFY_UNLOAD_ID 0x2000
86 | #define DYLD_PROCESS_INFO_NOTIFY_MAIN_ID 0x3000
87 |
88 |
89 | struct dyld_process_info_image_entry {
90 | uuid_t uuid;
91 | uint64_t loadAddress;
92 | uint32_t pathStringOffset;
93 | uint32_t pathLength;
94 | };
95 |
96 | struct dyld_process_info_notify_header {
97 | mach_msg_header_t header;
98 | uint32_t version;
99 | uint32_t imageCount;
100 | uint32_t imagesOffset;
101 | uint32_t stringsOffset;
102 | uint64_t timestamp;
103 | };
104 |
105 | struct dyld_uuid_info {
106 | const struct mach_header* imageLoadAddress; /* base address image is mapped into */
107 | uuid_t imageUUID; /* UUID of image */
108 | };
109 |
110 | #endif // _DYLD_PROCESS_INFO_INTERNAL_H_
111 |
112 |
113 |
--------------------------------------------------------------------------------
/dsdump/Protocols.mm:
--------------------------------------------------------------------------------
1 | //
2 | // Protocols.cpp
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 4/29/20.
6 | // Copyright © 2020 Selander. All rights reserved.
7 | //
8 |
9 | #include "Protocols.h"
10 |
11 |
12 | static BOOL printObjectiveCProtocolsFromProtocol(protocol_t* protocol);
13 | /********************************************************************************
14 | // Protocols
15 | ********************************************************************************/
16 |
17 | void dumpObjectiveCProtocols(void) {
18 | if (xref_options.undefined) {
19 | return;
20 | }
21 | struct section_64* protocolsSection = payload::sectionsDict["__DATA.__objc_protolist"];
22 | if (!protocolsSection) {
23 | protocolsSection = payload::sectionsDict["__DATA_CONST.__objc_protolist"];
24 | }
25 | if (!protocolsSection) {
26 | return;
27 | }
28 |
29 | auto protocolsDisk = payload::LoadToDiskTranslator::Cast(protocolsSection->addr)->disk();
30 | for (int i = 0; i < protocolsSection->size / PTR_SIZE; i++) {
31 | auto protocol = payload::Cast(protocolsDisk[i]);
32 | if (protocol == nullptr) {
33 | continue;
34 | }
35 | auto protocolDisk = protocol->disk();
36 | auto name = protocolDisk->mangledName ? protocolDisk->mangledName->disk() : "BUG DEREK";
37 | if (!ContainsFilteredWords(name)) {
38 | continue;
39 | }
40 | printf("%s@protocol %s%s%s%s", dcolor(DSCOLOR_YELLOW), color_end(), dcolor(DSCOLOR_MAGENTA), name, color_end());
41 | if(!printObjectiveCProtocolsFromProtocol(protocolDisk)) {
42 | putchar('\n');
43 | }
44 |
45 | if (protocolDisk->instanceProperties) {
46 | auto properties = protocolDisk->instanceProperties->disk();
47 | dumpObjCPropertiesWithResolvedAddress(properties);
48 | }
49 |
50 | if (protocolDisk->classMethods) {
51 | auto classMethods = protocolDisk->classMethods->disk();
52 | dumpObjectiveCMethods(classMethods, name, true, true, dcolor(DSCOLOR_YELLOW));
53 | }
54 |
55 | if (protocolDisk->instanceMethods) {
56 | auto instanceMethods = protocolDisk->instanceMethods->disk();
57 | dumpObjectiveCMethods(instanceMethods, name, false, true, dcolor(DSCOLOR_YELLOW));
58 | }
59 |
60 | auto optionalInstanceMethods = protocolDisk->optionalInstanceMethods;
61 | auto optionalClassMethods = protocolDisk->optionalClassMethods;
62 | if (optionalClassMethods || optionalInstanceMethods) {
63 | printf("%s@optional%s\n", dcolor(DSCOLOR_YELLOW), color_end());
64 | }
65 |
66 | dumpObjectiveCMethods(optionalClassMethods, name, true, true, dcolor(DSCOLOR_YELLOW));
67 | dumpObjectiveCMethods(optionalInstanceMethods, name, false, true, dcolor(DSCOLOR_YELLOW));
68 |
69 | printf("%s@end%s\n\n", dcolor(DSCOLOR_YELLOW), color_end());
70 | }
71 | }
72 |
73 |
74 | static BOOL printObjectiveCProtocolsFromProtocol(protocol_t* protocol) {
75 | if (xref_options.verbose <= VERBOSE_1) {
76 | return NO;
77 | }
78 |
79 | if (!protocol->disk()->protocols) {
80 | return NO;
81 | }
82 | auto protocolList = protocol->disk()->protocols->disk();
83 | auto count = protocolList->disk()->count;
84 | if (count == 0) {
85 | return NO;
86 | }
87 |
88 | auto protocols = &protocolList->disk()->first_protocol;
89 | printf("%s <", dcolor(DSCOLOR_YELLOW));
90 |
91 | for (int i = 0; i < count; i++) {
92 | auto prot = protocols[i];
93 | auto mangledName = prot->disk()->mangledName->disk();
94 | printf("%s", mangledName ? mangledName : "");
95 | if (i != count - 1) {
96 | putchar(',');
97 | putchar(' ');
98 | }
99 | }
100 | printf(">\n%s", color_end());
101 |
102 | return YES;
103 | }
104 |
105 | BOOL listProtocolsForObjectiveCClass(protocol_list_t* protocolList) {
106 | if (protocolList == nullptr) {
107 | return NO;
108 | }
109 |
110 | auto count = protocolList->disk()->count;
111 | if (count == 0) {
112 | return NO;
113 | }
114 |
115 | auto protocols = &protocolList->disk()->first_protocol;
116 | printf("%s <", dcolor(DSCOLOR_YELLOW));
117 |
118 | for (int i = 0; i < count; i++) {
119 | auto prot = protocols[i];
120 | auto mangledName = prot->disk()->mangledName->disk();
121 | printf("%s", mangledName ? mangledName : "");
122 | if (i != count - 1) {
123 | putchar(',');
124 | putchar(' ');
125 | }
126 | }
127 | printf(">\n%s", color_end());
128 | return YES;
129 | }
130 |
131 | BOOL listProtocolsForObjectiveCClass(swift_class* cls) {
132 | if (xref_options.verbose <= VERBOSE_1) {
133 | return NO;
134 | }
135 |
136 | auto rodata = cls->disk()->rodata();
137 | if (rodata == nullptr) {
138 | return NO;
139 | }
140 |
141 | auto protocolList = rodata->disk()->baseProtocols;
142 | return listProtocolsForObjectiveCClass(protocolList);
143 | }
144 |
145 |
--------------------------------------------------------------------------------
/dsdump.xcodeproj/xcshareddata/xcschemes/dsdump.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
44 |
46 |
52 |
53 |
54 |
55 |
58 |
59 |
62 |
63 |
66 |
67 |
70 |
71 |
74 |
75 |
78 |
79 |
82 |
83 |
86 |
87 |
90 |
91 |
94 |
95 |
98 |
99 |
100 |
101 |
107 |
109 |
115 |
116 |
117 |
118 |
120 |
121 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/dsdump/miscellaneous.mm:
--------------------------------------------------------------------------------
1 | //
2 | // miscellaneous.m
3 | // xref
4 | //
5 | // Created by Derek Selander on 3/7/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import "miscellaneous.h"
10 | #include
11 | #include
12 | #include
13 | #include
14 | #import "payload.hpp"
15 |
16 | extern "C" {
17 |
18 | #define XSTR(x) STR(x)
19 | #define STR(x) #x
20 |
21 | BOOL quiet_mode = NO;
22 | NSMutableSet *pathsSet = nil;
23 | NSMutableSet *exploredSet = nil;
24 | NSMutableSet *rpathSet = nil;
25 |
26 | xref_options_t xref_options;
27 |
28 | __attribute__((constructor)) static void InitializeStuff() {
29 | pathsSet = [NSMutableSet set];
30 | exploredSet = [NSMutableSet set];
31 | rpathSet = [NSMutableSet set];
32 | }
33 |
34 | /********************************************************************************
35 | // Documentation
36 | ********************************************************************************/
37 |
38 | static const char * dsdump_usage = "dsdump [option..] ";
39 | static const char* dsdump_version = XSTR(DD_VERSION);
40 |
41 |
42 |
43 | void print_manpage() {
44 | printf("%s\n\n", __manpage_deets ? (const char*)&__manpage_deets : dsdump_usage);
45 | }
46 |
47 | void print_usage() {
48 | printf("Version: %s Built: (%s, %s) %s\n", dsdump_version, __TIME__, __DATE__, dsdump_usage);
49 | }
50 |
51 | /********************************************************************************
52 | // Colors!
53 | ********************************************************************************/
54 |
55 | static const std::map colorMap = {
56 | {DSCOLOR_CYAN, "\e[36m"},
57 | {DSCOLOR_GREEN, "\e[92m"},
58 | {DSCOLOR_DARK_GREEN, "\e[32m"},
59 | {DSCOLOR_YELLOW, "\e[33m"},
60 | {DSCOLOR_YELLOW_LIGHT, "\e[93m"},
61 | {DSCOLOR_MAGENTA, "\e[95m"},
62 | {DSCOLOR_PURPLE, "\e[35m"},
63 | {DSCOLOR_RED, "\e[91m"},
64 | {DSCOLOR_STRONG_RED, "\e[31;4m"},
65 | {DSCOLOR_BLUE, "\e[34m"},
66 | {DSCOLOR_GRAY, "\e[90m"},
67 | {DSCOLOR_PURPLE_BOLD, "\e[35;1m"},
68 | {DSCOLOR_LIGHT_BLUE, "\e[94m"},
69 | {DSCOLOR_CYAN_LIGHT,"\e[96m"},
70 | {DSCOLOR_BOLD, "\e[1m"},
71 | {DSCOLOR_CYAN_UNDERLINE, "\033[36;1;4m"}
72 | };
73 |
74 | char const* dcolor(DSCOLOR c) {
75 | static BOOL useColor = NO;
76 | static dispatch_once_t onceToken;
77 | dispatch_once(&onceToken, ^{
78 | if (xref_options.color || getenv("DSCOLOR")) {
79 | useColor = YES;
80 | }
81 | });
82 | if (!useColor) {
83 | return "";
84 | }
85 |
86 | auto color = colorMap.at(c);
87 | if (color) {
88 | return color;
89 | }
90 | return "";
91 | }
92 |
93 | char const* color_end() {
94 | static BOOL useColor = NO;
95 | static dispatch_once_t onceToken;
96 | dispatch_once(&onceToken, ^{
97 | if (xref_options.color || getenv("DSCOLOR")) {
98 | useColor = YES;
99 | }
100 | });
101 | if (useColor) {
102 | return "\e[0m";
103 | }
104 | return "";
105 | }
106 |
107 | void warn_debug(const char *format, ...) {
108 | if (!xref_options.debug) {
109 | return;
110 | }
111 | va_list args;
112 | va_start( args, format );
113 | dprintf(STDERR_FILENO, format, args );
114 | va_end( args );
115 | }
116 |
117 | /********************************************************************************
118 | // Leb128 Encoding
119 | ********************************************************************************/
120 |
121 | /* Read a ULEB128 into a 64-bit word. Return (uint64_t)-1 on overflow
122 | or error. On overflow, skip past the rest of the uleb128. */
123 | uint64_t read_uleb128 (const uint8_t ** offset, const uint8_t * end) {
124 | uint64_t result = 0;
125 | int bit = 0;
126 |
127 | do {
128 | uint64_t b;
129 |
130 | if (*offset == end)
131 | return (uint64_t) -1;
132 |
133 | b = **offset & 0x7f;
134 |
135 | if (bit >= 64 || b << bit >> bit != b) {
136 | result = (uint64_t) -1;
137 | } else {
138 | result |= b << bit;
139 | bit += 7;
140 | }
141 | } while (*(*offset)++ >= 0x80);
142 | return result;
143 | }
144 |
145 | /// Unsigned Leb128
146 | const uint8_t *r_uleb128_decode(uint8_t *data, int *datalen, uint64_t *v) {
147 | uint8_t c = 0xff;
148 | uint64_t s = 0, sum = 0, l = 0;
149 | if (data && *data) {
150 | do {
151 | c = *(data++) & 0xff;
152 | sum |= ((uint64_t) (c & 0x7f) << s);
153 | s += 7;
154 | l++;
155 | } while (c & 0x80);
156 | }
157 | if (v) {*v = sum; }
158 | if (datalen) { *datalen = (int)l; }
159 | return data;
160 | }
161 |
162 | /// Signed Leb128
163 | const uintptr_t r_sleb128_decode(uint8_t *byte, uintptr_t* datalen, uint64_t *v) {
164 | uintptr_t result = 0;
165 | uintptr_t shift = 0;
166 |
167 | size_t size = sizeof(signed int);
168 | uint8_t *cur = byte;
169 | int l =0 ;
170 | do{
171 | l++;
172 | result |= ((0x7f & *cur) << shift);
173 | shift += 7;
174 | } while((*cur & 0x80) != 0);
175 |
176 | /* sign bit of byte is second high order bit (0x40) */
177 | if ((shift < size) && (*cur & 0x80)) {
178 | /* sign extend */
179 | result |= (~0 << shift);
180 | }
181 |
182 | if (v) { *v = result; }
183 | if (datalen) { *datalen = l; }
184 | return result;
185 | }
186 |
187 |
188 |
189 |
190 |
191 |
192 | BOOL ContainsFilteredWords(const char *word) {
193 | static size_t count = 0;
194 | static dispatch_once_t onceToken;
195 | dispatch_once(&onceToken, ^{
196 | count = payload::filters.size();
197 | });
198 |
199 | if (count == 0) {
200 | return YES;
201 | }
202 |
203 | for (auto &it : payload::filters) {
204 | if (strcasestr(word, it)) {
205 | return YES;
206 | }
207 | }
208 | return NO;
209 | }
210 |
211 |
212 | void AddFilter(char * filter) {
213 | payload::filters.insert(filter);
214 | }
215 |
216 | }; // extern "C"
217 |
--------------------------------------------------------------------------------
/dsdump/TaskPath.mm:
--------------------------------------------------------------------------------
1 | //
2 | // TaskPath.mm
3 | // xref
4 | //
5 | // Created by Derek Selander on 5/7/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 |
10 | #import
11 | #import
12 | #import
13 | #import
14 | #import
15 | #import
16 | #import
17 | #import
18 |
19 | extern "C" {
20 |
21 | #import "miscellaneous.h"
22 | BOOL FindLibraryInTask(pid_t task, pid_t pid, const char *search_string, uuid_t uuid, uint64_t *loadAddr, kern_return_t* err);
23 | BOOL isUUIDMatch(task_t task, vm_address_t address, uuid_t uuid);
24 |
25 | void DumpProcessesContainingLibrary(const char *lib_name, uuid_t uuid) {
26 | int pidcount = proc_listallpids(NULL, 0);
27 | int *all_pids = (int*)malloc(pidcount * sizeof(int));
28 | proc_listallpids(all_pids, pidcount);
29 | for (int i = 0; i < pidcount; i++) {
30 | pid_t pid = all_pids[i];
31 | task_t pid_task = TASK_NULL;
32 | kern_return_t kr = task_for_pid(mach_task_self(), pid, &pid_task);
33 |
34 | if (kr != KERN_SUCCESS) { continue; }
35 |
36 |
37 | uint64 loadAddr = 0;
38 | if (!FindLibraryInTask(pid_task, pid, lib_name, uuid, &loadAddr, NULL)) { continue; }
39 |
40 | char buffer[PATH_MAX];
41 | proc_regionfilename(all_pids[i], 0, buffer, PATH_MAX);
42 |
43 |
44 | if (xref_options.verbose >= VERBOSE_1) {
45 | printf("%s0x%012llx%s ", dcolor(DSCOLOR_GRAY), loadAddr, color_end());
46 | }
47 | // TODO figure out basename bug, this gets screwed up on basename(buffer)...
48 | NSString *p;
49 | if (xref_options.verbose >= VERBOSE_2) {
50 | p = [NSString stringWithUTF8String:buffer];
51 | } else {
52 | p = [[NSString stringWithUTF8String:buffer] lastPathComponent];
53 | }
54 |
55 |
56 | printf("%s%d%s", dcolor(DSCOLOR_CYAN), all_pids[i], color_end());
57 | printf(" %s%s%s", dcolor(DSCOLOR_GREEN), [p UTF8String], color_end());
58 | putchar('\n');
59 | }
60 | }
61 |
62 |
63 | BOOL FindLibraryInTask(pid_t task, pid_t pid, const char *search_string, uuid_t uuid, uint64_t *loadAddr, kern_return_t* err) {
64 |
65 | kern_return_t kr = KERN_SUCCESS;
66 | if (loadAddr) { *loadAddr = 0; }
67 |
68 | task_dyld_info_data_t task_dyld_info;
69 | mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
70 | kr = task_info(task, TASK_DYLD_INFO, (task_info_t)&task_dyld_info, &count);
71 | if (kr != KERN_SUCCESS) {
72 | if (err) *err = kr;
73 | return NO;
74 | }
75 |
76 | if (task_dyld_info.all_image_info_addr == MACH_VM_MIN_ADDRESS) {
77 | if (err) *err = -1;
78 | return NO;
79 | }
80 |
81 | if (task_dyld_info.all_image_info_size > sizeof(struct dyld_all_image_infos)) {
82 | if (err) *err = -1;
83 | return NO;
84 | }
85 |
86 | struct dyld_all_image_infos all_image_infos;
87 | mach_vm_size_t readSize = task_dyld_info.all_image_info_size;
88 | if ((kr = mach_vm_read_overwrite(task, task_dyld_info.all_image_info_addr, task_dyld_info.all_image_info_size, (vm_address_t)&all_image_infos, &readSize) ) != KERN_SUCCESS) {
89 | if (err) *err = kr;
90 | return NO;
91 | }
92 |
93 | // Die if lower than 15
94 | if (all_image_infos.version < 0xf) { return NO; }
95 |
96 | uint32_t imageCount = all_image_infos.infoArrayCount;
97 | size_t imageArraySize = imageCount * sizeof(dyld_image_info);
98 | dyld_image_info *imageArray64 = (dyld_image_info *)malloc(imageArraySize);
99 | if ((kr = ::mach_vm_read_overwrite(task, (mach_vm_address_t)all_image_infos.infoArray, imageArraySize, (vm_address_t)imageArray64, &readSize)) != KERN_SUCCESS ) {
100 | if (err) *err = kr;
101 | free(imageArray64);
102 | return NO;
103 | }
104 |
105 | for (int i = 0; i < imageCount; i++) {
106 | char path[PATH_MAX];
107 |
108 | // Just restart, there can be a bad addresses
109 | if (::mach_vm_read_overwrite(task, (mach_vm_address_t)imageArray64[i].imageFilePath, PATH_MAX, (vm_address_t)path, &readSize)) {
110 | continue;
111 | }
112 |
113 | // First checkk for the name of the string
114 | // If we got this far, let's go after the UUID
115 | // DYLD has a uuidArray, but that's only for non-shared cache modules
116 | if (strstr(path, search_string) && isUUIDMatch(task, (vm_address_t)imageArray64[i].imageLoadAddress, uuid)) {
117 | if (loadAddr) {
118 | *loadAddr = (uint64_t)imageArray64[i].imageLoadAddress;
119 | }
120 | free(imageArray64);
121 | return YES;
122 | }
123 | }
124 |
125 | // Just couldn't find it...
126 | if (err) *err = KERN_SUCCESS;
127 | free(imageArray64);
128 | return NO;
129 | }
130 |
131 | BOOL isUUIDMatch(task_t task, vm_address_t address, uuid_t uuid) {
132 | struct mach_header_64 header;
133 | mach_vm_size_t size = 0;
134 | if (::mach_vm_read_overwrite(task, address, sizeof(struct mach_header_64), (vm_address_t)&header, &size)) {
135 | return NO;
136 | }
137 |
138 | if (header.magic != MH_MAGIC_64) {
139 | pid_t pid = 0;
140 | pid_for_task(task, &pid);
141 | warn_debug("Didn't find a 0xfeedfacf in %d, %p\n", pid, address);
142 | return NO;
143 | }
144 |
145 | uintptr_t *pointer = (uintptr_t*)malloc(header.sizeofcmds);
146 | if (::mach_vm_read_overwrite(task, address, header.sizeofcmds, (vm_address_t)pointer, &size)) {
147 | return NO;
148 | }
149 | uintptr_t cur = (((uintptr_t)pointer) + sizeof(mach_header_64));
150 | for (int i = 0; i < header.ncmds; i++) {
151 | load_command *cmd = (load_command *)cur;
152 | if (cmd->cmd == LC_UUID) {
153 | struct uuid_command* uuid_cmd = (struct uuid_command*)cur;
154 | if (strncmp((const char*)&uuid_cmd->uuid, (const char*)uuid, 16) == 0) {
155 | return YES;
156 | }
157 |
158 | }
159 | cur += cmd->cmdsize;
160 | }
161 |
162 | return NO;
163 | }
164 |
165 | } // extern "C" {
166 |
--------------------------------------------------------------------------------
/dsdump/FAT/XRMachOLibrary+FAT.mm:
--------------------------------------------------------------------------------
1 | //
2 | // XRMachOLibrary+FAT.m
3 | // xref
4 | //
5 | // Created by Derek Selander on 5/1/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #import "XRMachOLibrary+FAT.h"
10 | #import "../payload.hpp"
11 | #include
12 | #include
13 |
14 |
15 | @implementation XRMachOLibrary (FAT)
16 |
17 | -(NSString *)nameForCPU:(cpu_type_t)cputype subtype:(cpu_subtype_t)subtype {
18 | if (cputype == CPU_TYPE_X86_64 && subtype & (CPU_SUBTYPE_X86_64_H)) {
19 | return @"x86_64h";
20 | }
21 |
22 | if (cputype == CPU_TYPE_X86_64 && subtype & (CPU_SUBTYPE_X86_64_ALL)) {
23 | return @"x86_64";
24 | }
25 |
26 | if (cputype == CPU_TYPE_X86 && subtype & CPU_SUBTYPE_X86_64_ALL) {
27 | return @"i386";
28 | }
29 |
30 | if (cputype == CPU_TYPE_ARM64 && subtype == CPU_SUBTYPE_ARM64_ALL) {
31 | return @"arm64";
32 | }
33 |
34 | if (cputype == CPU_TYPE_ARM && subtype & CPU_SUBTYPE_ARM_V7) {
35 | return @"armv7";
36 | }
37 |
38 | if (cputype == CPU_TYPE_ARM64 && subtype & CPU_SUBTYPE_ARM64E) {
39 | return @"arm64e";
40 | }
41 |
42 | return [NSString stringWithFormat:@"(?) 0x%x %x", cputype, subtype];
43 | }
44 |
45 | - (intptr_t)offsetForDefaultArchitecture {
46 | return [self offsetForArchitecture:[self defaultArchitectureName] size:NULL];
47 | }
48 |
49 | - (intptr_t)offsetForArchitecture:(NSString *)architecture size:(size_t*)size {
50 | if (!architecture) {
51 | return FAT_OFFSET_BAD_NAME;
52 | }
53 |
54 | auto magic = *payload::GetData(0);
55 | // big endian
56 | struct fat_header *fat = payload::GetData(0); //(void*)payload::data;
57 | if (magic == MH_CIGAM_64 || magic == MH_MAGIC_64) {
58 |
59 | auto mach_header = payload::GetData(0);
60 | cpu_subtype_t cpu_subytpe = mach_header->cpusubtype;
61 | cpu_subytpe = FIX_ENDIAN(cpu_subytpe);
62 |
63 | cpu_type_t cputype = mach_header->cputype;
64 | cputype = FIX_ENDIAN(cputype);
65 |
66 | if ([[self nameForCPU:cputype subtype:cpu_subytpe] isEqualToString:architecture]) {
67 | if (size) {
68 | *size = payload::size;
69 | }
70 | return 0;
71 | } else {
72 | if (size) {
73 | *size = 0;
74 | }
75 | return FAT_OFFSET_BAD_NAME;
76 | }
77 | }
78 |
79 |
80 | if (!(magic == FAT_MAGIC || magic == FAT_CIGAM)) {
81 | if (size) {
82 | *size = 0;
83 | }
84 | return FAT_OFFSET_BAD_NAME;
85 | }
86 |
87 | for (int i = 0; i < FIX_ENDIAN(fat->nfat_arch); i++) {
88 | struct fat_arch *arch = payload::GetData(sizeof(struct fat_header) + sizeof(struct fat_arch) * i);
89 | NSString *ar = [self nameForCPU:FIX_ENDIAN(arch->cputype) subtype:FIX_ENDIAN(arch->cpusubtype)];
90 | if ([ar isEqualToString:architecture]) {
91 | if (size) {
92 | *size = FIX_ENDIAN(arch->size);
93 | }
94 | return FIX_ENDIAN(arch->offset);
95 | }
96 | }
97 | if (size) {
98 | *size = 0;
99 | }
100 | return FAT_OFFSET_BAD_NAME;
101 | }
102 |
103 | -(NSString *)printAllArchitectures {
104 | auto magic = *payload::GetData(0);
105 |
106 | if (magic == MH_CIGAM_64) {
107 | auto machHeader = payload::GetData(0);
108 | NSString *name = [self nameForCPU:htonl(machHeader->cputype) subtype:htonl(machHeader->cpusubtype)];
109 | return [NSString stringWithFormat:@"[ %@ ]", name];
110 | }
111 |
112 | if (magic == MH_MAGIC_64) {
113 | auto machHeader = payload::GetData(0);
114 | NSString *name = [self nameForCPU:machHeader->cputype subtype:machHeader->cpusubtype];
115 | return [NSString stringWithFormat:@"[ %@ ]", name];
116 | }
117 |
118 | NSMutableString *retString = [NSMutableString string];
119 | struct fat_header *fat = payload::GetData(0); // (struct fat_header *)self.data;
120 |
121 | [retString appendString:@"["];
122 | for (int i = 0; i < FIX_ENDIAN(fat->nfat_arch); i++) {
123 | // struct fat_arch *arch = (void*)&self.data[sizeof(struct fat_header) + sizeof(struct fat_arch) * i];
124 | struct fat_arch *arch = payload::GetData(sizeof(struct fat_header) + sizeof(struct fat_arch) * i);
125 | NSString *ar = [self nameForCPU:FIX_ENDIAN(arch->cputype) subtype:FIX_ENDIAN(arch->cpusubtype)];
126 | [retString appendFormat:@" %@ ", ar];
127 | if (i < FIX_ENDIAN(fat->nfat_arch) - 1) {
128 | [retString appendFormat:@"|"];
129 | }
130 | }
131 | [retString appendString:@"]"];
132 |
133 | return retString;
134 |
135 | }
136 |
137 | - (NSString *)defaultArchitectureName {
138 | static cpu_type_t this_cputype;
139 | static cpu_subtype_t this_cpusubtype;
140 | static dispatch_once_t onceToken;
141 | dispatch_once(&onceToken, ^{
142 | size_t len = sizeof(cpu_type_t);
143 | sysctlbyname("hw.cputype", &this_cputype, &len, NULL, 0);
144 | assert(len == sizeof(uint32_t));
145 | len = sizeof(cpu_subtype_t);
146 | sysctlbyname("hw.cpusubtype", &this_cpusubtype, &len, NULL, 0);
147 | assert(len == sizeof(uint32_t));
148 | });
149 |
150 | this_cputype |= CPU_ARCH_ABI64;
151 |
152 | struct fat_header *fat = payload::GetData(0);
153 |
154 | // Let's try the closest to the cpu type first...
155 | for (int i = 0; i < FIX_ENDIAN(fat->nfat_arch); i++) {
156 | auto arch = payload::GetData(sizeof(struct fat_header) + sizeof(struct fat_arch) * i);
157 | if (FIX_ENDIAN(arch->cpusubtype) == this_cpusubtype && (FIX_ENDIAN(arch->cputype) == this_cputype)) {
158 | return [self nameForCPU:FIX_ENDIAN(arch->cputype) subtype:FIX_ENDIAN(arch->cpusubtype)];
159 | }
160 | }
161 |
162 | // If they don't have the right type, try x86_64
163 | for (int i = 0; i < FIX_ENDIAN(fat->nfat_arch); i++) {
164 | auto arch = payload::GetData(sizeof(struct fat_header) + sizeof(struct fat_arch) * i);
165 | if (FIX_ENDIAN(arch->cputype) == CPU_TYPE_X86_64) {
166 | return [self nameForCPU:FIX_ENDIAN(arch->cputype) subtype:FIX_ENDIAN(arch->cpusubtype)];
167 | }
168 | }
169 |
170 | // Really!? OK, first 64 arch now...
171 | for (int i = 0; i < FIX_ENDIAN(fat->nfat_arch); i++) {
172 | auto arch = payload::GetData(sizeof(struct fat_header) + sizeof(struct fat_arch) * i);
173 | if (FIX_ENDIAN(arch->cputype) & CPU_ARCH_ABI64) {
174 | return [self nameForCPU:FIX_ENDIAN(arch->cputype) subtype:FIX_ENDIAN(arch->cpusubtype)];
175 | }
176 | }
177 |
178 | return nil;
179 | }
180 |
181 |
182 | @end
183 |
--------------------------------------------------------------------------------
/dsdump/progressbar.c:
--------------------------------------------------------------------------------
1 | /**
2 | * \file
3 | * \author Trevor Fountain
4 | * \author Johannes Buchner
5 | * \author Erik Garrison
6 | * \date 2010-2014
7 | * \copyright BSD 3-Clause
8 | *
9 | * progressbar -- a C class (by convention) for displaying progress
10 | * on the command line (to stderr).
11 | */
12 |
13 | #include /* tgetent, tgetnum */
14 | #include
15 | #include
16 | #include "progressbar.h"
17 |
18 | /// How wide we assume the screen is if termcap fails.
19 | enum { DEFAULT_SCREEN_WIDTH = 80 };
20 | /// The smallest that the bar can ever be (not including borders)
21 | enum { MINIMUM_BAR_WIDTH = 10 };
22 | /// The format in which the estimated remaining time will be reported
23 | static const char *const ETA_FORMAT = "ETA:%2dh%02dm%02ds";
24 | /// The maximum number of characters that the ETA_FORMAT can ever yield
25 | enum { ETA_FORMAT_LENGTH = 13 };
26 | /// Amount of screen width taken up by whitespace (i.e. whitespace between label/bar/ETA components)
27 | enum { WHITESPACE_LENGTH = 2 };
28 | /// The amount of width taken up by the border of the bar component.
29 | enum { BAR_BORDER_WIDTH = 2 };
30 |
31 | /// Models a duration of time broken into hour/minute/second components. The number of seconds should be less than the
32 | /// number of seconds in one minute, and the number of minutes should be less than the number of minutes in one hour.
33 | typedef struct {
34 | int hours;
35 | int minutes;
36 | int seconds;
37 | } progressbar_time_components;
38 |
39 | static void progressbar_draw(const progressbar *bar);
40 |
41 | /**
42 | * Create a new progress bar with the specified label, max number of steps, and format string.
43 | * Note that `format` must be exactly three characters long, e.g. "<->" to render a progress
44 | * bar like "<---------->". Returns NULL if there isn't enough memory to allocate a progressbar
45 | */
46 | progressbar *progressbar_new_with_format(const char *label, unsigned long max, const char *format)
47 | {
48 | progressbar *new = malloc(sizeof(progressbar));
49 | if(new == NULL) {
50 | return NULL;
51 | }
52 |
53 | new->max = max;
54 | new->value = 0;
55 | new->start = time(NULL);
56 | assert(3 == strlen(format) && "format must be 3 characters in length");
57 | new->format.begin = format[0];
58 | new->format.fill = format[1];
59 | new->format.end = format[2];
60 |
61 | progressbar_update_label(new, label);
62 | progressbar_draw(new);
63 |
64 | return new;
65 | }
66 |
67 | /**
68 | * Create a new progress bar with the specified label and max number of steps.
69 | */
70 | progressbar *progressbar_new(const char *label, unsigned long max)
71 | {
72 | return progressbar_new_with_format(label, max, "|=|");
73 | }
74 |
75 | void progressbar_update_label(progressbar *bar, const char *label)
76 | {
77 | bar->label = label;
78 | }
79 |
80 | /**
81 | * Delete an existing progress bar.
82 | */
83 | void progressbar_free(progressbar *bar)
84 | {
85 | free(bar);
86 | }
87 |
88 | /**
89 | * Increment an existing progressbar by `value` steps.
90 | */
91 | void progressbar_update(progressbar *bar, unsigned long value)
92 | {
93 | bar->value = value;
94 | progressbar_draw(bar);
95 | }
96 |
97 | /**
98 | * Increment an existing progressbar by a single step.
99 | */
100 | void progressbar_inc(progressbar *bar)
101 | {
102 | progressbar_update(bar, bar->value+1);
103 | }
104 |
105 | static void progressbar_write_char(FILE *file, const int ch, const size_t times) {
106 | size_t i;
107 | for (i = 0; i < times; ++i) {
108 | fputc(ch, file);
109 | }
110 | }
111 |
112 | static int progressbar_max(int x, int y) {
113 | return x > y ? x : y;
114 | }
115 |
116 | static unsigned int get_screen_width(void) {
117 | char termbuf[2048];
118 | if (tgetent(termbuf, getenv("TERM")) >= 0) {
119 | return tgetnum("co") /* -2 */;
120 | } else {
121 | return DEFAULT_SCREEN_WIDTH;
122 | }
123 | }
124 |
125 | static int progressbar_bar_width(int screen_width, int label_length) {
126 | return progressbar_max(MINIMUM_BAR_WIDTH, screen_width - label_length - ETA_FORMAT_LENGTH - WHITESPACE_LENGTH);
127 | }
128 |
129 | static int progressbar_label_width(int screen_width, int label_length, int bar_width) {
130 | int eta_width = ETA_FORMAT_LENGTH;
131 |
132 | // If the progressbar is too wide to fit on the screen, we must sacrifice the label.
133 | if (label_length + 1 + bar_width + 1 + ETA_FORMAT_LENGTH > screen_width) {
134 | return progressbar_max(0, screen_width - bar_width - eta_width - WHITESPACE_LENGTH);
135 | } else {
136 | return label_length;
137 | }
138 | }
139 |
140 | static int progressbar_remaining_seconds(const progressbar* bar) {
141 | double offset = difftime(time(NULL), bar->start);
142 | if (bar->value > 0 && offset > 0) {
143 | return (offset / (double) bar->value) * (bar->max - bar->value);
144 | } else {
145 | return 0;
146 | }
147 | }
148 |
149 | static progressbar_time_components progressbar_calc_time_components(int seconds) {
150 | int hours = seconds / 3600;
151 | seconds -= hours * 3600;
152 | int minutes = seconds / 60;
153 | seconds -= minutes * 60;
154 |
155 | progressbar_time_components components = {hours, minutes, seconds};
156 | return components;
157 | }
158 |
159 | static void progressbar_draw(const progressbar *bar)
160 | {
161 | int screen_width = get_screen_width();
162 | int label_length = (int)strlen(bar->label);
163 | int bar_width = progressbar_bar_width(screen_width, label_length);
164 | int label_width = progressbar_label_width(screen_width, label_length, bar_width);
165 |
166 | int progressbar_completed = (bar->value >= bar->max);
167 | int bar_piece_count = bar_width - BAR_BORDER_WIDTH;
168 | int bar_piece_current = (progressbar_completed)
169 | ? bar_piece_count
170 | : bar_piece_count * ((double) bar->value / bar->max);
171 |
172 | progressbar_time_components eta = (progressbar_completed)
173 | ? progressbar_calc_time_components(difftime(time(NULL), bar->start))
174 | : progressbar_calc_time_components(progressbar_remaining_seconds(bar));
175 |
176 | if (label_width == 0) {
177 | // The label would usually have a trailing space, but in the case that we don't print
178 | // a label, the bar can use that space instead.
179 | bar_width += 1;
180 | } else {
181 | // Draw the label
182 | fwrite(bar->label, 1, label_width, stderr);
183 | fputc(' ', stderr);
184 | }
185 |
186 | // Draw the progressbar
187 | fputc(bar->format.begin, stderr);
188 | progressbar_write_char(stderr, bar->format.fill, bar_piece_current);
189 | progressbar_write_char(stderr, ' ', bar_piece_count - bar_piece_current);
190 | fputc(bar->format.end, stderr);
191 |
192 | // Draw the ETA
193 | fputc(' ', stderr);
194 | fprintf(stderr, ETA_FORMAT, eta.hours, eta.minutes, eta.seconds);
195 | fputc('\r', stderr);
196 | }
197 |
198 | /**
199 | * Finish a progressbar, indicating 100% completion, and free it.
200 | */
201 | void progressbar_finish(progressbar *bar)
202 | {
203 | // Make sure we fill the progressbar so things look complete.
204 | progressbar_draw(bar);
205 |
206 | // Print a newline, so that future outputs to stderr look prettier
207 | fprintf(stderr, "\n");
208 |
209 | // We've finished with this progressbar, so go ahead and free it.
210 | progressbar_free(bar);
211 | }
212 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | NOTE: around ~2021 Apple introduced new binding opcodes which I haven't gotten around to updating yet for dsdump. This results in bad output for objc class dumps.
2 | I recommend you check out [@blacktop](https://twitter.com/blacktop__)'s [ipsw](https://github.com/blacktop/ipsw) instead
3 |
4 |
5 | ## dsdump
6 | An improved nm + objc/swift class-dump ([writeup](https://derekselander.github.io/dsdump/))
7 |
8 | Works great on Objective-C classes
9 | [](https://store.raywenderlich.com/products/advanced-apple-debugging-and-reverse-engineering)
10 |
11 | ... and Swift types
12 | [](https://store.raywenderlich.com/products/advanced-apple-debugging-and-reverse-engineering)
13 |
14 | ### man
15 |
16 |
17 | ```
18 | dsdump(1) BSD General Commands Manual dsdump(1)
19 |
20 | NAME
21 | dsdump -- An improved nm + objc/swift class-dump
22 |
23 | SYNOPSIS
24 | dsdump [option...]
25 |
26 | DESCRIPTION
27 | Provides an "nm-improved" experience when working with Mach-O executa-
28 | bles. dsdump has 3 "primary" modes: Symbol table (--sym), Objective-C
29 | (--objc), and Swift (--swift, -s). Omitting all of these options will
30 | default to the Swift mode.
31 |
32 | OPTIONS
33 | -c, --color
34 | Adds color to output
35 |
36 | -d, --demangle
37 | Demangle Swift and C++ symbols in print symbol mode
38 |
39 | -l, --library
40 | Instead of dumping symbols, search all procs for library
41 |
42 | -O, --opcs
43 | Dump the DYLD opcodes used to bind external symbols at load time
44 |
45 | -f, --filter FilterWord
46 | Specify classes to filter by (case insensitive, can be used mul-
47 | tiple times)
48 |
49 | -a, --arch architecture
50 | Specify the arichtecture if file is FAT. Understands x86_64h,
51 | x86_64, arm64, arm64e
52 |
53 | -u, --undefined
54 | Only display undefined (externally referenced) symbols or classes
55 |
56 | -U, --defined
57 | Only display defined (internally implemented) symbols or classes
58 |
59 | -v, --verbose
60 | Specifies the verbosity level. The -v option can be used multiple
61 | times, while the long argument sets the exact level 0-5. Kind of
62 | like codesign(1)'s verbosity that everyone complains about...
63 |
64 | --objc Dump the Objective-C classes
65 |
66 | -o Sets mode to Objective-C mode and verbosity to level 4
67 |
68 | --swift
69 | Dump the Swift type descriptors (classes, structs, enums)
70 |
71 | -s Sets mode to Swift mode and verbosity to level 4
72 |
73 | -h, --help
74 | Print out this beautiful, helpful document
75 |
76 | EXAMPLES
77 | List ObjC internal/external classes referenced/implemented by vmmap:
78 | dsdump --objc $(which vmmap)
79 |
80 | List all alive processes that have the MobileDevice loaded
81 | sudo dsdump -l /S*/L*/P*/MobileDevice.framework/MobileDevice
82 |
83 | List the Objective-C external classes called by vmmap:
84 | dsdump --objc $(which vmmap) -u
85 |
86 | List the Objective-C internal classes implemented by vmmap:
87 | dsdump --objc $(which vmmap) -U
88 |
89 | Perform an Objective-C "class-dump" in color of vmmap
90 | dsdump --objc $(which vmmap) -U -vvvc
91 |
92 | Thoroughly dump the Swift content in color in the Console app
93 | dsdump --swift
94 | /Applications/Utilities/Console.app/Contents/MacOS/Console -cvvvv
95 |
96 | VERBOSITY
97 | dsdump can output a range of verbosity between the 3 different modes
98 | (--sym, --swift, --objc). The verbosity level can be set by the long form
99 | (--verbose=3) or by specifying a count via short form (-vvv). The break-
100 | down of these levels are shown below:
101 |
102 | --sym:
103 | 0. Print symbol
104 | 1. 0 + library path or Mach-O section
105 | 2. 1 + fullpath to library
106 | 3. 2 + nlist struct output
107 | 4. Same as 3... for now
108 | 5. Same as 3... for now
109 |
110 | --swift:
111 | 0. List swift types
112 | 1. 0 + Parent classes
113 | 2. 1 + Protocols
114 | 3. 2 + Swift type dump
115 | 4. 3 + Extended type dump, ObjC bridge methods
116 | 5. 4 + Commenting in methods
117 |
118 | --objc:
119 | 0. List Objective-C classes
120 | 1. 0 + Parent classes & library basename for external
121 | 2. 1 + Fullpath to libraries for external + protocols
122 | 3. 2 + Objective-C class dump
123 | 4. 3 + Print properties
124 | 5. 4 + Print ivars & offsets
125 |
126 | ENVIRONMENT
127 | DSCOLOR Enables color. Alternatively, use -c
128 |
129 | ARCH Specify the architecture if inspecting a FAT executable,
130 | Alternatively use --arch
131 |
132 | SEE ALSO
133 | nm(1), objdump(1), vmmap(1)
134 |
135 | BUGS
136 | There's a situation where occassionally dsdump will think the parent
137 | class is a RO_ROOT where it will in fact won't be. I'll print this out
138 | for now so I can hunt it down
139 |
140 | ARM64e still needs some luv, especially on the Swift side, especially
141 | with Protocols... and not crashing
142 |
143 | AUTHORS
144 | Derek Selander @LOLgrep
145 |
146 | Darwin March 26, 2020 Darwin
147 | ```
148 |
149 |
150 | ## Compiling
151 |
152 | Compiling this will be a bit of a pain in the butt on your end. You'll need to clone the Swift language in the same directory. Swift can't be a submodule to this repo since some of their git cloning scripts won't work :|
153 |
154 | ```bash
155 | # cd into the dsdump repo
156 | cd dsdump/
157 |
158 | # make a directory called swift-source, yes, name it exactly that
159 | mkdir swift-source
160 |
161 | cd swift-source/
162 |
163 | # clone the Swift repository into swift-source
164 | git clone https://github.com/apple/swift.git
165 |
166 | # checkout
167 | cd swift
168 | git checkout 75670c17272a993ed798cee7e31c20590e94118b
169 |
170 | # Use the Swift update helper script to grab everything else
171 | ./swift/utils/update-checkout --clone-with-ssh --tag swift-5.1.4-RELEASE
172 | ```
173 | Comment out any remaining problematic code after a build, remove methods in `Metadata.h` as needed (i.e. problematic ARC bridging code on line 700)
174 |
175 | I've included the `libSwiftDemangling.a` static lib that I built into `dsdump/dsdump`. If you want to build entirely from Swift source, you'll need to build this yourself. Otherwise you should be good to go to build `dsdump` via Xcode.
176 |
177 | Alternatively, you can skip all of this by simply grabbing the compiled `dsdump` version in the **compiled** directory [found here](https://github.com/DerekSelander/dsdump/tree/master/compiled). Make sure the SHA256 matches below if you're paranoid.
178 |
179 | Compiled SHA256
180 | ```
181 | SHA256: 83eebd025b43b58a486235e1bec70a3239995be409605e3ff19bdae07adff917
182 | ```
183 |
184 | ### Credits
185 |
186 | * [https://opensource.apple.com/source/dyld/dyld-635.2/src/dyldInitialization.cpp.auto.html](https://opensource.apple.com/source/dyld/dyld-635.2/src/dyldInitialization.cpp.auto.html) Specifically the THREADED code for ARM64e
187 | * [https://opensource.apple.com/source/objc4/](https://opensource.apple.com/source/objc4/) Specifically, the objc_class swift_class structs (and all the property, protocol, method, ivar, etc structs)
188 | * [https://github.com/apple/swift](https://github.com/apple/swift)
189 |
190 | ### TODO list for v1
191 |
192 | * Full ARM64e support
193 | * M1 support
194 | * Crashes
195 | * iOS 15/Monterey support
196 | * In process support (TODO TODO guess that means a libdsdump.a)
197 | * Basic dsc listing with options to `dlopen` from cmdline
198 | * header files
199 |
--------------------------------------------------------------------------------
/dsdump/payload.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // payload.hpp
3 | // dsdump
4 | //
5 | // Created by Derek Selander on 6/10/19.
6 | // Copyright © 2019 Selander. All rights reserved.
7 | //
8 |
9 | #ifndef payload_hpp
10 | #define payload_hpp
11 |
12 | #import
13 | #import
14 | #import
15 | #import
16 | #import