Source code for binaryninja.kernelcache.kernelcache

import ctypes
import dataclasses
from typing import Optional

import binaryninja
from binaryninja import BinaryView
from binaryninja._binaryninjacore import BNFreeStringList, BNAllocString, BNFreeString

from . import _kernelcachecore as kccore
from .kernelcache_enums import *

[docs] @dataclasses.dataclass class CacheImage: name: str header_virtual_address: int header_file_address: int def __str__(self): return repr(self) def __repr__(self): return f"<CacheImage '{self.name}': 0x{self.header_virtual_address:x} (@0x{self.header_file_address:x})>"
[docs] @dataclasses.dataclass class CacheSymbol: symbol_type: kccore.SymbolTypeEnum address: int name: str def __str__(self): return repr(self) def __repr__(self): return f"<CacheSymbol '{self.name}': 0x{self.address:x}>"
[docs] def image_from_api(image: kccore.BNKernelCacheImage) -> CacheImage: return CacheImage( name=image.name, header_file_address=image.headerFileAddress, header_virtual_address=image.headerVirtualAddress )
[docs] def image_to_api(image: CacheImage) -> kccore.BNKernelCacheImage: return kccore.BNKernelCacheImage( _name=BNAllocString(image.name), headerFileAddress=image.header_file_address, headerVirtualAddress=image.header_virtual_address, )
[docs] def symbol_from_api(symbol: kccore.BNKernelCacheSymbol) -> CacheSymbol: return CacheSymbol( symbol_type=symbol.symbolType, address=symbol.address, name=symbol.name )
[docs] def symbol_to_api(symbol: CacheSymbol) -> kccore.BNKernelCacheSymbol: return kccore.BNKernelCacheSymbol( symbolType=symbol.symbol_type, address=symbol.address, _name=BNAllocString(symbol.name) )
[docs] class KernelCacheController:
[docs] def __init__(self, view: BinaryView): """ Retrieve the shared cache controller for a given view. Call `is_valid` to check if the controller is valid. """ self.handle = kccore.BNGetKernelCacheController(view.handle)
def __del__(self): if self.handle is not None: kccore.BNFreeKernelCacheControllerReference(self.handle) def __str__(self): return repr(self) def __repr__(self): return f"<KernelCacheController: {len(self.images)} images>"
[docs] def is_valid(self) -> bool: return self.handle is not None
[docs] def apply_image(self, view: BinaryView, image: CacheImage) -> bool: api_image: kccore.BNKernelCacheImage = image_to_api(image) result = kccore.BNKernelCacheControllerApplyImage(self.handle, view.handle, api_image) kccore.BNKernelCacheFreeImage(api_image) return result
[docs] def is_image_loaded(self, image: CacheImage) -> bool: api_image: kccore.BNKernelCacheImage = image_to_api(image) result = kccore.BNKernelCacheControllerIsImageLoaded(self.handle, api_image) kccore.BNKernelCacheFreeImage(api_image) return result
[docs] def get_image_at(self, address: int) -> Optional[CacheImage]: api_image = kccore.BNKernelCacheImage() if not kccore.BNKernelCacheControllerGetImageAt(self.handle, address, api_image): return None image = image_from_api(api_image) kccore.BNKernelCacheFreeImage(api_image) return image
[docs] def get_image_containing(self, address: int) -> Optional[CacheImage]: api_image = kccore.BNKernelCacheImage() if not kccore.BNKernelCacheControllerGetImageContaining(self.handle, address, api_image): return None image = image_from_api(api_image) kccore.BNKernelCacheFreeImage(api_image) return image
[docs] def get_image_with_name(self, name: str) -> Optional[CacheImage]: api_image = kccore.BNKernelCacheImage() if not kccore.BNKernelCacheControllerGetImageWithName(self.handle, name, api_image): return None image = image_from_api(api_image) kccore.BNKernelCacheFreeImage(api_image) return image
[docs] def get_image_dependencies(self, image: CacheImage) -> [str]: """ Returns a list of image names that this image depends on. """ count = ctypes.c_ulonglong() api_image: kccore.BNKernelCacheImage = image_to_api(image) value = kccore.BNKernelCacheControllerGetImageDependencies(self.handle, api_image, count) kccore.BNKernelCacheFreeImage(api_image) if value is None: return [] result = [] for i in range(count.value): result.append(value[i].decode("utf-8")) BNFreeStringList(value, count) return result
[docs] def get_symbol_at(self, address: int) -> Optional[CacheSymbol]: api_symbol = kccore.BNKernelCacheSymbol() if not kccore.BNKernelCacheControllerGetSymbolAt(self.handle, address, api_symbol): return None symbol = symbol_from_api(api_symbol) kccore.BNKernelCacheFreeSymbol(api_symbol) return symbol
[docs] def get_symbol_with_name(self, name: str) -> Optional[CacheSymbol]: api_symbol = kccore.BNKernelCacheSymbol() if not kccore.BNKernelCacheControllerGetSymbolWithName(self.handle, name, api_symbol): return None symbol = symbol_from_api(api_symbol) kccore.BNKernelCacheFreeSymbol(api_symbol) return symbol
@property def images(self) -> [CacheImage]: count = ctypes.c_ulonglong() value = kccore.BNKernelCacheControllerGetImages(self.handle, count) if value is None: return [] result = [] for i in range(count.value): result.append(image_from_api(value[i])) kccore.BNKernelCacheFreeImageList(value, count) return result @property def loaded_images(self) -> [CacheImage]: """ Get a list of images that are currently loaded in the view. """ count = ctypes.c_ulonglong() value = kccore.BNKernelCacheControllerGetLoadedImages(self.handle, count) if value is None: return [] result = [] for i in range(count.value): result.append(image_from_api(value[i])) kccore.BNKernelCacheFreeImageList(value, count) return result @property def symbols(self) -> [CacheSymbol]: count = ctypes.c_ulonglong() value = kccore.BNKernelCacheControllerGetSymbols(self.handle, count) if value is None: return [] result = [] for i in range(count.value): result.append(symbol_from_api(value[i])) kccore.BNKernelCacheFreeSymbolList(value, count) return result
def _get_kernel_cache(instance: binaryninja.PythonScriptingInstance): if instance.interpreter.active_view is None: return None controller = KernelCacheController(instance.interpreter.active_view) if not controller.is_valid(): return None return controller binaryninja.PythonScriptingProvider.register_magic_variable( "kc", _get_kernel_cache ) binaryninja.PythonScriptingProvider.register_magic_variable( "kernel_cache", _get_kernel_cache )