Skip to content

Commit 3f2e25a

Browse files
committed
wip
1 parent 08179e6 commit 3f2e25a

28 files changed

+1054
-1541
lines changed

view/sharedcache/api/python/sharedcache.py

Lines changed: 67 additions & 251 deletions
Original file line numberDiff line numberDiff line change
@@ -9,259 +9,75 @@
99
from . import _sharedcachecore as sccore
1010
from .sharedcache_enums import *
1111

12-
13-
@dataclasses.dataclass
14-
class DSCMemoryMapping:
15-
name: str
16-
vmAddress: int
17-
size: int
18-
19-
def __str__(self):
20-
return repr(self)
21-
22-
def __repr__(self):
23-
return f"<DSCMemoryMapping '{self.name}': {self.vmAddress:x}+{self.size:x}>"
24-
25-
26-
@dataclasses.dataclass
27-
class LoadedRegion:
28-
name: str
29-
headerAddress: int
30-
mappings: list[DSCMemoryMapping]
31-
32-
def __str__(self):
33-
return repr(self)
34-
35-
def __repr__(self):
36-
return f"<LoadedRegion {self.name} @ {self.headerAddress:x}>"
37-
38-
39-
@dataclasses.dataclass
40-
class DSCBackingCacheMapping:
41-
vmAddress: int
42-
size: int
43-
fileOffset: int
44-
45-
def __str__(self):
46-
return repr(self)
47-
48-
def __repr__(self):
49-
return f"<DSCBackingCacheMapping {self.vmAddress:x}+{self.size:x} @ {self.fileOffset:x}"
50-
51-
52-
@dataclasses.dataclass
53-
class DSCBackingCache:
54-
path: str
55-
cacheType: BackingCacheType
56-
mappings: list[DSCBackingCacheMapping]
57-
58-
def __str__(self):
59-
return repr(self)
60-
61-
def __repr__(self):
62-
match self.cacheType:
63-
case BackingCacheType.BackingCacheTypePrimary:
64-
cacheTypeStr = 'Primary'
65-
case BackingCacheType.BackingCacheTypeSecondary:
66-
cacheTypeStr = 'Secondary'
67-
case BackingCacheType.BackingCacheTypeSymbols:
68-
cacheTypeStr = 'Symbols'
69-
return f"<DSCBackingCache {self.path} {cacheTypeStr} | {len(self.mappings)} mappings>"
70-
71-
7212
@dataclasses.dataclass
73-
class DSCImageMemoryMapping:
74-
filePath: str
75-
name: str
76-
vmAddress: int
77-
size: int
78-
loaded: bool
79-
rawViewOffset: int
13+
class CacheRegion:
14+
regionType: SharedCacheRegionType
15+
name: str
16+
start: int
17+
size: int
18+
imageStart: int
19+
flags: binaryninja.enums.SegmentFlag
8020

81-
def __str__(self):
82-
return repr(self)
83-
84-
def __repr__(self):
85-
return f"<DSCImageMemoryMapping '{self.name}' {os.path.basename(self.filePath)} raw<{self.rawViewOffset:x}>: {self.vmAddress:x}+{self.size:x}>"
21+
def __str__(self):
22+
return repr(self)
8623

24+
def __repr__(self):
25+
return f"<CacheRegion '{self.name}': {self.start:x}+{self.size:x}>"
8726

8827
@dataclasses.dataclass
89-
class DSCImage:
90-
name: str
91-
headerAddress: int
92-
mappings: list[DSCImageMemoryMapping]
93-
94-
def __str__(self):
95-
return repr(self)
96-
97-
def __repr__(self):
98-
return f"<DSCImage {self.name} @ {self.headerAddress:x}>"
99-
100-
101-
@dataclasses.dataclass
102-
class DSCSymbol:
103-
name: str
104-
image: str
105-
address: int
106-
107-
def __str__(self):
108-
return repr(self)
109-
110-
def __repr__(self):
111-
return f"<DSCSymbol {self.name} @ {self.address:x} ({self.image}>"
112-
113-
114-
class SharedCache:
115-
def __init__(self, view):
116-
self.handle = sccore.BNGetSharedCache(view.handle)
117-
118-
def load_image_with_install_name(self, installName, skipObjC = False):
119-
return sccore.BNDSCViewLoadImageWithInstallName(self.handle, installName, skipObjC)
120-
121-
def load_section_at_address(self, addr):
122-
return sccore.BNDSCViewLoadSectionAtAddress(self.handle, addr)
123-
124-
def load_image_containing_address(self, addr, skipObjC = False):
125-
return sccore.BNDSCViewLoadImageContainingAddress(self.handle, addr, skipObjC)
126-
127-
def process_objc_sections_for_image_with_install_name(self, installName):
128-
return sccore.BNDSCViewProcessObjCSectionsForImageWithInstallName(self.handle, installName)
129-
130-
def process_all_objc_sections(self):
131-
return sccore.BNDSCViewProcessAllObjCSections(self.handle)
132-
133-
@property
134-
def caches(self):
135-
count = ctypes.c_ulonglong()
136-
value = sccore.BNDSCViewGetBackingCaches(self.handle, count)
137-
if value is None:
138-
return []
139-
140-
result = []
141-
for i in range(count.value):
142-
mappings = []
143-
for j in range(value[i].mappingCount):
144-
mapping = DSCBackingCacheMapping(
145-
value[i].mappings[j].vmAddress,
146-
value[i].mappings[j].size,
147-
value[i].mappings[j].fileOffset
148-
)
149-
mappings.append(mapping)
150-
result.append(DSCBackingCache(
151-
value[i].path,
152-
value[i].cacheType,
153-
mappings
154-
))
155-
156-
sccore.BNDSCViewFreeBackingCaches(value, count)
157-
return result
158-
159-
@property
160-
def images(self):
161-
count = ctypes.c_ulonglong()
162-
value = sccore.BNDSCViewGetAllImages(self.handle, count)
163-
if value is None:
164-
return []
165-
166-
result = []
167-
for i in range(count.value):
168-
mappings = []
169-
for j in range(value[i].mappingCount):
170-
mapping = DSCImageMemoryMapping(
171-
value[i].mappings[j].filePath,
172-
value[i].mappings[j].name,
173-
value[i].mappings[j].vmAddress,
174-
value[i].mappings[j].size,
175-
value[i].mappings[j].loaded,
176-
value[i].mappings[j].rawViewOffset
177-
)
178-
mappings.append(mapping)
179-
result.append(DSCImage(
180-
value[i].name,
181-
value[i].headerAddress,
182-
mappings
183-
))
184-
185-
sccore.BNDSCViewFreeAllImages(value, count)
186-
return result
187-
188-
@property
189-
def loaded_regions(self):
190-
"""
191-
Get all loaded regions in the shared cache
192-
193-
The internal logic for loading images treats a region as 'loaded' whenever
194-
that region has been mapped into memory, and, if it's located within an image, header information has been applied to that region.
195-
196-
Individual segments within an image can be loaded independently of the image itself.
197-
198-
Only once all regions of an image are loaded will the header processor refuse to run on that region.
199-
:return:
200-
"""
201-
count = ctypes.c_ulonglong()
202-
value = sccore.BNDSCViewGetLoadedRegions(self.handle, count)
203-
if value is None:
204-
return []
205-
206-
result = []
207-
for i in range(count.value):
208-
mapping = DSCMemoryMapping(
209-
value[i].name,
210-
value[i].vmAddress,
211-
value[i].size,
212-
)
213-
result.append(mapping)
214-
sccore.BNDSCViewFreeLoadedRegions(value, count)
215-
return result
216-
217-
def load_all_symbols_and_wait(self):
218-
count = ctypes.c_ulonglong()
219-
value = sccore.BNDSCViewLoadAllSymbolsAndWait(self.handle, count)
220-
if value is None:
221-
return []
222-
result = []
223-
for i in range(count.value):
224-
sym = DSCSymbol(
225-
value[i].name,
226-
value[i].image,
227-
value[i].address
228-
)
229-
result.append(sym)
230-
231-
sccore.BNDSCViewFreeSymbols(value, count)
232-
return result
233-
234-
@property
235-
def image_names(self):
236-
count = ctypes.c_ulonglong()
237-
value = sccore.BNDSCViewGetInstallNames(self.handle, count)
238-
if value is None:
239-
return []
240-
241-
result = []
242-
for i in range(count.value):
243-
result.append(value[i].decode('utf-8'))
244-
245-
BNFreeStringList(value, count)
246-
return result
247-
248-
@property
249-
def state(self):
250-
return DSCViewState(sccore.BNDSCViewGetState(self.handle))
251-
252-
def get_name_for_address(self, address):
253-
name = sccore.BNDSCViewGetNameForAddress(self.handle, address)
254-
if name is None:
255-
return ""
256-
result = name
257-
return result
258-
259-
def get_image_name_for_address(self, address):
260-
name = sccore.BNDSCViewGetImageNameForAddress(self.handle, address)
261-
if name is None:
262-
return ""
263-
result = name
264-
return result
265-
266-
def find_symbol_at_addr_and_apply_to_addr(self, symbolAddress, targetAddress, triggerReanalysis) -> None:
267-
sccore.BNDSCFindSymbolAtAddressAndApplyToAddress(self.handle, symbolAddress, targetAddress, triggerReanalysis)
28+
class CacheImage:
29+
name: str
30+
headerAddress: int
31+
regionStarts: [int]
32+
33+
def __str__(self):
34+
return repr(self)
35+
36+
def __repr__(self):
37+
return f"<CacheImage '{self.name}': {self.headerAddress:x}>"
38+
39+
def region_from_api(region):
40+
return CacheRegion(
41+
SharedCacheRegionType(region.regionType),
42+
region.name.decode('utf-8'),
43+
region.start,
44+
region.size,
45+
region.imageStart,
46+
binaryninja.enums.SegmentFlag(region.flags)
47+
)
48+
49+
def image_from_api(image):
50+
return CacheImage(
51+
image.name.decode('utf-8'),
52+
image.headerAddress,
53+
image.regionStarts
54+
)
55+
56+
class SharedCacheController:
57+
def __init__(self, view):
58+
self.handle = sccore.BNGetSharedCacheController(view.handle)
59+
60+
@property
61+
def regions(self):
62+
count = ctypes.c_ulonglong()
63+
value = sccore.BNGetSharedCacheRegions(self.handle, count)
64+
if value is None:
65+
return []
66+
result = []
67+
for i in range(count.value):
68+
result.append(region_from_api(value[i]))
69+
sccore.BNSharedCacheFreeRegionList(value, count)
70+
return result
71+
72+
73+
@property
74+
def images(self):
75+
count = ctypes.c_ulonglong()
76+
value = sccore.BNGetSharedCacheImages(self.handle, count)
77+
if value is None:
78+
return []
79+
result = []
80+
for i in range(count.value):
81+
result.append(image_from_api(value[i]))
82+
sccore.BNSharedCacheFreeImageList(value, count)
83+
return result
Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,38 @@
11
import enum
22

33

4-
class BackingCacheType(enum.IntEnum):
5-
BackingCacheTypePrimary = 0
6-
BackingCacheTypeSecondary = 1
7-
BackingCacheTypeSymbols = 2
4+
class SegmentFlag(enum.IntEnum):
5+
SegmentExecutable = 1
6+
SegmentWritable = 2
7+
SegmentReadable = 4
8+
SegmentContainsData = 8
9+
SegmentContainsCode = 16
10+
SegmentDenyWrite = 32
11+
SegmentDenyExecute = 64
812

913

10-
class DSCViewLoadProgress(enum.IntEnum):
11-
LoadProgressNotStarted = 0
12-
LoadProgressLoadingCaches = 1
13-
LoadProgressLoadingImages = 2
14-
LoadProgressFinished = 3
14+
class SharedCacheEntryType(enum.IntEnum):
15+
SharedCacheEntryTypePrimary = 0
16+
SharedCacheEntryTypeSecondary = 1
17+
SharedCacheEntryTypeSymbols = 2
18+
SharedCacheEntryTypeDyldData = 3
19+
SharedCacheEntryTypeStub = 4
1520

1621

17-
class DSCViewState(enum.IntEnum):
18-
Unloaded = 0
19-
Loaded = 1
20-
LoadedWithImages = 2
22+
class SharedCacheRegionType(enum.IntEnum):
23+
SharedCacheRegionTypeImage = 0
24+
SharedCacheRegionTypeStubIsland = 1
25+
SharedCacheRegionTypeDyldData = 2
26+
SharedCacheRegionTypeNonImage = 3
27+
28+
29+
class SymbolType(enum.IntEnum):
30+
FunctionSymbol = 0
31+
ImportAddressSymbol = 1
32+
ImportedFunctionSymbol = 2
33+
DataSymbol = 3
34+
ImportedDataSymbol = 4
35+
ExternalSymbol = 5
36+
LibraryFunctionSymbol = 6
37+
SymbolicFunctionSymbol = 7
38+
LocalLabelSymbol = 8

0 commit comments

Comments
 (0)