Pkg.DotNETBinaryFormatter — API for parsing .NET BinaryFormatter data

Overview

The Pkg.DotNETBinaryFormatter module contains the API for parsing data serialized using System.Runtime.Serialization.Formatters.Binary.BinaryFormatter (MS-NRBF). The parser is based on the dotnet/runtime source code and performs safe, read-only parsing without loading types or instantiating objects from the serialized data.

Inspecting Parsed Records

The following code example demonstrates how to walk the parsed NRBF record tree:

from Pro.Core import *
from Pkg.DotNETBinaryFormatter import *

def inspectBinaryFormatter(fname):
    c = createContainerFromFile(fname)
    if c.isNull():
        return
    obj = DotNETBinaryFormatterObject()
    if not obj.Load(c) or not obj.Initialize():
        return
    root = obj.GetRoot()
    if root is None:
        return
    print("Header:", root.PrimitiveValue)
    for i in range(root.ChildCount):
        child = root.GetChild(i)
        print("  [%d] %s" % (child.Id, child.GetLabel()))

Detecting Embedded Objects

BinaryFormatter payloads often contain byte arrays with embedded files (executables, documents, etc.). The following code example demonstrates how to check for them:

from Pro.Core import *
from Pkg.DotNETBinaryFormatter import *

def findEmbeddedObjects(fname):
    c = createContainerFromFile(fname)
    if c.isNull():
        return
    obj = DotNETBinaryFormatterObject()
    if not obj.Load(c) or not obj.Initialize():
        return
    stream = obj.GetStream()
    for i in range(obj.GetByteArrayNodeCount()):
        node = obj.GetByteArrayNode(i)
        size = int(node.Lengths[0])
        offs = int(node.EndOffset) - size
        rc = stream.clone()
        rc.setRange(offs, size)
        fmts = identifyPossibleFormats(rc)
        if not fmts.isEmpty():
            print("Embedded object at 0x%X (%d bytes)" % (offs, size))

Module API

Pkg.DotNETBinaryFormatter module API.

Classes:

DotNETBinaryFormatterObject()

CFFObject subclass for parsing .NET BinaryFormatter (MS-NRBF) serialized data.

NrbfNode()

A parsed NRBF record node.

class DotNETBinaryFormatterObject

Bases: Pro.Core.CFFObject

CFFObject subclass for parsing .NET BinaryFormatter (MS-NRBF) serialized data.

This class provides safe, read-only parsing of BinaryFormatter payloads without loading types or instantiating objects from the serialized data. The parsing is performed by a C# helper based on the dotnet/runtime source code.

The parsed structure is exposed as a tree of record nodes that can be inspected via GetRoot() and navigated via BuildNodeMap().

Methods:

BuildNodeMap()

Builds a dictionary mapping node IDs to (node, parent_id, child_index) tuples for tree navigation.

GetByteArrayNode(index)

Returns the byte array node at the specified index.

GetByteArrayNodeCount()

Returns the number of byte array records found during parsing.

GetRoot()

Returns the root node of the parsed NRBF record tree.

BuildNodeMap()Dict[int, Tuple]

Builds a dictionary mapping node IDs to (node, parent_id, child_index) tuples for tree navigation.

Returns

A dictionary suitable for tree view callbacks.

Return type

Dict[int, Tuple]

GetByteArrayNode(index: int)Optional[Pkg.DotNETBinaryFormatter.NrbfNode]

Returns the byte array node at the specified index.

Parameters

index (int) – The zero-based index of the byte array node.

Returns

The node for the byte array.

Return type

Optional[NrbfNode]

GetByteArrayNodeCount()int

Returns the number of byte array records found during parsing.

These are ArraySinglePrimitive records with Byte element type. They may contain embedded objects (executables, documents, etc.).

Returns

The number of byte array nodes.

Return type

int

GetRoot()Optional[Pkg.DotNETBinaryFormatter.NrbfNode]

Returns the root node of the parsed NRBF record tree.

The root node represents the SerializationHeader record and its children are the top-level records (assemblies, the root object, etc.).

Returns

The root node, or None if parsing failed.

Return type

Optional[NrbfNode]

class NrbfNode

A parsed NRBF record node. Each node represents a single record in the BinaryFormatter serialized stream and may have children forming a tree structure.

All fields are read-only and may be None depending on the record type.

Attributes:

ArrayElementPrimitiveType

The primitive type of array elements for ArraySinglePrimitive records (record type 15).

ArrayElementTypeName

The type name of array elements for typed array records.

ArrayType

The array type as a BinaryArrayTypeEnum integer value for array records.

AssemId

The assembly ID for Assembly records (record type 12).

AssemblyName

The assembly name for class or assembly records.

ChildCount

The number of child nodes.

ClassName

The class name for class records (record types 1-5).

EndOffset

The end offset of this record in the serialized stream.

Id

Unique node identifier used for tree navigation.

Lengths

The length of each dimension for array records.

LowerBounds

The lower bound of each dimension for array records (non-zero only for offset arrays).

MemberName

The member name this node was assigned to in its parent class, if applicable.

MemberNames

The member names for class records that define a new class.

MemberTypeNames

The member type descriptions for typed class records (record types 4-5).

NullCount

The number of consecutive nulls for ObjectNullMultiple records (record types 13-14).

ObjectId

The object ID assigned to this record in the serialized stream.

Offset

The start offset of this record in the serialized stream.

PrimitiveType

The primitive type as an InternalPrimitiveTypeE integer value for MemberPrimitiveTyped records (record type 8).

PrimitiveValue

The primitive value as a string for MemberPrimitiveTyped records and the SerializationHeader.

Rank

The number of dimensions for array records.

RecordType

The record type as a BinaryHeaderEnum integer value.

ReferenceId

The target object ID for MemberReference records (record type 9).

StringValue

The string value for ObjectString records (record type 6).

Methods:

GetChild(index)

Returns the child node at the specified index.

GetDetails()

Returns a multi-line detail string shown when the node is selected, including record type, offset, class info, member list, or array dimensions as applicable.

GetLabel()

Returns a short display label for tree views (e.g.

ArrayElementPrimitiveType: int

The primitive type of array elements for ArraySinglePrimitive records (record type 15).

ArrayElementTypeName: Optional[str]

The type name of array elements for typed array records.

ArrayType: int

The array type as a BinaryArrayTypeEnum integer value for array records.

AssemId: int

The assembly ID for Assembly records (record type 12).

AssemblyName: Optional[str]

The assembly name for class or assembly records.

ChildCount: int

The number of child nodes.

ClassName: Optional[str]

The class name for class records (record types 1-5).

EndOffset: int

The end offset of this record in the serialized stream.

GetChild(index: int)Pkg.DotNETBinaryFormatter.NrbfNode

Returns the child node at the specified index.

Parameters

index (int) – The zero-based index of the child.

Returns

The child node.

Return type

NrbfNode

GetDetails()str

Returns a multi-line detail string shown when the node is selected, including record type, offset, class info, member list, or array dimensions as applicable.

Returns

The detail text.

Return type

str

GetLabel()str

Returns a short display label for tree views (e.g. "ClassName (Id=2)" or ""Hello" (Id=3)").

Returns

The display label.

Return type

str

Id: int

Unique node identifier used for tree navigation.

Lengths: Optional[List[int]]

The length of each dimension for array records.

LowerBounds: Optional[List[int]]

The lower bound of each dimension for array records (non-zero only for offset arrays).

MemberName: Optional[str]

The member name this node was assigned to in its parent class, if applicable.

MemberNames: Optional[List[str]]

The member names for class records that define a new class.

MemberTypeNames: Optional[List[str]]

The member type descriptions for typed class records (record types 4-5).

NullCount: int

The number of consecutive nulls for ObjectNullMultiple records (record types 13-14).

ObjectId: int

The object ID assigned to this record in the serialized stream.

Offset: int

The start offset of this record in the serialized stream.

PrimitiveType: int

The primitive type as an InternalPrimitiveTypeE integer value for MemberPrimitiveTyped records (record type 8).

Common values: 1 = Boolean, 2 = Byte, 5 = Decimal, 6 = Double, 7 = Int16, 8 = Int32, 9 = Int64, 11 = Single, 14 = UInt16, 15 = UInt32, 16 = UInt64, 13 = DateTime, 18 = String.

PrimitiveValue: Optional[str]

The primitive value as a string for MemberPrimitiveTyped records and the SerializationHeader.

Rank: int

The number of dimensions for array records.

RecordType: int

The record type as a BinaryHeaderEnum integer value.

Common values: 0 = SerializedStreamHeader, 1 = ClassWithId, 2 = ObjectWithMap, 3 = ObjectWithMapAssemId, 4 = ObjectWithMapTyped, 5 = ObjectWithMapTypedAssemId, 6 = ObjectString, 7 = Array, 8 = MemberPrimitiveTyped, 9 = MemberReference, 10 = ObjectNull, 11 = MessageEnd, 12 = Assembly, 13 = ObjectNullMultiple256, 14 = ObjectNullMultiple, 15 = ArraySinglePrimitive, 16 = ArraySingleObject, 17 = ArraySingleString.

ReferenceId: int

The target object ID for MemberReference records (record type 9).

StringValue: Optional[str]

The string value for ObjectString records (record type 6).