Mach-O support (including Universal Binaries and Apple Code Signatures)

The reason behind this addition is that before undertaking the next big step in the road map of the Profiler there was some spare time to dedicate to some extra features for the upcoming 0.9.6 version. There have also been some customer requests for Mach-O support, so we hope that this will satisfy their request. While there are still some things left which would be useful and nice to add to the Mach-O support, they are not many.

Layout

The first screenshot as you can see features the Mach-O layout.

The logic of Mach-Os starts with their load commands which describe everything else:

Load commands

Segments and sections:

Segments

Entry points (LC_MAIN, LC_UNIXTHREAD):

Entry points

Symbols:

Symbols

Then the LC_DYLD_INFO can describle some VM operations for rebasing and binding:

Rebase

Binding:

Bind

Also the DyldInfo export section is represented as in the file as a tree:

Export

Function starts:

Function starts

Of course, Mach-O support makes little sense without Fat/Universal Binary support:

Fat/Universal Binary

While the upcoming version won’t yet support validation of Apple Code Signatures embedded in Mach-Os, it’s already possible to inspect their format and the embedded certificates.

Apple Code Signature

As usual all the formats added have been exposed to Python as well. I paste some of the SDK class documentation here excluding constants, which are just too many.

class MachObject
    : CFFObject

    AddressToOffset(MaxUInt address) -> MaxUInt
    AddressToSection(MaxUInt address) -> CFFStruct
    AddressToSegment(MaxUInt address) -> CFFStruct
    BuildSymbolsValueHash(CFFStruct symtablc) -> NTHash< MaxUInt,UInt32 >
    CertificateLCs() -> NTUIntVector
    DyLibModules(CFFStruct dysymtablc) -> CFFStruct
    DySymTableLC() -> CFFStruct
    DyTableOfContents(CFFStruct dysymtablc) -> CFFStruct
    DyldDisassembleBind(NTTextStream out, MaxUInt offset, UInt32 size)
    DyldDisassembleBind(NTTextStream out, CFFStruct dyldinfo)
    DyldDisassembleLazyBind(NTTextStream out, CFFStruct dyldinfo)
    DyldDisassembleRebase(NTTextStream out, MaxUInt offset, UInt32 size)
    DyldDisassembleRebase(NTTextStream out, CFFStruct dyldinfo)
    DyldDisassembleWeakBind(NTTextStream out, CFFStruct dyldinfo)
    DyldFindExportedSymbol(CFFStruct dyldinfo, char const * symbol) -> MaxUInt
    DyldInfoLC() -> CFFStruct
    EntryPointAddress(CFFStruct lc) -> MaxUInt
    EntryPointLCs() -> NTUIntVector
    ExternalSymbolReferences(CFFStruct dysymtablc) -> CFFStruct
    FunctionStartsLC() -> CFFStruct
    FunctionStartsOffsetsAndValues(CFFStruct funcstartslc, NTVector< MaxUInt > & values) -> NTUIntVector
    GetLC(LoadCmdInfo info) -> CFFStruct
    GetLC(UInt32 index) -> CFFStruct
    GetLCCount() -> UInt32
    GetLCDescription(CFFStruct s) -> NTString
    GetLCDescription(UInt32 index) -> NTString
    GetLCInfo(UInt32 index) -> LoadCmdInfo
    GetLCInfoFromOffset(MaxUInt offset) -> LoadCmdInfo
    static GetLCName(UInt32 cmd) -> NTString
    IndirectSymbolTable(CFFStruct dysymtablc) -> CFFStruct
    IsMachO64() -> bool
    MachHeader() -> CFFStruct
    OffsetToAddress(MaxUInt offset) -> MaxUInt
    OffsetToSection(MaxUInt offset) -> CFFStruct
    OffsetToSegment(MaxUInt offset) -> CFFStruct
    ProcessLoadCommands() -> bool
    ReadSLEB128(NTBuffer b) -> Int64
    ReadSLEB128(MaxUInt offset, UInt32 & size) -> Int64
    ReadULEB128(NTBuffer b) -> UInt64
    ReadULEB128(MaxUInt offset, UInt32 & size) -> UInt64
    SectionFromOffset(UInt32 cmd, MaxUInt offset) -> CFFStruct
    SegmentSections(CFFStruct seg) -> CFFStruct
    SymTableLC() -> CFFStruct
    SymbolNList(CFFStruct symtablc) -> CFFStruct

class FatObject
    : CFFObject

    Architectures() -> CFFStruct

class AppleCodeSignatureObject
    : CFFObject

    BlobFromOffset(UInt32 offset) -> CFFStruct
    BlobIndexes(CFFStruct supblob) -> CFFStruct
    BlobName(UInt32 magic) -> NTString
    BlobName(CFFStruct blob) -> NTString
    IsSuperBlob(UInt32 magic) -> bool
    IsSuperBlob(CFFStruct blob) -> bool
    TopBlob() -> CFFStruct

Given the SDK capabilities, it’s easy to perform custom scans on Mach-Os or to create plugins.

That’s all. Hope you enjoyed and don’t be shy if you have feature requests or suggestions. 😉