-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathinspect-sig.py
executable file
·206 lines (161 loc) · 6.31 KB
/
inspect-sig.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#!/usr/bin/env python3
import sys
import math
import enum
from construct import *
# See
# https://opensource.apple.com/source/xnu/xnu-3248.20.55/bsd/sys/codesign.h
class CSFlags(enum.IntFlag):
CS_VALID = 0x00000001 # dynamically valid
CS_ADHOC = 0x00000002 # ad hoc signed
CS_GET_TASK_ALLOW = 0x00000004 # has get-task-allow entitlement
CS_INSTALLER = 0x00000008 # has installer entitlement
CS_FORCED_LV = 0x00000010 # Library Validation required by Hardened System Policy
# (macOS Only) Page invalidation allowed by task port policy
CS_INVALID_ALLOWED = 0x00000020
CS_HARD = 0x00000100 # don't load invalid pages
CS_KILL = 0x00000200 # kill process if it becomes invalid
CS_CHECK_EXPIRATION = 0x00000400 # force expiration checking
CS_RESTRICT = 0x00000800 # tell dyld to treat restricted
CS_ENFORCEMENT = 0x00001000 # require enforcement
CS_REQUIRE_LV = 0x00002000 # require library validation
# code signature permits restricted entitlements
CS_ENTITLEMENTS_VALIDATED = 0x00004000
# has com.apple.rootless.restricted-nvram-variables.heritable en titlement
CS_NVRAM_UNRESTRICTED = 0x00008000
CS_RUNTIME = 0x00010000 # Apply hardened runtime policies
CS_LINKER_SIGNED = 0x00020000 # Automatically signed by the linker
cs_flags = FlagsEnum(Int32ub, CSFlags)
class CSExecSegFlags(enum.IntFlag):
CS_EXECSEG_MAIN_BINARY = 0x1 # executable segment denotes main binary
CS_EXECSEG_ALLOW_UNSIGNED = 0x10 # allow unsigned pages (for debugging)
CS_EXECSEG_DEBUGGER = 0x20 # main binary is debugger
CS_EXECSEG_JIT = 0x40 # JIT enabled
CS_EXECSEG_SKIP_LV = 0x80 # OBSOLETE: skip library validation
CS_EXECSEG_CAN_LOAD_CDHASH = 0x100 # can bless cdhash for execution
CS_EXECSEG_CAN_EXEC_CDHASH = 0x200 # can execute blessed cdhash
cs_execseg_flags = FlagsEnum(Int64ub, CSExecSegFlags)
class CSMagic(enum.IntEnum):
# From cs_blobs.h, which is under Apple's open source license
CSMAGIC_REQUIREMENT = 0xfade0c00, # single Requirement blob
# Requirements vector (internal requirements)
CSMAGIC_REQUIREMENTS = 0xfade0c01,
CSMAGIC_CODEDIRECTORY = 0xfade0c02, # CodeDirectory blob
CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0, # embedded form of signature data
CSMAGIC_EMBEDDED_SIGNATURE_OLD = 0xfade0b02, # XXX
CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171, # embedded entitlements
# multi-arch collection of embedded signatures
CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1,
CSMAGIC_BLOBWRAPPER = 0xfade0b01, # CMS Signature, among other things
cs_magic = Enum(Int32ub, CSMagic)
class CSHashType(enum.IntEnum):
CS_HASHTYPE_SHA1 = 1,
CS_HASHTYPE_SHA256 = 2,
CS_HASHTYPE_SHA256_TRUNCATED = 3,
CS_HASHTYPE_SHA384 = 4,
cs_hashtype = Enum(Int8ub, CSHashType)
class CSSlot(enum.IntEnum):
# slot index for CodeDirectory
CSSLOT_CODEDIRECTORY = 0,
CSSLOT_INFOSLOT = 1,
CSSLOT_REQUIREMENTS = 2,
CSSLOT_RESOURCEDIR = 3,
CSSLOT_APPLICATION = 4,
CSSLOT_ENTITLEMENTS = 5,
# first alternate CodeDirectory, if any
CSSLOT_ALTERNATE_CODEDIRECTORIES = 0x1000,
# max number of alternate CD slots
CSSLOT_ALTERNATE_CODEDIRECTORY_MAX = 5,
# CSSLOT_ALTERNATE_CODEDIRECTORIES + CSSLOT_ALTERNATE_CODEDIRECTORY_MAX, # one past the last
CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT = 0x1000 + 5,
CSSLOT_SIGNATURESLOT = 0x10000, # CMS Signature
CSSLOT_IDENTIFICATIONSLOT = 0x10001,
CSSLOT_TICKETSLOT = 0x10002,
csslot = Enum(Int32ub, CSSlot)
codeDirectory = Struct(
"start" / Tell,
"magic" / cs_magic,
"length" / Int32ub,
"version" / Hex(Int32ub),
"flags" / cs_flags,
"hashOffset" / Int32ub,
"identOffset" / Int32ub,
"nSpecialSlots" / Int32ub,
"nCodeSlots" / Int32ub,
"codeLimit" / Int32ub,
"hashSize" / Int8ub,
"hashType" / cs_hashtype,
"platform" / Int8ub,
"pageSize" / Hex(ExprAdapter(Int8ub, 1 << obj_,
lambda x: math.log2(x))),
"spare2" / Int32ub,
"specialHashes" / Pointer(this.start + this.hashOffset - this.nSpecialSlots * this.hashSize,
Array(this.nSpecialSlots, Hex(Bytes(this.hashSize)))),
"codeHashes" / Pointer(this.start + this.hashOffset,
Array(this.nCodeSlots, Hex(Bytes(this.hashSize)))),
"identifier" / Pointer(this.start + this.identOffset,
CString("ascii")),
StopIf(this.version < 0x20100),
"scatterOffset" / Int32ub,
StopIf(this.version < 0x020200),
"teamOffset" / Int32ub,
StopIf(this.version < 0x020300),
"spare3" / Int32ub,
"codeLimit64" / Int64ub,
StopIf(this.version < 0x020400),
"execSegBase" / Int64ub,
"execSegLimit" / Int64ub,
"execSegFlags" / cs_execseg_flags,
StopIf(this.version < 0x020500),
"runtime" / Int32ub,
"preEncryptionOffset" / Int32ub,
StopIf(this.version < 0x020600),
"linkageHashType" / Int8ub,
"linkageTruncated" / Int8ub,
"spare4" / Int16ub,
"linkageOffset" / Int32ub,
"linkageSize" / Int32ub
)
codeSignature = Struct(
"cs_magic" / cs_magic,
"length" / Int32ub,
)
requirementsBlobIndex = Struct(
"type" / Int32ub,
"offset" / Int32ub,
)
requirements = Struct(
"start" / Tell,
"cs_magic" / cs_magic,
"length" / Int32ub,
"count" / Int32ub,
"raw" / Pointer(this.start, Hex(Bytes(this.length))),
"items" / Array(this.count, requirementsBlobIndex),
)
signature = Struct(
"cs_magic" / cs_magic,
"length" / Int32ub,
StopIf(this.length == 8),
"signature" / Hex(Bytes(this.length)),
)
blobIndex = Struct(
"type" / csslot,
"offset" / Int32ub,
"blob" / Pointer(this._.pointer + this.offset, codeSignature),
"parsed" / Pointer(this._.pointer + this.offset, Switch(this.type, {
CSSlot.CSSLOT_CODEDIRECTORY.name: codeDirectory,
CSSlot.CSSLOT_REQUIREMENTS.name: requirements,
CSSlot.CSSLOT_SIGNATURESLOT.name: signature,
}, default=Hex(Pointer(this._.pointer + this.offset + 8, Bytes(this.blob.length - 8)))))
)
superBlob = Struct(
"pointer" / Tell,
"magic" / cs_magic,
"length" / Int32ub,
"count" / Int32ub,
"index" / Array(this.count, blobIndex)
)
def main(filename):
print(superBlob.parse_file(filename))
if __name__ == "__main__":
main(sys.argv[1])