Skip to content

zlib.py

ofrak.core.zlib

ZlibCompressionLevelAnalyzer (Analyzer)

Attempts to determine the compression level (0-9) used when creating zlib-compressed data by analyzing compression parameters and testing decompression with different level hints. Understanding compression level can help with recompression to match original size. Use when analyzing compression characteristics for size optimization, understanding compression trade-offs, or preparing to modify and recompress data while maintaining similar characteristics. Useful for forensics or binary diffing.

analyze(self, resource, config=None) async

Analyze a resource for to extract specific ResourceAttributes.

Users should not call this method directly; rather, they should run Resource.run or Resource.analyze.

Parameters:

Name Type Description Default
resource Resource

The resource that is being analyzed

required
config

Optional config for analyzing. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run.

None

Returns:

Type Description
ZlibData

The analysis results

Source code in ofrak/core/zlib.py
async def analyze(self, resource: Resource, config=None) -> ZlibData:
    zlib_data = await resource.get_data(Range(0, 2))
    flevel = zlib_data[-1]
    if flevel == 0x01:
        compression_level = 1
    elif flevel == 0x5E:
        compression_level = 2
    elif flevel == 0x9C:
        compression_level = 6
    elif flevel == 0xDA:
        compression_level = 7
    else:
        compression_level = 6
    return ZlibData(compression_level)

ZlibData (GenericBinary) dataclass

ZlibData(compression_level: int)

ZlibPacker (Packer)

Compresses data using zlib's DEFLATE algorithm. Use after modifying decompressed zlib data to recreate compressed sections in binaries, PNG files, or any format that uses zlib compression. The packer can target different compression levels for size vs speed tradeoffs.

pack(self, resource, config=None) async

Pack the given resource.

Users should not call this method directly; rather, they should run Resource.run or Resource.pack.

Parameters:

Name Type Description Default
resource Resource required
config

Optional config for packing. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run.

None
Source code in ofrak/core/zlib.py
async def pack(self, resource: Resource, config=None):
    zlib_view = await resource.view_as(ZlibData)
    compression_level = zlib_view.compression_level
    zlib_child = await zlib_view.get_child()
    zlib_data = await zlib_child.resource.get_data()
    zlib_compressed = zlib.compress(zlib_data, compression_level)

    original_zlib_size = await zlib_view.resource.get_data_length()
    resource.queue_patch(Range(0, original_zlib_size), zlib_compressed)

ZlibUnpacker (Unpacker)

Decompresses zlib-compressed data. Use when encountering zlib-compressed data blocks. The decompressed data may contain further structure that can be analyzed or unpacked.

unpack(self, resource, config=None) async

Unpack the given resource.

Users should not call this method directly; rather, they should run Resource.run or Resource.unpack.

Parameters:

Name Type Description Default
resource Resource

The resource that is being unpacked

required
config

Optional config for unpacking. If an implementation provides a default, this default will always be used when config would otherwise be None. Note that a copy of the default config will be passed, so the default config values cannot be modified persistently by a component run.

None
Source code in ofrak/core/zlib.py
async def unpack(self, resource: Resource, config=None):
    zlib_data = await resource.get_data()
    zlib_uncompressed_data = zlib.decompress(zlib_data)
    await resource.create_child(
        tags=(GenericBinary,),
        data=zlib_uncompressed_data,
    )