Skip to content

Commit ede39ae

Browse files
committed
[WARP] Enhanced network support
1 parent a1c4681 commit ede39ae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3371
-256
lines changed

Cargo.lock

Lines changed: 75 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/warp/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ arboard = "3.4"
1919
walkdir = "2.5"
2020
serde = { version = "1.0", features = ["derive"] }
2121
serde_json = "1.0"
22-
uuid = { version = "1.12.0", features = ["v4"] }
22+
uuid = { version = "1.12.0", features = ["v4", "serde"] }
2323
thiserror = "2.0"
2424
ar = { git = "https://github.com/mdsteele/rust-ar" }
2525
tempdir = "0.3.7"
2626
regex = "1.11"
2727
reqwest = { version = "0.12", features = ["blocking", "json", "multipart"] }
28+
directories = "6.0"
29+
compact_str = { version = "0.9.0", features = ["serde"] }
2830

2931
# For reports
3032
minijinja = "2.10.2"

plugins/warp/api/python/warp.py

Lines changed: 119 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from binaryninja._binaryninjacore import BNFreeString, BNAllocString, BNType
99

1010
from . import _warpcore as warpcore
11+
from .warp_enums import WARPContainerSearchItemKind
1112

1213

1314
class WarpUUID:
@@ -195,6 +196,108 @@ def apply(self, function: Function):
195196
warpcore.BNWARPFunctionApply(self.handle, function.handle)
196197

197198

199+
class WarpContainerSearchQuery:
200+
def __init__(self, query: str, offset: Optional[int] = None, limit: Optional[int] = None, source: Optional[Source] = None, source_tags: Optional[List[str]] = None):
201+
self.query = query
202+
self.source = source
203+
self.offset = offset
204+
self.limit = limit
205+
offset_ptr = None
206+
if offset is not None:
207+
self._c_offset = ctypes.c_size_t(offset)
208+
offset_ptr = ctypes.byref(self._c_offset)
209+
limit_ptr = None
210+
if limit is not None:
211+
self._c_limit = ctypes.c_size_t(limit)
212+
limit_ptr = ctypes.byref(self._c_limit)
213+
source_ptr = None
214+
if source is not None:
215+
self._c_source = source.uuid
216+
source_ptr = ctypes.byref(self._c_source)
217+
source_tags_len = 0
218+
source_tags_array_ptr = None
219+
if source_tags is not None:
220+
source_tags_ptr = (ctypes.c_char_p * len(source_tags))()
221+
source_tags_len = len(source_tags)
222+
for i in range(len(source_tags)):
223+
source_tags_ptr[i] = source_tags[i].encode('utf-8')
224+
source_tags_array_ptr = ctypes.cast(source_tags_ptr, ctypes.POINTER(ctypes.c_char_p))
225+
self.handle = warpcore.BNWARPNewContainerSearchQuery(query, offset_ptr, limit_ptr, source_ptr, source_tags_array_ptr, source_tags_len)
226+
227+
def __del__(self):
228+
if self.handle is not None:
229+
warpcore.BNWARPFreeContainerSearchQueryReference(self.handle)
230+
231+
def __repr__(self):
232+
# TODO: Display offset and limit in a pythonic way.
233+
if self.source is None:
234+
return f"<WarpContainerSearchQuery '{self.query}'>"
235+
return f"<WarpContainerSearchQuery '{self.query}': '{self.source}'>"
236+
237+
238+
class WarpContainerSearchItem:
239+
def __init__(self, handle: warpcore.BNWARPContainerSearchItem):
240+
self.handle = handle
241+
242+
def __del__(self):
243+
if self.handle is not None:
244+
warpcore.BNWARPFreeContainerSearchItemReference(self.handle)
245+
246+
@property
247+
def kind(self) -> WARPContainerSearchItemKind:
248+
return WARPContainerSearchItemKind(warpcore.BNWARPContainerSearchItemGetKind(self.handle))
249+
250+
@property
251+
def source(self) -> Source:
252+
return Source(warpcore.BNWARPContainerSearchItemGetSource(self.handle))
253+
254+
@property
255+
def name(self) -> str:
256+
return warpcore.BNWARPContainerSearchItemGetName(self.handle)
257+
258+
def get_type(self, arch: Architecture) -> Optional[Type]:
259+
ty = warpcore.BNWARPContainerSearchItemGetType(arch.handle, self.handle)
260+
if not ty:
261+
return None
262+
return Type(ty)
263+
264+
@property
265+
def function(self) -> Optional[WarpFunction]:
266+
func = warpcore.BNWARPContainerSearchItemGetFunction(self.handle)
267+
if not func:
268+
return None
269+
return WarpFunction(func)
270+
271+
def __repr__(self):
272+
return f"<WarpContainerSearchItem '{self.name}': '{self.source}'>"
273+
274+
275+
class WarpContainerResponse:
276+
def __init__(self, items: List[WarpContainerSearchItem], offset: int, total: int):
277+
self.items = items
278+
self.offset = offset
279+
self.total = total
280+
281+
def __iter__(self):
282+
return iter(self.items)
283+
284+
def __len__(self):
285+
return len(self.items)
286+
287+
def __repr__(self):
288+
return f"<WarpContainerResponse items={len(self.items)} offset={self.offset} total={self.total}>"
289+
290+
@staticmethod
291+
def from_api(response: warpcore.BNWARPContainerSearchResponse) -> 'WarpContainerResponse':
292+
try:
293+
items = []
294+
for i in range(response.count):
295+
items.append(WarpContainerSearchItem(warpcore.BNWARPNewContainerSearchItemReference(response.items[i])))
296+
return WarpContainerResponse(items=items, offset=response.offset, total=response.total)
297+
finally:
298+
warpcore.BNWARPFreeContainerSearchResponse(response)
299+
300+
198301
class _WarpContainerMetaclass(type):
199302
def __iter__(self):
200303
binaryninja._init_plugins()
@@ -305,12 +408,19 @@ def remove_types(self, source: Source, guids: List[TypeGUID]) -> bool:
305408
core_guids[i] = guids[i].uuid
306409
return warpcore.BNWARPContainerRemoveTypes(self.handle, source.uuid, core_guids, count)
307410

308-
def fetch_functions(self, target: WarpTarget, guids: List[FunctionGUID]):
411+
def fetch_functions(self, target: WarpTarget, guids: List[FunctionGUID], source_tags: Optional[List[str]] = None):
309412
count = len(guids)
310413
core_guids = (warpcore.BNWARPFunctionGUID * count)()
311414
for i in range(count):
312415
core_guids[i] = guids[i].uuid
313-
warpcore.BNWARPContainerFetchFunctions(self.handle, target.handle, core_guids, count)
416+
if source_tags is None:
417+
source_tags = []
418+
source_tags_ptr = (ctypes.c_char_p * len(source_tags))()
419+
source_tags_len = len(source_tags)
420+
for i in range(len(source_tags)):
421+
source_tags_ptr[i] = source_tags[i].encode('utf-8')
422+
source_tags_array_ptr = ctypes.cast(source_tags_ptr, ctypes.POINTER(ctypes.c_char_p))
423+
warpcore.BNWARPContainerFetchFunctions(self.handle, target.handle, source_tags_array_ptr, source_tags_len, core_guids, count)
314424

315425
def get_sources_with_function_guid(self, target: WarpTarget, guid: FunctionGUID) -> List[Source]:
316426
count = ctypes.c_size_t()
@@ -346,7 +456,7 @@ def get_functions_with_guid(self, target: WarpTarget, source: Source, guid: Func
346456
return result
347457

348458
def get_type_with_guid(self, arch: Architecture, source: Source, guid: TypeGUID) -> Optional[Type]:
349-
ty = warpcore.BNWARPContainerGetTypeWithGUID(self.handle, arch.handle, source.uuid, guid.uuid)
459+
ty = warpcore.BNWARPContainerGetTypeWithGUID(arch.handle, self.handle, source.uuid, guid.uuid)
350460
if not ty:
351461
return None
352462
return Type(ty)
@@ -362,6 +472,12 @@ def get_type_guids_with_name(self, source: Source, name: str) -> List[TypeGUID]:
362472
warpcore.BNWARPFreeUUIDList(guids, count.value)
363473
return result
364474

475+
def search(self, query: WarpContainerSearchQuery) -> Optional[WarpContainerResponse]:
476+
response = warpcore.BNWARPContainerSearch(self.handle, query.handle)
477+
if not response:
478+
return None
479+
return WarpContainerResponse.from_api(response.contents)
480+
365481

366482
def run_matcher(view: BinaryView):
367483
warpcore.BNWARPRunMatcher(view.handle)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
11
import enum
2+
3+
4+
class WARPContainerSearchItemKind(enum.IntEnum):
5+
WARPContainerSearchItemKindSource = 0
6+
WARPContainerSearchItemKindFunction = 1
7+
WARPContainerSearchItemKindType = 2
8+
WARPContainerSearchItemKindSymbol = 3

0 commit comments

Comments
 (0)