一个分析和操作二进制数据的框架

bal的Python项目详细描述


二进制抽象层(bal)

二进制抽象层(bal)包是一个用于分析和操作的小框架 二进制数据。 其指导原则是树是二进制数据的自然表示。 例如,固件可能如下所示:

    zip数据
      小精灵
      • 标题
      • 代码
      • 数据
    • 图像
    • 配置

它在树上定义了3大类操作:转换分析修改

  • 转换器处理二进制数据的序列化和反序列化。
  • 分析器处理从树表示中提取信息。
  • 修饰符处理二进制文件的任意修改。

安装

可以使用以下命令从pypi安装bal包:

pip install bal

要从存储库安装BAL模块,请克隆repo并运行:

pip install .

要安装BAL软件包并生成其文档的本地副本,请运行:

pip install .[docs]
make html-docs

要安装示例的核心BAL模块和依赖项,请运行:

pip install .[examples]

概念

树中的每个节点都表示为一个dataobjectdataobject可以包装原始二进制数据的非结构化字符串或datamodel(或两者都包装)。 数据模型是定义某种结构化数据的抽象类。 在反序列化原始二进制数据时创建数据模型。 它符合数据模型的典型定义。

此外,bal框架还定义了几个接口:

  • bal.context\u ioc.abstractconverterconverter负责将字节解包到数据模型中 (即反序列化)并将其数据模型打包成字节(即序列化)。其方法 签名是不灵活的,因此可以由dataobject直接调用它们。
  • bal.context\u ioc.abstractmodifier修饰符更新树中任何节点的内容。 它可以修改打包或解包的数据。它包含一个 未定义的签名。它可能会走整棵树,在路上打开包装。
  • bal.context\u ioc.abstractanalyzer分析器从树中提取数据。类型 返回的数据由具体的分析器实现定义。它包含一个 analyze()具有未定义签名的方法。它可能会走整棵树,在路上打开包装。
  • bal.context\u ioc.balioccontextioc上下文提供了 控制反转模式。它抬起头来 给定接口的实现并返回新实例。它用于实例化 一个abstractconverterabstractmodifierabstractanalyzer
    • 对于abstractmodifiers和abstractanalyzers,提供扩展abstractmodifierabstractanalyzer的接口,并返回接口的实现。
    • 对于abstractconverters,将提供扩展datamodel的接口,并返回abstractconverter实现。此实现的pack()方法将创建提供的datamodel接口的实例,其unpack()方法将序列化提供的datamodel接口的实例。
  • bal.context\u ioc.balioccontextfactory创建balioccontext的配置实例。它 为用户提供注册接口实现的方法。
  • bal.context.balcontext为每个树创建一个新上下文。它继承自T他 balioccontext。上下文包含对根数据对象的引用。它可以用作 用于昂贵或经常调用的分析器的缓存。它也可以用来 存储不完全适合树的数据(例如不相关的 节点)
  • bal.context.balcontextfactory正如所暗示的,它负责创建balcontext。这个 工厂是加载将传递到上下文的外部配置的好地方。在 大多数设置,工厂将在应用程序启动时创建,并在应用程序启动时销毁 模具:
  • bal.context.bal managerbal管理器提供了一种使用键查找工厂的方法。它是 不是严格必要的,应该只用于需要动态检索多个不同 上下文工厂

API的完整文档可在 github.io

指南

本指南的所有代码都包含在。/example文件夹中。

第一步是声明一个新的datamodel类,该类定义根的数据结构 节点及其子节点。 例如,一个xilinx比特流有3个子:报头、同步标记和配置包。 报头的格式未知,同步标记没有格式,数据包 是未知数据的数组。

classXilinxPacketsInterface(DataModel):"""    An array of Xilinx register configuration packets.    """classXilinxBitstreamHeaderInterface(DataModel):"""    The Xilinx bitstream header contains unknown information.    """classXilinxBitstreamSyncMarkerInterface(DataModel):"""    The Xilinx bitstream sync marker    """classXilinxBitstream(ClassModel[DataObject]):"""    The root model for a Xilinx bitstream. It contains data objects for a header, sync marker, and packets.    """def__init__(self,header,sync_marker,packets):"""        :param DataObject[XilinxBitstreamHeaderInterface] header:        :param DataObject[XilinxBitstreamSyncMarker] sync_marker:        :param DataObject[XilinxPackets] packets:        """super(XilinxBitstream,self).__init__((("header",self.get_header),("sync_marker",self.get_sync_marker),("packets",self.get_packets),))self.header=headerself.sync_marker=sync_markerself.packets=packetsdefget_header(self):returnself.headerdefget_sync_marker(self):returnself.sync_markerdefget_packets(self):returnself.packets

重要的是要注意,即使孩子的结构是未知的,一个接口 仍然是为他们创造的。正如我们稍后将看到的,它允许外部开发人员稍后定义 它们的格式和转换器。

既然我们有了模型,我们就可以创建根转换器了:

classXilinxBitstreamConverter(AbstractConverter):"""    Converter for a Xilinx FPGA bitstream    :param BALContext context: The BAL context.    """def__init__(self,context):super(XilinxBitstreamConverter,self).__init__(context)self.context=contextdefunpack(self,data_bytes):sync_marker=self.context.format.sync_wordsync_marker_index=data_bytes.find(sync_marker)assertsync_marker_index>=0, \
            "The sync marker is not present in the provided bitstream data"assertsync_marker_index+len(sync_marker)<len(data_bytes)-2, \
            "The configuration data is expected to contain at least one word size worth of data"returnXilinxBitstream(DataObject.create_packed(self.context,data_bytes[:sync_marker_index],XilinxBitstreamHeaderInterface),DataObject.create_packed(self.context,data_bytes[sync_marker_index:sync_marker_index+len(sync_marker)],XilinxBitstreamSyncMarkerInterface,),DataObject.create_packed(self.context,data_bytes[sync_marker_index+len(sync_marker):],XilinxPacketsInterface,))defpack(self,data_model):"""        :param XilinxBitstream data_model:        :rtype: bytes        """assertisinstance(data_model,XilinxBitstream)returnb"".join([data_model.get_header().pack(),self.context.format.sync_word,data_model.get_packets().pack()])

这已经变得有点复杂了。 转换器采用balcontext作为参数,这意味着转换器实例必须 专用于特定比特流。 unpack()方法不实例化其任何子对象datamodel,它只创建 dataobject用于包装该模型的压缩数据。 它为dataobject提供包装数据模型的接口。 dataobject使用接口提取有关打包数据的基本信息(即类型 以及接口名及其docstring中的描述)。 它在解包时也使用接口,为此查找转换器实现 balcontext中的接口(请记住,它继承自balioccontext)。 这是一个重要的属性,因为它允许树"懒洋洋地"解包。 用户可以精确地控制给定的子项何时被解包(如果它被解包的话),这可以 在许多用例中都会带来显著的更好的性能。

最后,我们需要一个balcontextbalfactorycontext实现:

classXilinxContext(BALContext):"""    :param Dict[Type[DataModel],Type[AbstractConverter]] converters_by_type:    :param Dict[Type[AnalyzerInterface],Type[AbstractAnalyzer]] analyzers_by_type:    :param Dict[Type[ModifierInterface],Type[AbstractModifier]] modifiers_by_type:    :param bytes bytes: The bytes making up the bitstream.    """def__init__(self,converters_by_type,analyzers_by_type,modifiers_by_type,bytes):super(XilinxContext,self).__init__(converters_by_type,analyzers_by_type,modifiers_by_type)self._bitstream=DataObject.create_packed(self,bytes,XilinxBitstream)defget_data(self):"""        :rtype: DataObject[XilinxBitstream]        """returnself._bitstreamclassXilinxContextFactory(BALContextFactory):def__init__(self):super(XilinxContextFactory,self).__init__()defcreate(self,data):"""        :param bytes bytes: The bytes for the Xilinx FPGA bitstream        :rtype: XilinxContext        """returnXilinxContext(self._converters_by_type,self._analyzers_by_type,self._modifiers_by_type,data)

因为我们的xilinx实现非常有限,所以上下文和它的工厂都很简单。

让我们看看实际的实现:

importwgetcontext_factory=XilinxContextFactory()# Register the XilinxBitsreamConvertercontext_factory.register_converter(XilinxBitstream,XilinxBitstreamConverter)lx9_bin=wget.download('https://redballoonsecurity.com/files/JwfEU4veQSNFao8h/lx9.bin')withopen(lx9_bin,"rb")asf:data=f.read()context=context_factory.create(data)bitstream_object=context.get_data()print("Bitstream object: {}".format(bitstream_object))print("Bitstream model type: {}".format(bitstream_object.get_model_type()))print("Bitstream model description: {}".format(bitstream_object.get_model_description()))print("\nUNPACKING\n")bitstream_object.unpack()print("Bitstream object: {}".format(bitstream_object))print("\nHEADER\n")header_object=bitstream_object.get_model().get_header()print("Bitstream header object: {}".format(header_object))print("Bitstream header model type: {}".format(header_object.get_model_type()))print("Bitstream header model description: {}".format(header_object.get_model_description()))

此脚本应打印:

Bitstream object: PackedXilinxBitstream(340604)
Bitstream model type: XilinxBitstream
Bitstream model description: The root model for a Xilinx bitstream. It contains a header and packets data objects.

UNPACKING

Bitstream object: XilinxBitstream({
  header: PackedXilinxBitstreamHeaderInterface(16), 
  sync_marker: PackedXilinxBitstreamSyncMarkerInterface(4), 
  packets: PackedXilinxPacketsInterface(340584), 
})

HEADER

Bitstream header object: PackedXilinxBitstreamHeaderInterface(16)
Bitstream header model type: XilinxBitstreamHeaderInterface
Bitstream header model description: The Xilinx bitstream header contains unknown information.

从输出中可以看到,bal框架已经有了关于 比特流的结构。 它使用接口上定义的docstring来获取数据模型的描述,即使 它们还不能打开包装。

这是给这个向导的。 接下来的步骤可能是实现xilinxpacketsinterface,xilinxbitstreamheaderface, 和xilinxbitstreamsyncmarkerinterface接口并实现各自的转换器。 如果你想了解更多关于编写一个完整的转换器、分析器和修饰符链的知识, 转到bal-xilinx项目。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java操作数组上的字符串   java JAXB内容未实例化   图形在Java中如何绘制垂直居中的字符串?   java Apache Ant:使用Junit时出现NoClassDefFoundError   java无法从服务器上运行perl脚本   如何在java中沿树进行预排序遍历,并打印0和1以对应每个节点上的特定字符?   java如何创建。p12文件?   java线程访问无效   java只匹配命名空间中的XML节点,而不知道NS前缀   从java获取2d arraylist元素   数组Java动态集合对象   java Xpath通过通配符或布尔运算查找以相同名称开头的节点?   java注释元素类型   java在中看不到Super()。反编译后的类文件