summaryrefslogtreecommitdiff
path: root/plugins/warp/api/python
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/warp/api/python')
-rw-r--r--plugins/warp/api/python/CMakeLists.txt50
-rw-r--r--plugins/warp/api/python/__init__.py7
-rw-r--r--plugins/warp/api/python/_warpcore.py1081
-rw-r--r--plugins/warp/api/python/_warpcore_template.py58
-rw-r--r--plugins/warp/api/python/generator.cpp652
-rw-r--r--plugins/warp/api/python/warp.py384
-rw-r--r--plugins/warp/api/python/warp_enums.py1
7 files changed, 2233 insertions, 0 deletions
diff --git a/plugins/warp/api/python/CMakeLists.txt b/plugins/warp/api/python/CMakeLists.txt
new file mode 100644
index 00000000..8e6003c0
--- /dev/null
+++ b/plugins/warp/api/python/CMakeLists.txt
@@ -0,0 +1,50 @@
+cmake_minimum_required(VERSION 3.9...3.15 FATAL_ERROR)
+
+project(warp-python-api)
+
+file(GLOB PYTHON_SOURCES ${PROJECT_SOURCE_DIR}/*.py)
+list(REMOVE_ITEM PYTHON_SOURCES ${PROJECT_SOURCE_DIR}/_warpcore.py)
+list(REMOVE_ITEM PYTHON_SOURCES ${PROJECT_SOURCE_DIR}/enums.py)
+
+add_executable(warp_generator
+ ${PROJECT_SOURCE_DIR}/generator.cpp)
+target_link_libraries(warp_generator binaryninjaapi)
+target_include_directories(warp_generator PUBLIC {PROJECT_SOURCE_DIR}/../../api)
+
+set_target_properties(warp_generator PROPERTIES
+ CXX_STANDARD 17
+ CXX_STANDARD_REQUIRED ON
+ BUILD_WITH_INSTALL_RPATH OFF
+ RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
+
+if(BN_INTERNAL_BUILD)
+ set(PYTHON_OUTPUT_DIRECTORY ${BN_RESOURCE_DIR}/python/binaryninja/warp/)
+else()
+ set(PYTHON_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/out/plugins/warp/)
+endif()
+
+if(WIN32)
+ if (BN_INTERNAL_BUILD)
+ add_custom_command(TARGET warp_generator PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${BN_CORE_OUTPUT_DIR}/binaryninjacore.dll ${PROJECT_BINARY_DIR}/)
+ else()
+ add_custom_command(TARGET warp_generator PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${BN_INSTALL_DIR}/binaryninjacore.dll ${PROJECT_BINARY_DIR}/)
+ endif()
+endif()
+
+add_custom_target(warp_generator_copy ALL
+ BYPRODUCTS ${PROJECT_SOURCE_DIR}/_warpcore.py ${PROJECT_SOURCE_DIR}/enums.py
+ DEPENDS ${PYTHON_SOURCES} ${PROJECT_SOURCE_DIR}/../warpcore.h $<TARGET_FILE:warp_generator>
+ COMMAND ${CMAKE_COMMAND} -E echo "Copying WARP Python Sources"
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${PYTHON_OUTPUT_DIRECTORY}
+ COMMAND ${CMAKE_COMMAND} -E env ASAN_OPTIONS=detect_leaks=0 $<TARGET_FILE:warp_generator>
+ ${PROJECT_SOURCE_DIR}/../warpcore.h
+ ${PROJECT_SOURCE_DIR}/_warpcore.py
+ ${PROJECT_SOURCE_DIR}/_warpcore_template.py
+ ${PROJECT_SOURCE_DIR}/warp_enums.py
+
+ COMMAND ${CMAKE_COMMAND} -E copy ${PYTHON_SOURCES} ${PYTHON_OUTPUT_DIRECTORY}
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/_warpcore.py ${PYTHON_OUTPUT_DIRECTORY}
+ COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/warp_enums.py ${PYTHON_OUTPUT_DIRECTORY})
+
diff --git a/plugins/warp/api/python/__init__.py b/plugins/warp/api/python/__init__.py
new file mode 100644
index 00000000..f4bc8e83
--- /dev/null
+++ b/plugins/warp/api/python/__init__.py
@@ -0,0 +1,7 @@
+import os
+
+from binaryninja._binaryninjacore import BNGetUserPluginDirectory
+user_plugin_dir = os.path.realpath(BNGetUserPluginDirectory())
+current_path = os.path.realpath(__file__)
+
+from .warp import * \ No newline at end of file
diff --git a/plugins/warp/api/python/_warpcore.py b/plugins/warp/api/python/_warpcore.py
new file mode 100644
index 00000000..c53feefa
--- /dev/null
+++ b/plugins/warp/api/python/_warpcore.py
@@ -0,0 +1,1081 @@
+import binaryninja
+import ctypes, os
+
+from typing import Optional
+from . import warp_enums
+# Load core module
+import platform
+core = None
+core_platform = platform.system()
+
+from binaryninja import Settings
+if Settings().get_bool("corePlugins.warp"):
+ from binaryninja._binaryninjacore import BNGetBundledPluginDirectory
+ if core_platform == "Darwin":
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.dylib"))
+
+ elif core_platform == "Linux":
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.so"))
+
+ elif (core_platform == "Windows") or (core_platform.find("CYGWIN_NT") == 0):
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "warp_ninja.dll"))
+ else:
+ raise Exception("OS not supported")
+else:
+ from binaryninja._binaryninjacore import BNGetUserPluginDirectory
+ if core_platform == "Darwin":
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.dylib"))
+
+ elif core_platform == "Linux":
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.so"))
+
+ elif (core_platform == "Windows") or (core_platform.find("CYGWIN_NT") == 0):
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "warp_ninja.dll"))
+ else:
+ raise Exception("OS not supported")
+
+def cstr(var) -> Optional[ctypes.c_char_p]:
+ if var is None:
+ return None
+ if isinstance(var, bytes):
+ return var
+ return var.encode("utf-8")
+
+def pyNativeStr(arg):
+ if isinstance(arg, str):
+ return arg
+ else:
+ return arg.decode('utf8')
+
+def free_string(value:ctypes.c_char_p) -> None:
+ BNFreeString(ctypes.cast(value, ctypes.POINTER(ctypes.c_byte)))
+
+from binaryninja._binaryninjacore import BNFreeString
+# Type definitions
+from binaryninja._binaryninjacore import BNArchitecture, BNArchitectureHandle
+from binaryninja._binaryninjacore import BNBasicBlock, BNBasicBlockHandle
+from binaryninja._binaryninjacore import BNBinaryView, BNBinaryViewHandle
+from binaryninja._binaryninjacore import BNFunction, BNFunctionHandle
+from binaryninja._binaryninjacore import BNLowLevelILFunction, BNLowLevelILFunctionHandle
+from binaryninja._binaryninjacore import BNPlatform, BNPlatformHandle
+from binaryninja._binaryninjacore import BNSymbol, BNSymbolHandle
+from binaryninja._binaryninjacore import BNType, BNTypeHandle
+class BNWARPConstraint(ctypes.Structure):
+ pass
+BNWARPConstraintHandle = ctypes.POINTER(BNWARPConstraint)
+class BNWARPContainer(ctypes.Structure):
+ pass
+BNWARPContainerHandle = ctypes.POINTER(BNWARPContainer)
+class BNWARPFunction(ctypes.Structure):
+ pass
+BNWARPFunctionHandle = ctypes.POINTER(BNWARPFunction)
+class BNWARPFunctionComment(ctypes.Structure):
+ @property
+ def text(self):
+ return pyNativeStr(self._text)
+ @text.setter
+ def text(self, value):
+ self._text = cstr(value)
+BNWARPFunctionCommentHandle = ctypes.POINTER(BNWARPFunctionComment)
+class BNWARPTarget(ctypes.Structure):
+ pass
+BNWARPTargetHandle = ctypes.POINTER(BNWARPTarget)
+class BNWARPUUID(ctypes.Structure):
+ pass
+BNWARPUUIDHandle = ctypes.POINTER(BNWARPUUID)
+
+# Structure definitions
+BNWARPBasicBlockGUID = BNWARPUUID
+BNWARPBasicBlockGUIDHandle = BNWARPUUIDHandle
+BNWARPConstraintGUID = BNWARPUUID
+BNWARPConstraintGUIDHandle = BNWARPUUIDHandle
+BNWARPFunctionComment._fields_ = [
+ ("_text", ctypes.c_char_p),
+ ("offset", ctypes.c_longlong),
+ ]
+BNWARPFunctionGUID = BNWARPUUID
+BNWARPFunctionGUIDHandle = BNWARPUUIDHandle
+BNWARPSource = BNWARPUUID
+BNWARPSourceHandle = BNWARPUUIDHandle
+BNWARPTypeGUID = BNWARPUUID
+BNWARPTypeGUIDHandle = BNWARPUUIDHandle
+BNWARPUUID._fields_ = [
+ ("uuid", ctypes.c_ubyte * 16),
+ ]
+BNWARPConstraint._fields_ = [
+ ("guid", BNWARPConstraintGUID),
+ ("offset", ctypes.c_longlong),
+ ]
+
+# Function definitions
+# -------------------------------------------------------
+# _BNWARPContainerAddFunctions
+
+_BNWARPContainerAddFunctions = core.BNWARPContainerAddFunctions
+_BNWARPContainerAddFunctions.restype = ctypes.c_bool
+_BNWARPContainerAddFunctions.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPTarget),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerAddFunctions(
+ container: ctypes.POINTER(BNWARPContainer),
+ target: ctypes.POINTER(BNWARPTarget),
+ source: ctypes.POINTER(BNWARPSource),
+ functions: ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ count: int
+ ) -> bool:
+ return _BNWARPContainerAddFunctions(container, target, source, functions, count)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerAddSource
+
+_BNWARPContainerAddSource = core.BNWARPContainerAddSource
+_BNWARPContainerAddSource.restype = ctypes.c_bool
+_BNWARPContainerAddSource.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.c_char_p,
+ ctypes.POINTER(BNWARPSource),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerAddSource(
+ container: ctypes.POINTER(BNWARPContainer),
+ sourcePath: Optional[str],
+ result: ctypes.POINTER(BNWARPSource)
+ ) -> bool:
+ return _BNWARPContainerAddSource(container, cstr(sourcePath), result)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerAddTypes
+
+_BNWARPContainerAddTypes = core.BNWARPContainerAddTypes
+_BNWARPContainerAddTypes.restype = ctypes.c_bool
+_BNWARPContainerAddTypes.argtypes = [
+ ctypes.POINTER(BNBinaryView),
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(ctypes.POINTER(BNType)),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerAddTypes(
+ view: ctypes.POINTER(BNBinaryView),
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource),
+ types: ctypes.POINTER(ctypes.POINTER(BNType)),
+ count: int
+ ) -> bool:
+ return _BNWARPContainerAddTypes(view, container, source, types, count)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerCommitSource
+
+_BNWARPContainerCommitSource = core.BNWARPContainerCommitSource
+_BNWARPContainerCommitSource.restype = ctypes.c_bool
+_BNWARPContainerCommitSource.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerCommitSource(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource)
+ ) -> bool:
+ return _BNWARPContainerCommitSource(container, source)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetFunctionsWithGUID
+
+_BNWARPContainerGetFunctionsWithGUID = core.BNWARPContainerGetFunctionsWithGUID
+_BNWARPContainerGetFunctionsWithGUID.restype = ctypes.POINTER(ctypes.POINTER(BNWARPFunction))
+_BNWARPContainerGetFunctionsWithGUID.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPTarget),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(BNWARPFunctionGUID),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetFunctionsWithGUID(
+ container: ctypes.POINTER(BNWARPContainer),
+ target: ctypes.POINTER(BNWARPTarget),
+ source: ctypes.POINTER(BNWARPSource),
+ guid: ctypes.POINTER(BNWARPFunctionGUID),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(ctypes.POINTER(BNWARPFunction))]:
+ result = _BNWARPContainerGetFunctionsWithGUID(container, target, source, guid, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetName
+
+_BNWARPContainerGetName = core.BNWARPContainerGetName
+_BNWARPContainerGetName.restype = ctypes.POINTER(ctypes.c_byte)
+_BNWARPContainerGetName.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetName(
+ container: ctypes.POINTER(BNWARPContainer)
+ ) -> Optional[Optional[str]]:
+ result = _BNWARPContainerGetName(container)
+ if not result:
+ return None
+ string = str(pyNativeStr(ctypes.cast(result, ctypes.c_char_p).value))
+ BNFreeString(result)
+ return string
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetSourcePath
+
+_BNWARPContainerGetSourcePath = core.BNWARPContainerGetSourcePath
+_BNWARPContainerGetSourcePath.restype = ctypes.POINTER(ctypes.c_byte)
+_BNWARPContainerGetSourcePath.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetSourcePath(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource)
+ ) -> Optional[Optional[str]]:
+ result = _BNWARPContainerGetSourcePath(container, source)
+ if not result:
+ return None
+ string = str(pyNativeStr(ctypes.cast(result, ctypes.c_char_p).value))
+ BNFreeString(result)
+ return string
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetSources
+
+_BNWARPContainerGetSources = core.BNWARPContainerGetSources
+_BNWARPContainerGetSources.restype = ctypes.POINTER(BNWARPSource)
+_BNWARPContainerGetSources.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetSources(
+ container: ctypes.POINTER(BNWARPContainer),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPSource)]:
+ result = _BNWARPContainerGetSources(container, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetSourcesWithFunctionGUID
+
+_BNWARPContainerGetSourcesWithFunctionGUID = core.BNWARPContainerGetSourcesWithFunctionGUID
+_BNWARPContainerGetSourcesWithFunctionGUID.restype = ctypes.POINTER(BNWARPSource)
+_BNWARPContainerGetSourcesWithFunctionGUID.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPTarget),
+ ctypes.POINTER(BNWARPFunctionGUID),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetSourcesWithFunctionGUID(
+ container: ctypes.POINTER(BNWARPContainer),
+ target: ctypes.POINTER(BNWARPTarget),
+ guid: ctypes.POINTER(BNWARPFunctionGUID),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPSource)]:
+ result = _BNWARPContainerGetSourcesWithFunctionGUID(container, target, guid, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetSourcesWithTypeGUID
+
+_BNWARPContainerGetSourcesWithTypeGUID = core.BNWARPContainerGetSourcesWithTypeGUID
+_BNWARPContainerGetSourcesWithTypeGUID.restype = ctypes.POINTER(BNWARPSource)
+_BNWARPContainerGetSourcesWithTypeGUID.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPTypeGUID),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetSourcesWithTypeGUID(
+ container: ctypes.POINTER(BNWARPContainer),
+ guid: ctypes.POINTER(BNWARPTypeGUID),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPSource)]:
+ result = _BNWARPContainerGetSourcesWithTypeGUID(container, guid, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetTypeGUIDsWithName
+
+_BNWARPContainerGetTypeGUIDsWithName = core.BNWARPContainerGetTypeGUIDsWithName
+_BNWARPContainerGetTypeGUIDsWithName.restype = ctypes.POINTER(BNWARPTypeGUID)
+_BNWARPContainerGetTypeGUIDsWithName.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.c_char_p,
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetTypeGUIDsWithName(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource),
+ name: Optional[str],
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPTypeGUID)]:
+ result = _BNWARPContainerGetTypeGUIDsWithName(container, source, cstr(name), count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerGetTypeWithGUID
+
+_BNWARPContainerGetTypeWithGUID = core.BNWARPContainerGetTypeWithGUID
+_BNWARPContainerGetTypeWithGUID.restype = ctypes.POINTER(BNType)
+_BNWARPContainerGetTypeWithGUID.argtypes = [
+ ctypes.POINTER(BNArchitecture),
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(BNWARPTypeGUID),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerGetTypeWithGUID(
+ arch: ctypes.POINTER(BNArchitecture),
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource),
+ guid: ctypes.POINTER(BNWARPTypeGUID)
+ ) -> Optional[ctypes.POINTER(BNType)]:
+ result = _BNWARPContainerGetTypeWithGUID(arch, container, source, guid)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPContainerIsSourceUncommitted
+
+_BNWARPContainerIsSourceUncommitted = core.BNWARPContainerIsSourceUncommitted
+_BNWARPContainerIsSourceUncommitted.restype = ctypes.c_bool
+_BNWARPContainerIsSourceUncommitted.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerIsSourceUncommitted(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource)
+ ) -> bool:
+ return _BNWARPContainerIsSourceUncommitted(container, source)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerIsSourceWritable
+
+_BNWARPContainerIsSourceWritable = core.BNWARPContainerIsSourceWritable
+_BNWARPContainerIsSourceWritable.restype = ctypes.c_bool
+_BNWARPContainerIsSourceWritable.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerIsSourceWritable(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource)
+ ) -> bool:
+ return _BNWARPContainerIsSourceWritable(container, source)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerRemoveFunctions
+
+_BNWARPContainerRemoveFunctions = core.BNWARPContainerRemoveFunctions
+_BNWARPContainerRemoveFunctions.restype = ctypes.c_bool
+_BNWARPContainerRemoveFunctions.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPTarget),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerRemoveFunctions(
+ container: ctypes.POINTER(BNWARPContainer),
+ target: ctypes.POINTER(BNWARPTarget),
+ source: ctypes.POINTER(BNWARPSource),
+ functions: ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ count: int
+ ) -> bool:
+ return _BNWARPContainerRemoveFunctions(container, target, source, functions, count)
+
+
+# -------------------------------------------------------
+# _BNWARPContainerRemoveTypes
+
+_BNWARPContainerRemoveTypes = core.BNWARPContainerRemoveTypes
+_BNWARPContainerRemoveTypes.restype = ctypes.c_bool
+_BNWARPContainerRemoveTypes.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ctypes.POINTER(BNWARPSource),
+ ctypes.POINTER(BNWARPTypeGUID),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPContainerRemoveTypes(
+ container: ctypes.POINTER(BNWARPContainer),
+ source: ctypes.POINTER(BNWARPSource),
+ types: ctypes.POINTER(BNWARPTypeGUID),
+ count: int
+ ) -> bool:
+ return _BNWARPContainerRemoveTypes(container, source, types, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeConstraintList
+
+_BNWARPFreeConstraintList = core.BNWARPFreeConstraintList
+_BNWARPFreeConstraintList.restype = None
+_BNWARPFreeConstraintList.argtypes = [
+ ctypes.POINTER(BNWARPConstraint),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeConstraintList(
+ constraints: ctypes.POINTER(BNWARPConstraint),
+ count: int
+ ) -> None:
+ return _BNWARPFreeConstraintList(constraints, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeContainerList
+
+_BNWARPFreeContainerList = core.BNWARPFreeContainerList
+_BNWARPFreeContainerList.restype = None
+_BNWARPFreeContainerList.argtypes = [
+ ctypes.POINTER(ctypes.POINTER(BNWARPContainer)),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeContainerList(
+ containers: ctypes.POINTER(ctypes.POINTER(BNWARPContainer)),
+ count: int
+ ) -> None:
+ return _BNWARPFreeContainerList(containers, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeContainerReference
+
+_BNWARPFreeContainerReference = core.BNWARPFreeContainerReference
+_BNWARPFreeContainerReference.restype = None
+_BNWARPFreeContainerReference.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeContainerReference(
+ container: ctypes.POINTER(BNWARPContainer)
+ ) -> None:
+ return _BNWARPFreeContainerReference(container)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeFunctionCommentList
+
+_BNWARPFreeFunctionCommentList = core.BNWARPFreeFunctionCommentList
+_BNWARPFreeFunctionCommentList.restype = None
+_BNWARPFreeFunctionCommentList.argtypes = [
+ ctypes.POINTER(BNWARPFunctionComment),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeFunctionCommentList(
+ comments: ctypes.POINTER(BNWARPFunctionComment),
+ count: int
+ ) -> None:
+ return _BNWARPFreeFunctionCommentList(comments, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeFunctionList
+
+_BNWARPFreeFunctionList = core.BNWARPFreeFunctionList
+_BNWARPFreeFunctionList.restype = None
+_BNWARPFreeFunctionList.argtypes = [
+ ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeFunctionList(
+ functions: ctypes.POINTER(ctypes.POINTER(BNWARPFunction)),
+ count: int
+ ) -> None:
+ return _BNWARPFreeFunctionList(functions, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeFunctionReference
+
+_BNWARPFreeFunctionReference = core.BNWARPFreeFunctionReference
+_BNWARPFreeFunctionReference.restype = None
+_BNWARPFreeFunctionReference.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeFunctionReference(
+ function: ctypes.POINTER(BNWARPFunction)
+ ) -> None:
+ return _BNWARPFreeFunctionReference(function)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeTargetReference
+
+_BNWARPFreeTargetReference = core.BNWARPFreeTargetReference
+_BNWARPFreeTargetReference.restype = None
+_BNWARPFreeTargetReference.argtypes = [
+ ctypes.POINTER(BNWARPTarget),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeTargetReference(
+ target: ctypes.POINTER(BNWARPTarget)
+ ) -> None:
+ return _BNWARPFreeTargetReference(target)
+
+
+# -------------------------------------------------------
+# _BNWARPFreeUUIDList
+
+_BNWARPFreeUUIDList = core.BNWARPFreeUUIDList
+_BNWARPFreeUUIDList.restype = None
+_BNWARPFreeUUIDList.argtypes = [
+ ctypes.POINTER(BNWARPUUID),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFreeUUIDList(
+ uuids: ctypes.POINTER(BNWARPUUID),
+ count: int
+ ) -> None:
+ return _BNWARPFreeUUIDList(uuids, count)
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionApply
+
+_BNWARPFunctionApply = core.BNWARPFunctionApply
+_BNWARPFunctionApply.restype = None
+_BNWARPFunctionApply.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(BNFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionApply(
+ function: ctypes.POINTER(BNWARPFunction),
+ analysisFunction: ctypes.POINTER(BNFunction)
+ ) -> None:
+ return _BNWARPFunctionApply(function, analysisFunction)
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetComments
+
+_BNWARPFunctionGetComments = core.BNWARPFunctionGetComments
+_BNWARPFunctionGetComments.restype = ctypes.POINTER(BNWARPFunctionComment)
+_BNWARPFunctionGetComments.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetComments(
+ function: ctypes.POINTER(BNWARPFunction),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPFunctionComment)]:
+ result = _BNWARPFunctionGetComments(function, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetConstraints
+
+_BNWARPFunctionGetConstraints = core.BNWARPFunctionGetConstraints
+_BNWARPFunctionGetConstraints.restype = ctypes.POINTER(BNWARPConstraint)
+_BNWARPFunctionGetConstraints.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetConstraints(
+ function: ctypes.POINTER(BNWARPFunction),
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(BNWARPConstraint)]:
+ result = _BNWARPFunctionGetConstraints(function, count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetGUID
+
+_BNWARPFunctionGetGUID = core.BNWARPFunctionGetGUID
+_BNWARPFunctionGetGUID.restype = BNWARPFunctionGUID
+_BNWARPFunctionGetGUID.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetGUID(
+ function: ctypes.POINTER(BNWARPFunction)
+ ) -> BNWARPFunctionGUID:
+ return _BNWARPFunctionGetGUID(function)
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetSymbol
+
+_BNWARPFunctionGetSymbol = core.BNWARPFunctionGetSymbol
+_BNWARPFunctionGetSymbol.restype = ctypes.POINTER(BNSymbol)
+_BNWARPFunctionGetSymbol.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(BNFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetSymbol(
+ function: ctypes.POINTER(BNWARPFunction),
+ analysisFunction: ctypes.POINTER(BNFunction)
+ ) -> Optional[ctypes.POINTER(BNSymbol)]:
+ result = _BNWARPFunctionGetSymbol(function, analysisFunction)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetSymbolName
+
+_BNWARPFunctionGetSymbolName = core.BNWARPFunctionGetSymbolName
+_BNWARPFunctionGetSymbolName.restype = ctypes.POINTER(ctypes.c_byte)
+_BNWARPFunctionGetSymbolName.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetSymbolName(
+ function: ctypes.POINTER(BNWARPFunction)
+ ) -> Optional[Optional[str]]:
+ result = _BNWARPFunctionGetSymbolName(function)
+ if not result:
+ return None
+ string = str(pyNativeStr(ctypes.cast(result, ctypes.c_char_p).value))
+ BNFreeString(result)
+ return string
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionGetType
+
+_BNWARPFunctionGetType = core.BNWARPFunctionGetType
+_BNWARPFunctionGetType.restype = ctypes.POINTER(BNType)
+_BNWARPFunctionGetType.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(BNFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionGetType(
+ function: ctypes.POINTER(BNWARPFunction),
+ analysisFunction: ctypes.POINTER(BNFunction)
+ ) -> Optional[ctypes.POINTER(BNType)]:
+ result = _BNWARPFunctionGetType(function, analysisFunction)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPFunctionsEqual
+
+_BNWARPFunctionsEqual = core.BNWARPFunctionsEqual
+_BNWARPFunctionsEqual.restype = ctypes.c_bool
+_BNWARPFunctionsEqual.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ctypes.POINTER(BNWARPFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPFunctionsEqual(
+ functionA: ctypes.POINTER(BNWARPFunction),
+ functionB: ctypes.POINTER(BNWARPFunction)
+ ) -> bool:
+ return _BNWARPFunctionsEqual(functionA, functionB)
+
+
+# -------------------------------------------------------
+# _BNWARPGetAnalysisFunctionGUID
+
+_BNWARPGetAnalysisFunctionGUID = core.BNWARPGetAnalysisFunctionGUID
+_BNWARPGetAnalysisFunctionGUID.restype = ctypes.c_bool
+_BNWARPGetAnalysisFunctionGUID.argtypes = [
+ ctypes.POINTER(BNFunction),
+ ctypes.POINTER(BNWARPFunctionGUID),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetAnalysisFunctionGUID(
+ analysisFunction: ctypes.POINTER(BNFunction),
+ result: ctypes.POINTER(BNWARPFunctionGUID)
+ ) -> bool:
+ return _BNWARPGetAnalysisFunctionGUID(analysisFunction, result)
+
+
+# -------------------------------------------------------
+# _BNWARPGetBasicBlockGUID
+
+_BNWARPGetBasicBlockGUID = core.BNWARPGetBasicBlockGUID
+_BNWARPGetBasicBlockGUID.restype = ctypes.c_bool
+_BNWARPGetBasicBlockGUID.argtypes = [
+ ctypes.POINTER(BNBasicBlock),
+ ctypes.POINTER(BNWARPBasicBlockGUID),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetBasicBlockGUID(
+ basicBlock: ctypes.POINTER(BNBasicBlock),
+ result: ctypes.POINTER(BNWARPBasicBlockGUID)
+ ) -> bool:
+ return _BNWARPGetBasicBlockGUID(basicBlock, result)
+
+
+# -------------------------------------------------------
+# _BNWARPGetContainers
+
+_BNWARPGetContainers = core.BNWARPGetContainers
+_BNWARPGetContainers.restype = ctypes.POINTER(ctypes.POINTER(BNWARPContainer))
+_BNWARPGetContainers.argtypes = [
+ ctypes.POINTER(ctypes.c_ulonglong),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetContainers(
+ count: ctypes.POINTER(ctypes.c_ulonglong)
+ ) -> Optional[ctypes.POINTER(ctypes.POINTER(BNWARPContainer))]:
+ result = _BNWARPGetContainers(count)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPGetFunction
+
+_BNWARPGetFunction = core.BNWARPGetFunction
+_BNWARPGetFunction.restype = ctypes.POINTER(BNWARPFunction)
+_BNWARPGetFunction.argtypes = [
+ ctypes.POINTER(BNFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetFunction(
+ analysisFunction: ctypes.POINTER(BNFunction)
+ ) -> Optional[ctypes.POINTER(BNWARPFunction)]:
+ result = _BNWARPGetFunction(analysisFunction)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPGetMatchedFunction
+
+_BNWARPGetMatchedFunction = core.BNWARPGetMatchedFunction
+_BNWARPGetMatchedFunction.restype = ctypes.POINTER(BNWARPFunction)
+_BNWARPGetMatchedFunction.argtypes = [
+ ctypes.POINTER(BNFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetMatchedFunction(
+ analysisFunction: ctypes.POINTER(BNFunction)
+ ) -> Optional[ctypes.POINTER(BNWARPFunction)]:
+ result = _BNWARPGetMatchedFunction(analysisFunction)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPGetTarget
+
+_BNWARPGetTarget = core.BNWARPGetTarget
+_BNWARPGetTarget.restype = ctypes.POINTER(BNWARPTarget)
+_BNWARPGetTarget.argtypes = [
+ ctypes.POINTER(BNPlatform),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPGetTarget(
+ platform: ctypes.POINTER(BNPlatform)
+ ) -> Optional[ctypes.POINTER(BNWARPTarget)]:
+ result = _BNWARPGetTarget(platform)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPIsLiftedInstructionBlacklisted
+
+_BNWARPIsLiftedInstructionBlacklisted = core.BNWARPIsLiftedInstructionBlacklisted
+_BNWARPIsLiftedInstructionBlacklisted.restype = ctypes.c_bool
+_BNWARPIsLiftedInstructionBlacklisted.argtypes = [
+ ctypes.POINTER(BNLowLevelILFunction),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPIsLiftedInstructionBlacklisted(
+ liftedFunction: ctypes.POINTER(BNLowLevelILFunction),
+ idx: int
+ ) -> bool:
+ return _BNWARPIsLiftedInstructionBlacklisted(liftedFunction, idx)
+
+
+# -------------------------------------------------------
+# _BNWARPIsLiftedInstructionVariant
+
+_BNWARPIsLiftedInstructionVariant = core.BNWARPIsLiftedInstructionVariant
+_BNWARPIsLiftedInstructionVariant.restype = ctypes.c_bool
+_BNWARPIsLiftedInstructionVariant.argtypes = [
+ ctypes.POINTER(BNLowLevelILFunction),
+ ctypes.c_ulonglong,
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPIsLiftedInstructionVariant(
+ liftedFunction: ctypes.POINTER(BNLowLevelILFunction),
+ idx: int
+ ) -> bool:
+ return _BNWARPIsLiftedInstructionVariant(liftedFunction, idx)
+
+
+# -------------------------------------------------------
+# _BNWARPNewContainerReference
+
+_BNWARPNewContainerReference = core.BNWARPNewContainerReference
+_BNWARPNewContainerReference.restype = ctypes.POINTER(BNWARPContainer)
+_BNWARPNewContainerReference.argtypes = [
+ ctypes.POINTER(BNWARPContainer),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPNewContainerReference(
+ container: ctypes.POINTER(BNWARPContainer)
+ ) -> Optional[ctypes.POINTER(BNWARPContainer)]:
+ result = _BNWARPNewContainerReference(container)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPNewFunctionReference
+
+_BNWARPNewFunctionReference = core.BNWARPNewFunctionReference
+_BNWARPNewFunctionReference.restype = ctypes.POINTER(BNWARPFunction)
+_BNWARPNewFunctionReference.argtypes = [
+ ctypes.POINTER(BNWARPFunction),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPNewFunctionReference(
+ function: ctypes.POINTER(BNWARPFunction)
+ ) -> Optional[ctypes.POINTER(BNWARPFunction)]:
+ result = _BNWARPNewFunctionReference(function)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPNewTargetReference
+
+_BNWARPNewTargetReference = core.BNWARPNewTargetReference
+_BNWARPNewTargetReference.restype = ctypes.POINTER(BNWARPTarget)
+_BNWARPNewTargetReference.argtypes = [
+ ctypes.POINTER(BNWARPTarget),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPNewTargetReference(
+ target: ctypes.POINTER(BNWARPTarget)
+ ) -> Optional[ctypes.POINTER(BNWARPTarget)]:
+ result = _BNWARPNewTargetReference(target)
+ if not result:
+ return None
+ return result
+
+
+# -------------------------------------------------------
+# _BNWARPRunMatcher
+
+_BNWARPRunMatcher = core.BNWARPRunMatcher
+_BNWARPRunMatcher.restype = None
+_BNWARPRunMatcher.argtypes = [
+ ctypes.POINTER(BNBinaryView),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPRunMatcher(
+ view: ctypes.POINTER(BNBinaryView)
+ ) -> None:
+ return _BNWARPRunMatcher(view)
+
+
+# -------------------------------------------------------
+# _BNWARPUUIDEqual
+
+_BNWARPUUIDEqual = core.BNWARPUUIDEqual
+_BNWARPUUIDEqual.restype = ctypes.c_bool
+_BNWARPUUIDEqual.argtypes = [
+ ctypes.POINTER(BNWARPUUID),
+ ctypes.POINTER(BNWARPUUID),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPUUIDEqual(
+ a: ctypes.POINTER(BNWARPUUID),
+ b: ctypes.POINTER(BNWARPUUID)
+ ) -> bool:
+ return _BNWARPUUIDEqual(a, b)
+
+
+# -------------------------------------------------------
+# _BNWARPUUIDGetString
+
+_BNWARPUUIDGetString = core.BNWARPUUIDGetString
+_BNWARPUUIDGetString.restype = ctypes.POINTER(ctypes.c_byte)
+_BNWARPUUIDGetString.argtypes = [
+ ctypes.POINTER(BNWARPUUID),
+ ]
+
+
+# noinspection PyPep8Naming
+def BNWARPUUIDGetString(
+ uuid: ctypes.POINTER(BNWARPUUID)
+ ) -> Optional[Optional[str]]:
+ result = _BNWARPUUIDGetString(uuid)
+ if not result:
+ return None
+ string = str(pyNativeStr(ctypes.cast(result, ctypes.c_char_p).value))
+ BNFreeString(result)
+ return string
+
+
+
+# Helper functions
+def handle_of_type(value, handle_type):
+ if isinstance(value, ctypes.POINTER(handle_type)) or isinstance(value, ctypes.c_void_p):
+ return ctypes.cast(value, ctypes.POINTER(handle_type))
+ raise ValueError('expected pointer to %s' % str(handle_type))
diff --git a/plugins/warp/api/python/_warpcore_template.py b/plugins/warp/api/python/_warpcore_template.py
new file mode 100644
index 00000000..fd923450
--- /dev/null
+++ b/plugins/warp/api/python/_warpcore_template.py
@@ -0,0 +1,58 @@
+import binaryninja
+import ctypes, os
+
+from typing import Optional
+from . import warp_enums
+# Load core module
+import platform
+core = None
+core_platform = platform.system()
+
+from binaryninja import Settings
+if Settings().get_bool("corePlugins.warp"):
+ from binaryninja._binaryninjacore import BNGetBundledPluginDirectory
+ if core_platform == "Darwin":
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.dylib"))
+
+ elif core_platform == "Linux":
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.so"))
+
+ elif (core_platform == "Windows") or (core_platform.find("CYGWIN_NT") == 0):
+ _base_path = BNGetBundledPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "warp_ninja.dll"))
+ else:
+ raise Exception("OS not supported")
+else:
+ from binaryninja._binaryninjacore import BNGetUserPluginDirectory
+ if core_platform == "Darwin":
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.dylib"))
+
+ elif core_platform == "Linux":
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "libwarp_ninja.so"))
+
+ elif (core_platform == "Windows") or (core_platform.find("CYGWIN_NT") == 0):
+ _base_path = BNGetUserPluginDirectory()
+ core = ctypes.CDLL(os.path.join(_base_path, "warp_ninja.dll"))
+ else:
+ raise Exception("OS not supported")
+
+def cstr(var) -> Optional[ctypes.c_char_p]:
+ if var is None:
+ return None
+ if isinstance(var, bytes):
+ return var
+ return var.encode("utf-8")
+
+def pyNativeStr(arg):
+ if isinstance(arg, str):
+ return arg
+ else:
+ return arg.decode('utf8')
+
+def free_string(value:ctypes.c_char_p) -> None:
+ BNFreeString(ctypes.cast(value, ctypes.POINTER(ctypes.c_byte)))
+
diff --git a/plugins/warp/api/python/generator.cpp b/plugins/warp/api/python/generator.cpp
new file mode 100644
index 00000000..f40fc01a
--- /dev/null
+++ b/plugins/warp/api/python/generator.cpp
@@ -0,0 +1,652 @@
+/*
+Copyright 2020-2025 Vector 35 Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+
+
+#include <stdio.h>
+#include <inttypes.h>
+#include "binaryninjaapi.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+
+map<string, string> g_pythonKeywordReplacements = {
+ {"False", "False_"},
+ {"True", "True_"},
+ {"None", "None_"},
+ {"and", "and_"},
+ {"as", "as_"},
+ {"assert", "assert_"},
+ {"async", "async_"},
+ {"await", "await_"},
+ {"break", "break_"},
+ {"class", "class_"},
+ {"continue", "continue_"},
+ {"def", "def_"},
+ {"del", "del_"},
+ {"elif", "elif_"},
+ {"else", "else_"},
+ {"except", "except_"},
+ {"finally", "finally_"},
+ {"for", "for_"},
+ {"from", "from_"},
+ {"global", "global_"},
+ {"if", "if_"},
+ {"import", "import_"},
+ {"in", "in_"},
+ {"is", "is_"},
+ {"lambda", "lambda_"},
+ {"nonlocal", "nonlocal_"},
+ {"not", "not_"},
+ {"or", "or_"},
+ {"pass", "pass_"},
+ {"raise", "raise_"},
+ {"return", "return_"},
+ {"try", "try_"},
+ {"while", "while_"},
+ {"with", "with_"},
+ {"yield", "yield_"},
+};
+
+
+void OutputType(FILE* out, Type* type, bool isReturnType = false, bool isCallback = false)
+{
+ switch (type->GetClass())
+ {
+ case BoolTypeClass:
+ fprintf(out, "ctypes.c_bool");
+ break;
+ case IntegerTypeClass:
+ switch (type->GetWidth())
+ {
+ case 1:
+ if (type->IsSigned())
+ fprintf(out, "ctypes.c_byte");
+ else
+ fprintf(out, "ctypes.c_ubyte");
+ break;
+ case 2:
+ if (type->IsSigned())
+ fprintf(out, "ctypes.c_short");
+ else
+ fprintf(out, "ctypes.c_ushort");
+ break;
+ case 4:
+ if (type->IsSigned())
+ fprintf(out, "ctypes.c_int");
+ else
+ fprintf(out, "ctypes.c_uint");
+ break;
+ default:
+ if (type->IsSigned())
+ fprintf(out, "ctypes.c_longlong");
+ else
+ fprintf(out, "ctypes.c_ulonglong");
+ break;
+ }
+ break;
+ case FloatTypeClass:
+ if (type->GetWidth() == 4)
+ fprintf(out, "ctypes.c_float");
+ else
+ fprintf(out, "ctypes.c_double");
+ break;
+ case NamedTypeReferenceClass:
+ if (type->GetNamedTypeReference()->GetTypeReferenceClass() == EnumNamedTypeClass)
+ {
+ string name = type->GetNamedTypeReference()->GetName().GetString();
+ if (name.size() > 16 && name.substr(0, 11) == "_BNDebugger")
+ name = name.substr(3);
+ else if (name.size() > 15 && name.substr(0, 10) == "BNDebugger")
+ name = name.substr(2);
+ else if (name.size() > 15 && name.substr(0, 7) == "BNDebug")
+ name = name.substr(2);
+ else if (name.size() > 2 && name.substr(0, 2) == "BN")
+ name = name.substr(2);
+ fprintf(out, "%sEnum", name.c_str());
+ }
+ else
+ {
+ fprintf(out, "%s", type->GetNamedTypeReference()->GetName().GetString().c_str());
+ }
+ break;
+ case PointerTypeClass:
+ if (isCallback || (type->GetChildType()->GetClass() == VoidTypeClass))
+ {
+ fprintf(out, "ctypes.c_void_p");
+ break;
+ }
+ else if ((type->GetChildType()->GetClass() == IntegerTypeClass) &&
+ (type->GetChildType()->GetWidth() == 1) && (type->GetChildType()->IsSigned()))
+ {
+ if (isReturnType)
+ fprintf(out, "ctypes.POINTER(ctypes.c_byte)");
+ else
+ fprintf(out, "ctypes.c_char_p");
+ break;
+ }
+ else if (type->GetChildType()->GetClass() == FunctionTypeClass)
+ {
+ fprintf(out, "ctypes.CFUNCTYPE(");
+ OutputType(out, type->GetChildType()->GetChildType().GetValue(), true, true);
+ for (auto& i : type->GetChildType()->GetParameters())
+ {
+ fprintf(out, ", ");
+ OutputType(out, i.type.GetValue());
+ }
+ fprintf(out, ")");
+ break;
+ }
+ fprintf(out, "ctypes.POINTER(");
+ OutputType(out, type->GetChildType().GetValue());
+ fprintf(out, ")");
+ break;
+ case ArrayTypeClass:
+ OutputType(out, type->GetChildType().GetValue());
+ fprintf(out, " * %" PRId64, type->GetElementCount());
+ break;
+ default:
+ fprintf(out, "None");
+ break;
+ }
+}
+
+
+void OutputSwizzledType(FILE* out, Type* type)
+{
+ switch (type->GetClass())
+ {
+ case BoolTypeClass:
+ fprintf(out, "bool");
+ break;
+ case IntegerTypeClass:
+ fprintf(out, "int");
+ break;
+ case FloatTypeClass:
+ fprintf(out, "float");
+ break;
+ case NamedTypeReferenceClass:
+ if (type->GetNamedTypeReference()->GetTypeReferenceClass() == EnumNamedTypeClass)
+ {
+ string name = type->GetNamedTypeReference()->GetName().GetString();
+ if (name.size() > 16 && name.substr(0, 11) == "_BNDebugger")
+ name = name.substr(3);
+ else if (name.size() > 15 && name.substr(0, 10) == "BNDebugger")
+ name = name.substr(2);
+ else if (name.size() > 15 && name.substr(0, 7) == "BNDebug")
+ name = name.substr(2);
+ else if (name.size() > 2 && name.substr(0, 2) == "BN")
+ name = name.substr(2);
+ fprintf(out, "%sEnum", name.c_str());
+ }
+ else
+ {
+ fprintf(out, "%s", type->GetNamedTypeReference()->GetName().GetString().c_str());
+ }
+ break;
+ case PointerTypeClass:
+ if (type->GetChildType()->GetClass() == VoidTypeClass)
+ {
+ fprintf(out, "Optional[ctypes.c_void_p]");
+ break;
+ }
+ else if ((type->GetChildType()->GetClass() == IntegerTypeClass) &&
+ (type->GetChildType()->GetWidth() == 1) && (type->GetChildType()->IsSigned()))
+ {
+ fprintf(out, "Optional[str]");
+ break;
+ }
+ else if (type->GetChildType()->GetClass() == FunctionTypeClass)
+ {
+ fprintf(out, "ctypes.CFUNCTYPE(");
+ OutputType(out, type->GetChildType()->GetChildType().GetValue(), true, true);
+ for (auto& i : type->GetChildType()->GetParameters())
+ {
+ fprintf(out, ", ");
+ OutputType(out, i.type.GetValue());
+ }
+ fprintf(out, ")");
+ break;
+ }
+ fprintf(out, "ctypes.POINTER(");
+ OutputType(out, type->GetChildType().GetValue());
+ fprintf(out, ")");
+ break;
+ case ArrayTypeClass:
+ OutputType(out, type->GetChildType().GetValue());
+ fprintf(out, " * %" PRId64, type->GetElementCount());
+ break;
+ default:
+ fprintf(out, "None");
+ break;
+ }
+}
+
+
+int main(int argc, char* argv[])
+{
+ if (argc < 5)
+ {
+ fprintf(stderr, "Usage: generator <header> <output> <output_template> <output_enum>\n");
+ return 1;
+ }
+
+ // Parse API header to get type and function information
+ map<QualifiedName, Ref<Type>> types, vars, funcs;
+ string errors;
+ auto arch = new CoreArchitecture(BNGetNativeTypeParserArchitecture());
+
+ // Enable ephemeral settings
+ Settings::Instance()->LoadSettingsFile("");
+ Settings::Instance()->Set("analysis.types.parserName", "ClangTypeParser");
+ bool ok = arch->GetStandalonePlatform()->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors);
+
+ if (!ok)
+ {
+ fprintf(stderr, "Errors: %s\n", errors.c_str());
+ return 1;
+ }
+
+ FILE* out = fopen(argv[2], "w");
+ FILE* out_template = fopen(argv[3], "r");
+ FILE* enums = fopen(argv[4], "w");
+
+ fprintf(enums, "import enum\n");
+
+ // Copy the content of the template to the output file
+ int c;
+ while((c = fgetc(out_template)) != EOF)
+ fputc(c, out);
+
+ // Create type objects
+ fprintf(out, "from binaryninja._binaryninjacore import BNFreeString\n");
+ fprintf(out, "# Type definitions\n");
+ for (auto& i : types)
+ {
+ string name;
+ if (i.first.size() != 1)
+ continue;
+ name = i.first[0];
+ if (name == "BNBinaryView")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNBinaryView, BNBinaryViewHandle\n");
+ continue;
+ }
+ if (name == "BNArchitecture")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNArchitecture, BNArchitectureHandle\n");
+ continue;
+ }
+ if (name == "BNBasicBlock")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNBasicBlock, BNBasicBlockHandle\n");
+ continue;
+ }
+ if (name == "BNFunction")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNFunction, BNFunctionHandle\n");
+ continue;
+ }
+ if (name == "BNLowLevelILFunction")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNLowLevelILFunction, BNLowLevelILFunctionHandle\n");
+ continue;
+ }
+ if (name == "BNPlatform")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNPlatform, BNPlatformHandle\n");
+ continue;
+ }
+ if (name == "BNSymbol")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNSymbol, BNSymbolHandle\n");
+ continue;
+ }
+ if (name == "BNType")
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import BNType, BNTypeHandle\n");
+ continue;
+ }
+ if (i.second->GetClass() == StructureTypeClass)
+ {
+ fprintf(out, "class %s(ctypes.Structure):\n", name.c_str());
+
+ // python uses str's, C uses byte-arrays
+ bool stringField = false;
+ for (auto& arg : i.second->GetStructure()->GetMembers())
+ {
+ if ((arg.type->GetClass() == PointerTypeClass) &&
+ (arg.type->GetChildType()->GetWidth() == 1) &&
+ (arg.type->GetChildType()->IsSigned()))
+ {
+ fprintf(out, "\t@property\n\tdef %s(self):\n\t\treturn pyNativeStr(self._%s)\n", arg.name.c_str(), arg.name.c_str());
+ fprintf(out, "\t@%s.setter\n\tdef %s(self, value):\n\t\tself._%s = cstr(value)\n", arg.name.c_str(), arg.name.c_str(), arg.name.c_str());
+ stringField = true;
+ }
+ }
+
+ if (!stringField)
+ fprintf(out, "\tpass\n");
+
+ fprintf(out, "%sHandle = ctypes.POINTER(%s)\n", name.c_str(), name.c_str());
+ }
+ else if (i.second->GetClass() == EnumerationTypeClass)
+ {
+ bool isBNAPIEnum = false;
+ if (name.size() > 16 && name.substr(0, 11) == "_BNDebugger")
+ name = name.substr(3);
+ else if (name.size() > 15 && name.substr(0, 10) == "BNDebugger")
+ name = name.substr(2);
+ else if (name.size() > 15 && name.substr(0, 7) == "BNDebug")
+ name = name.substr(2);
+ else if (name.size() > 2 && name.substr(0, 2) == "BN")
+ {
+ name = name.substr(2);
+ isBNAPIEnum = false;
+ }
+ else
+ continue;
+
+ if (isBNAPIEnum)
+ {
+ fprintf(out, "from binaryninja._binaryninjacore import %sEnum\n", name.c_str());
+ continue;
+ }
+
+ fprintf(out, "%sEnum = ctypes.c_int\n", name.c_str());
+
+ fprintf(enums, "\n\nclass %s(enum.IntEnum):\n", name.c_str());
+ for (auto& j : i.second->GetEnumeration()->GetMembers())
+ {
+ fprintf(enums, "\t%s = %" PRId64 "\n", j.name.c_str(), j.value);
+ }
+ }
+ else if ((i.second->GetClass() == BoolTypeClass) || (i.second->GetClass() == IntegerTypeClass) ||
+ (i.second->GetClass() == FloatTypeClass) || (i.second->GetClass() == ArrayTypeClass))
+ {
+ fprintf(out, "%s = ", name.c_str());
+ OutputType(out, i.second);
+ fprintf(out, "\n");
+ }
+ }
+
+
+ fprintf(out, "\n# Structure definitions\n");
+ set<QualifiedName> structsToProcess;
+ set<QualifiedName> finishedStructs;
+ for (auto& i : types)
+ structsToProcess.insert(i.first);
+ while (structsToProcess.size() != 0)
+ {
+ set<QualifiedName> currentStructList = structsToProcess;
+ structsToProcess.clear();
+ bool processedSome = false;
+ for (auto& i : currentStructList)
+ {
+ string name;
+ if (i.size() != 1)
+ continue;
+ Ref<Type> type = types[i];
+ name = i[0];
+ if ((type->GetClass() == StructureTypeClass) && (type->GetStructure()->GetMembers().size() != 0))
+ {
+ bool requiresDependency = false;
+ for (auto& j : type->GetStructure()->GetMembers())
+ {
+ if ((j.type->GetClass() == NamedTypeReferenceClass) &&
+ (finishedStructs.count(j.type->GetNamedTypeReference()->GetName()) == 0))
+ {
+ // This structure needs another structure that isn't fully defined yet, need to wait
+ // for the dependencies to be defined
+ structsToProcess.insert(i);
+ requiresDependency = true;
+ break;
+ }
+ }
+
+ if (requiresDependency)
+ continue;
+ fprintf(out, "%s._fields_ = [\n", name.c_str());
+ for (auto& j : type->GetStructure()->GetMembers())
+ {
+ // To help the python->C wrappers
+ if ((j.type->GetClass() == PointerTypeClass) &&
+ (j.type->GetChildType()->GetWidth() == 1) &&
+ (j.type->GetChildType()->IsSigned()))
+ {
+ fprintf(out, "\t\t(\"_%s\", ", j.name.c_str());
+ }
+ else
+ fprintf(out, "\t\t(\"%s\", ", j.name.c_str());
+ OutputType(out, j.type.GetValue());
+ fprintf(out, "),\n");
+ }
+ fprintf(out, "\t]\n");
+ finishedStructs.insert(i);
+ processedSome = true;
+ }
+ else if (type->GetClass() == NamedTypeReferenceClass)
+ {
+ if (type->GetNamedTypeReference()->GetTypeReferenceClass() == StructNamedTypeClass)
+ {
+ fprintf(out, "%s = %s\n", name.c_str(), type->GetNamedTypeReference()->GetName().GetString().c_str());
+ fprintf(out, "%sHandle = %sHandle\n", name.c_str(), type->GetNamedTypeReference()->GetName().GetString().c_str());
+ }
+ else if (type->GetNamedTypeReference()->GetTypeReferenceClass() == EnumNamedTypeClass)
+ {
+ fprintf(out, "%s = ctypes.c_int\n", name.c_str());
+ }
+ finishedStructs.insert(i);
+ processedSome = true;
+ }
+ }
+
+ if (!processedSome && structsToProcess.size() != 0)
+ {
+ fprintf(stderr, "Detected dependency cycle in structures\n");
+ for (auto& i : structsToProcess)
+ fprintf(stderr, "%s\n", i.GetString().c_str());
+ return 1;
+ }
+ }
+
+ fprintf(out, "\n# Function definitions\n");
+ for (auto& i : funcs)
+ {
+ string name;
+ if (i.first.size() != 1)
+ continue;
+ name = i.first[0];
+
+ // Check for a string result, these will be automatically wrapped to free the string
+ // memory and return a Python string
+ bool stringResult = (i.second->GetChildType()->GetClass() == PointerTypeClass) &&
+ (i.second->GetChildType()->GetChildType()->GetWidth() == 1) &&
+ (i.second->GetChildType()->GetChildType()->IsSigned());
+ // Pointer returns will be automatically wrapped to return None on null pointer
+ bool pointerResult = (i.second->GetChildType()->GetClass() == PointerTypeClass);
+
+ // From python -> C python3 requires str -> str.encode('charmap')
+ bool swizzleArgs = true;
+ if (name == "BNFreeString")
+ swizzleArgs = false;
+
+ bool callbackConvention = false;
+ if (name == "BNAllocString")
+ {
+ // Don't perform automatic wrapping of string allocation, and return a void
+ // pointer so that callback functions (which is the only valid use of BNDebuggerAllocString)
+ // can properly return the result
+ stringResult = false;
+ callbackConvention = true;
+ swizzleArgs = false;
+ }
+
+ string funcName = string("_") + name;
+
+ fprintf(out, "# -------------------------------------------------------\n");
+ fprintf(out, "# %s\n\n", funcName.c_str());
+ fprintf(out, "%s = core.%s\n", funcName.c_str(), name.c_str());
+ fprintf(out, "%s.restype = ", funcName.c_str());
+ OutputType(out, i.second->GetChildType().GetValue(), true, callbackConvention);
+ fprintf(out, "\n");
+ if (!i.second->HasVariableArguments())
+ {
+ fprintf(out, "%s.argtypes = [\n", funcName.c_str());
+ for (auto& j : i.second->GetParameters())
+ {
+ fprintf(out, "\t\t");
+ if (name == "BNFreeString")
+ {
+ // BNDebuggerFreeString expects a pointer to a string allocated by the core, so do not use
+ // a c_char_p here, as that would be allocated by the Python runtime. This can
+ // be enforced by outputting like a return value.
+ OutputType(out, j.type.GetValue(), true);
+ }
+ else
+ {
+ OutputType(out, j.type.GetValue());
+ }
+ fprintf(out, ",\n");
+ }
+ fprintf(out, "\t]");
+ }
+ else
+ {
+ // As of writing this, only BNLog's have variable instruction lengths, but in an attempt not to break in the future:
+ if (funcName.compare(0, 6, "_BNLog") == 0)
+ {
+ if (funcName != "_BNLog")
+ {
+ fprintf(out, "def %s(*args):\n", name.c_str());
+ fprintf(out, "\treturn %s(*[cstr(arg) for arg in args])\n\n", funcName.c_str());
+ continue;
+ }
+ else
+ {
+ fprintf(out, "def %s(level, *args):\n", name.c_str());
+ fprintf(out, "\treturn %s(level, *[cstr(arg) for arg in args])\n\n", funcName.c_str());
+ continue;
+ }
+ }
+ }
+ fprintf(out, "\n\n\n# noinspection PyPep8Naming\n");
+ fprintf(out, "def %s(", name.c_str());
+ if (!i.second->HasVariableArguments())
+ {
+ size_t argN = 0;
+ for (auto& arg: i.second->GetParameters())
+ {
+ string argName = arg.name;
+ if (g_pythonKeywordReplacements.find(argName) != g_pythonKeywordReplacements.end())
+ argName = g_pythonKeywordReplacements[argName];
+
+ if (argName.empty())
+ argName = "arg" + to_string(argN);
+
+ if (argN > 0)
+ fprintf(out, ", ");
+ fprintf(out, "\n\t\t");
+ fprintf(out, "%s: ", argName.c_str());
+ if (swizzleArgs)
+ OutputSwizzledType(out, arg.type.GetValue());
+ else
+ OutputType(out, arg.type.GetValue());
+ argN ++;
+ }
+ }
+ fprintf(out, "\n\t\t) -> ");
+ if (swizzleArgs)
+ {
+ if (stringResult || pointerResult)
+ fprintf(out, "Optional[");
+ OutputSwizzledType(out, i.second->GetChildType().GetValue());
+ if (stringResult || pointerResult)
+ fprintf(out, "]");
+ }
+ else
+ {
+ OutputType(out, i.second->GetChildType().GetValue());
+ }
+ fprintf(out, ":\n");
+
+ string stringArgFuncCall = funcName + "(";
+ size_t argN = 0;
+ for (auto& arg : i.second->GetParameters())
+ {
+ string argName = arg.name;
+ if (g_pythonKeywordReplacements.find(argName) != g_pythonKeywordReplacements.end())
+ argName = g_pythonKeywordReplacements[argName];
+
+ if (argName.empty())
+ argName = "arg" + to_string(argN);
+
+ if (swizzleArgs && (arg.type->GetClass() == PointerTypeClass) &&
+ (arg.type->GetChildType()->GetClass() == IntegerTypeClass) &&
+ (arg.type->GetChildType()->GetWidth() == 1) &&
+ (arg.type->GetChildType()->IsSigned()))
+ {
+ stringArgFuncCall += string("cstr(") + argName + "), ";
+ }
+ else
+ {
+ stringArgFuncCall += argName + ", ";
+ }
+ argN++;
+ }
+ if (argN > 0)
+ stringArgFuncCall = stringArgFuncCall.substr(0, stringArgFuncCall.size()-2);
+ stringArgFuncCall += ")";
+
+ if (stringResult)
+ {
+ // Emit wrapper to get Python string and free native memory
+ fprintf(out, "\tresult = ");
+ fprintf(out, "%s\n", stringArgFuncCall.c_str());
+ fprintf(out, "\tif not result:\n");
+ fprintf(out, "\t\treturn None\n");
+ fprintf(out, "\tstring = str(pyNativeStr(ctypes.cast(result, ctypes.c_char_p).value))\n");
+ fprintf(out, "\tBNFreeString(result)\n");
+ fprintf(out, "\treturn string\n");
+ }
+ else if (pointerResult)
+ {
+ // Emit wrapper to return None on null pointer
+ fprintf(out, "\tresult = ");
+ fprintf(out, "%s\n", stringArgFuncCall.c_str());
+ fprintf(out, "\tif not result:\n");
+ fprintf(out, "\t\treturn None\n");
+ fprintf(out, "\treturn result\n");
+ }
+ else
+ {
+ fprintf(out, "\treturn ");
+ fprintf(out, "%s\n", stringArgFuncCall.c_str());
+ }
+ fprintf(out, "\n\n");
+ }
+
+ fprintf(out, "\n# Helper functions\n");
+ fprintf(out, "def handle_of_type(value, handle_type):\n");
+ fprintf(out, "\tif isinstance(value, ctypes.POINTER(handle_type)) or isinstance(value, ctypes.c_void_p):\n");
+ fprintf(out, "\t\treturn ctypes.cast(value, ctypes.POINTER(handle_type))\n");
+ fprintf(out, "\traise ValueError('expected pointer to %%s' %% str(handle_type))\n");
+
+ fclose(out);
+ fclose(enums);
+ return 0;
+}
diff --git a/plugins/warp/api/python/warp.py b/plugins/warp/api/python/warp.py
new file mode 100644
index 00000000..e0500215
--- /dev/null
+++ b/plugins/warp/api/python/warp.py
@@ -0,0 +1,384 @@
+import ctypes
+import dataclasses
+import uuid
+from typing import List, Optional, Union
+
+import binaryninja
+from binaryninja import BinaryView, Function, BasicBlock, Architecture, Platform, Type, Symbol, LowLevelILInstruction, LowLevelILFunction
+from binaryninja._binaryninjacore import BNFreeString, BNAllocString, BNType
+
+from . import _warpcore as warpcore
+
+
+class WarpUUID:
+ def __init__(self, _uuid: Union[warpcore.BNWARPUUID, str, uuid.UUID]):
+ if isinstance(_uuid, str):
+ _uuid = uuid.UUID(_uuid)
+ if isinstance(_uuid, uuid.UUID):
+ uuid_bytes = _uuid.bytes
+ _uuid = warpcore.BNWARPUUID()
+ _uuid.uuid = (ctypes.c_ubyte * 16).from_buffer_copy(uuid_bytes)
+ elif isinstance(_uuid, warpcore.BNWARPUUID):
+ # We must create a copy!
+ new_uuid = warpcore.BNWARPUUID()
+ new_uuid.uuid = (ctypes.c_ubyte * 16).from_buffer_copy(_uuid.uuid)
+ _uuid = new_uuid
+ self._uuid = _uuid
+
+ def to_string(self) -> str:
+ return warpcore.BNWARPUUIDGetString(self._uuid)
+
+ def __str__(self):
+ return self.to_string()
+
+ def __repr__(self):
+ return f"<WarpUUID '{str(self)}'>"
+
+ def __hash__(self):
+ # Hash based on the UUID bytes
+ return hash(bytes(self._uuid.uuid))
+
+ def __eq__(self, other):
+ if not isinstance(other, WarpUUID):
+ return False
+ return warpcore.BNWARPUUIDEqual(self._uuid, other._uuid)
+
+ @property
+ def uuid(self):
+ return self._uuid
+
+
+class Source(WarpUUID):
+ def __repr__(self):
+ return f"<Source '{str(self)}'>"
+
+
+class BasicBlockGUID(WarpUUID):
+ def __repr__(self):
+ return f"<BasicBlockGUID '{str(self)}'>"
+
+
+class FunctionGUID(WarpUUID):
+ def __repr__(self):
+ return f"<FunctionGUID '{str(self)}'>"
+
+
+class ConstraintGUID(WarpUUID):
+ def __repr__(self):
+ return f"<ConstraintGUID '{str(self)}'>"
+
+
+class TypeGUID(WarpUUID):
+ def __repr__(self):
+ return f"<TypeGUID '{str(self)}'>"
+
+
+@dataclasses.dataclass
+class WarpFunctionComment:
+ text: str
+ offset: int
+
+ def __str__(self):
+ return repr(self)
+
+ def __repr__(self):
+ return f"<WarpFunctionComment '{self.text}': {self.offset:#x}>"
+
+ @staticmethod
+ def from_api(comment: warpcore.BNWARPFunctionComment) -> 'WarpFunctionComment':
+ return WarpFunctionComment(
+ text=comment.text.decode('utf-8'),
+ offset=comment.offset
+ )
+
+@dataclasses.dataclass
+class WarpConstraint:
+ guid: ConstraintGUID
+ offset: Optional[int]
+
+ def __str__(self):
+ return repr(self)
+
+ def __repr__(self):
+ if self.offset is None:
+ return f"<WarpConstraint '{self.guid}'>"
+ return f"<WarpConstraint '{self.guid}': {self.offset:#x}>"
+
+ @staticmethod
+ def from_api(constraint: warpcore.BNWARPConstraint) -> 'WarpConstraint':
+ if constraint.offset == -1:
+ return WarpConstraint(guid=ConstraintGUID(constraint.guid), offset=None)
+ return WarpConstraint(guid=ConstraintGUID(constraint.guid), offset=constraint.offset)
+
+class WarpTarget:
+ def __init__(self, handle: Union[warpcore.BNWARPTarget, Platform]):
+ if isinstance(handle, Platform):
+ self.handle = warpcore.BNWARPGetTarget(handle.handle)
+ else:
+ self.handle = handle
+
+ def __del__(self):
+ if self.handle is not None:
+ warpcore.BNWARPFreeTargetReference(self.handle)
+
+ @staticmethod
+ def from_platform(platform: Platform) -> Optional['WarpTarget']:
+ handle = warpcore.BNWARPGetTarget(platform.handle)
+ if not handle:
+ return None
+ return WarpTarget(handle)
+
+
+class WarpFunction:
+ def __init__(self, handle: Union[warpcore.BNWARPFunction, Function]):
+ if isinstance(handle, Function):
+ self.handle = warpcore.BNWARPGetFunction(handle.handle)
+ else:
+ self.handle = handle
+ def __del__(self):
+ if self.handle is not None:
+ warpcore.BNWARPFreeFunctionReference(self.handle)
+
+ def __repr__(self):
+ return f"<WarpFunction '{self.name}': '{self.guid}'>"
+
+ @property
+ def guid(self) -> FunctionGUID:
+ return FunctionGUID(warpcore.BNWARPFunctionGetGUID(self.handle))
+
+ @property
+ def name(self) -> str:
+ return warpcore.BNWARPFunctionGetSymbolName(self.handle)
+
+ def get_symbol(self, function: Function) -> Symbol:
+ symbol_handle = warpcore.BNWARPFunctionGetSymbol(self.handle, function.handle)
+ return Symbol(symbol_handle)
+
+ def get_type(self, function: Function) -> Optional[Type]:
+ type_handle = warpcore.BNWARPFunctionGetType(self.handle, function.handle)
+ if not type_handle:
+ return None
+ return Type(type_handle)
+
+ @property
+ def constraints(self) -> List[WarpConstraint]:
+ count = ctypes.c_size_t()
+ constraints = warpcore.BNWARPFunctionGetConstraints(self.handle, count)
+ if not constraints:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(WarpConstraint.from_api(constraints[i]))
+ warpcore.BNWARPFreeConstraintList(constraints, count.value)
+ return result
+
+ @property
+ def comments(self) -> List[WarpFunctionComment]:
+ count = ctypes.c_size_t()
+ comments = warpcore.BNWARPFunctionGetComments(self.handle, count)
+ if not comments:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(WarpFunctionComment.from_api(comments[i]))
+ warpcore.BNWARPFreeFunctionCommentList(comments, count.value)
+ return result
+
+ @staticmethod
+ def get_matched(function: Function) -> Optional['WarpFunction']:
+ handle = warpcore.BNWARPGetMatchedFunction(function.handle)
+ if not handle:
+ return None
+ return WarpFunction(handle)
+
+ def apply(self, function: Function):
+ warpcore.BNWARPFunctionApply(self.handle, function.handle)
+
+
+class _WarpContainerMetaclass(type):
+ def __iter__(self):
+ binaryninja._init_plugins()
+ count = ctypes.c_ulonglong()
+ containers = warpcore.BNWARPGetContainers(count)
+ try:
+ for i in range(0, count.value):
+ yield WarpContainer(warpcore.BNWARPNewContainerReference(containers[i]))
+ finally:
+ warpcore.BNWARPFreeContainerList(containers, count.value)
+
+ def __getitem__(self, value):
+ binaryninja._init_plugins()
+ count = ctypes.c_ulonglong()
+ containers = warpcore.BNWARPGetContainers(count)
+ try:
+ for i in range(0, count.value):
+ container = WarpContainer(warpcore.BNWARPNewContainerReference(containers[i]))
+ if container.name == str(value):
+ return container
+ raise KeyError(f"'{value}' is not a valid container name")
+ finally:
+ warpcore.BNWARPFreeContainerList(containers, count.value)
+
+
+class WarpContainer(metaclass=_WarpContainerMetaclass):
+ def __init__(self, handle: warpcore.BNWARPContainer):
+ self.handle = handle
+
+ def __del__(self):
+ if self.handle is not None:
+ warpcore.BNWARPFreeContainerReference(self.handle)
+
+ def __repr__(self):
+ return f"<WarpContainer '{self.name}'>"
+
+ @staticmethod
+ def all() -> List['WarpContainer']:
+ count = ctypes.c_size_t()
+ containers = warpcore.BNWARPGetContainers(count)
+ if not containers:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(WarpContainer(warpcore.BNWARPNewContainerReference(containers[i])))
+ warpcore.BNWARPFreeContainerList(containers, count.value)
+ return result
+
+ @property
+ def name(self) -> str:
+ return warpcore.BNWARPContainerGetName(self.handle)
+
+ @property
+ def sources(self) -> List[Source]:
+ count = ctypes.c_size_t()
+ sources = warpcore.BNWARPContainerGetSources(self.handle, count)
+ if not sources:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(Source(sources[i]))
+ warpcore.BNWARPFreeUUIDList(sources, count.value)
+ return result
+
+ def add_source(self, source_path: str) -> Optional[Source]:
+ source = warpcore.BNWARPUUID()
+ if not warpcore.BNWARPContainerAddSource(self.handle, source_path, source):
+ return None
+ return Source(source)
+
+ def commit_source(self, source: Source) -> bool:
+ return warpcore.BNWARPContainerCommitSource(self.handle, source.uuid)
+
+ def is_source_uncommitted(self, source: Source) -> bool:
+ return warpcore.BNWARPContainerIsSourceWritable(self.handle, source.uuid)
+
+ def is_source_writable(self, source: Source) -> bool:
+ return warpcore.BNWARPContainerIsSourceWritable(self.handle, source.uuid)
+
+ def get_source_path(self, source: Source) -> Optional[str]:
+ return warpcore.BNWARPContainerGetSourcePath(self.handle, source.uuid)
+
+ def add_functions(self, target: WarpTarget, source: Source, functions: List[Function]) -> bool:
+ count = len(functions)
+ core_funcs = (ctypes.POINTER(warpcore.BNWARPFunction) * count)()
+ for i in range(count):
+ core_funcs[i] = functions[i].handle
+ return warpcore.BNWARPContainerAddFunctions(self.handle, target.handle, source.uuid, core_funcs, count)
+
+ def add_types(self, view: BinaryView, source: Source, types: List[Type]) -> bool:
+ count = len(types)
+ core_types = (ctypes.POINTER(BNType) * count)()
+ for i in range(count):
+ core_types[i] = types[i].handle
+ return warpcore.BNWARPContainerAddTypes(view.handle, self.handle, source.uuid, core_types, count)
+
+ def remove_functions(self, target: WarpTarget, source: Source, functions: List[Function]) -> bool:
+ count = len(functions)
+ core_funcs = (ctypes.POINTER(warpcore.BNWARPFunction) * count)()
+ for i in range(count):
+ core_funcs[i] = functions[i].handle
+ return warpcore.BNWARPContainerRemoveFunctions(self.handle, target.handle, source.uuid, core_funcs, count)
+
+ def remove_types(self, source: Source, guids: List[TypeGUID]) -> bool:
+ count = len(guids)
+ core_guids = (ctypes.POINTER(warpcore.BNWARPTypeGUID) * count)()
+ for i in range(count):
+ core_guids[i] = guids[i].uuid
+ return warpcore.BNWARPContainerRemoveTypes(self.handle, source.uuid, core_guids, count)
+
+ def get_sources_with_function_guid(self, target: WarpTarget, guid: FunctionGUID) -> List[Source]:
+ count = ctypes.c_size_t()
+ sources = warpcore.BNWARPContainerGetSourcesWithFunctionGUID(self.handle, target.handle, guid.uuid, count)
+ if not sources:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(Source(sources[i]))
+ warpcore.BNWARPFreeUUIDList(sources, count.value)
+ return result
+
+ def get_sources_with_type_guid(self, guid: TypeGUID) -> List[Source]:
+ count = ctypes.c_size_t()
+ sources = warpcore.BNWARPContainerGetSourcesWithTypeGUID(self.handle, guid.uuid, count)
+ if not sources:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(Source(sources[i]))
+ warpcore.BNWARPFreeUUIDList(sources, count.value)
+ return result
+
+ def get_functions_with_guid(self, target: WarpTarget, source: Source, guid: FunctionGUID) -> List[Function]:
+ count = ctypes.c_size_t()
+ funcs = warpcore.BNWARPContainerGetFunctionsWithGUID(self.handle, target.handle, source.uuid, guid.uuid, count)
+ if not funcs:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(WarpFunction(warpcore.BNWARPNewFunctionReference(funcs[i])))
+ warpcore.BNWARPFreeFunctionList(funcs, count.value)
+ return result
+
+ def get_type_with_guid(self, arch: Architecture, source: Source, guid: TypeGUID) -> Optional[Type]:
+ ty = warpcore.BNWARPContainerGetTypeWithGUID(self.handle, arch.handle, source.uuid, guid.uuid)
+ if not ty:
+ return None
+ return Type(ty)
+
+ def get_type_guids_with_name(self, source: Source, name: str) -> List[TypeGUID]:
+ count = ctypes.c_size_t()
+ guids = warpcore.BNWARPContainerGetTypeGUIDsWithName(self.handle, source.uuid, name, count)
+ if not guids:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(TypeGUID(guids[i]))
+ warpcore.BNWARPFreeUUIDList(guids, count.value)
+ return result
+
+
+def run_matcher(view: BinaryView):
+ warpcore.BNWARPRunMatcher(view.handle)
+
+def is_instruction_variant(function: LowLevelILFunction, variant: LowLevelILInstruction) -> bool:
+ return warpcore.BNWARPIsLiftedInstructionVariant(function.handle, variant.instr_index)
+
+def is_instruction_blacklisted(function: LowLevelILFunction, variant: LowLevelILInstruction) -> bool:
+ return warpcore.BNWARPIsLiftedInstructionBlacklisted(function.handle, variant.instr_index)
+
+def get_function_guid(function: Function) -> Optional[FunctionGUID]:
+ guid = warpcore.BNWARPUUID()
+ if not warpcore.BNWARPGetAnalysisFunctionGUID(function.handle, guid):
+ return None
+ return FunctionGUID(guid)
+
+
+def get_basic_block_guid(basic_block: BasicBlock) -> Optional[BasicBlockGUID]:
+ # TODO: I believe this won't work for HLIL: https://github.com/Vector35/binaryninja-api/issues/6998
+ if basic_block.is_il:
+ basic_block = basic_block.source_block
+ guid = warpcore.BNWARPUUID()
+ if not warpcore.BNWARPGetBasicBlockGUID(basic_block.handle, guid):
+ return None
+ return BasicBlockGUID(guid)
+
+# TODO: Magic matched_function, possible_functions \ No newline at end of file
diff --git a/plugins/warp/api/python/warp_enums.py b/plugins/warp/api/python/warp_enums.py
new file mode 100644
index 00000000..e47ff1c3
--- /dev/null
+++ b/plugins/warp/api/python/warp_enums.py
@@ -0,0 +1 @@
+import enum