Skip to content

llvm-objcopy for MachO does not update ENCRYPTION_INFO load command #168038

@peledins-zimperium

Description

@peledins-zimperium

Objcopy removes gaps from the physical representation between segments.
ENCRYPTION_INFO load command matches physical representation of segment, but does not get updated correspondingly.
End result on manipulated binary:

objdump --headers Runner2
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/objdump: error: 'Runner2': truncated or malformed object (cryptoff field plus cryptsize field of LC_ENCRYPTION_INFO_64 command 14 extends past the end of the file)

repro.yaml:

--- !mach-o
FileHeader:
  magic:           0xFEEDFACF
  cputype:         0x100000C
  cpusubtype:      0x0
  filetype:        0x2
  ncmds:           11
  sizeofcmds:      640
  flags:           0x200085
  reserved:        0x0
LoadCommands:
  - cmd:             LC_ENCRYPTION_INFO_64
    cmdsize:         24
    cryptoff:        16384
    cryptsize:       4145152
    cryptid:         0
    pad:             0
  - cmd:             LC_SEGMENT_64
    cmdsize:         72
    segname:         __PAGEZERO
    vmaddr:          0
    vmsize:          4294967296
    fileoff:         0
    filesize:        0
    maxprot:         0
    initprot:        0
    nsects:          0
    flags:           0
  - cmd:             LC_SEGMENT_64
    cmdsize:         152
    segname:         __TEXT
    vmaddr:          4294967296
    vmsize:          4161536
    fileoff:         0
    filesize:        4161536
    maxprot:         5
    initprot:        5
    nsects:          1
    flags:           0
    Sections:
      - sectname:        __text
        segname:         __TEXT
        addr:            0x100004000
        size:            36
        offset:          0x4000
        align:           2
        reloff:          0x0
        nreloc:          0
        flags:           0x80000400
        reserved1:       0x0
        reserved2:       0x0
        reserved3:       0x0
        content:         FF8300D1F44F00A9FD7B01A905000094FD7B41A9F44F40A9FF830091C0035FD6C0035FD6
  - cmd:             LC_SEGMENT_64
    cmdsize:         152
    segname:         __DATA
    vmaddr:          4299128832
    vmsize:          16384
    fileoff:         0x3F8000
    filesize:        36
    maxprot:         5
    initprot:        5
    nsects:          1
    flags:           0
    Sections:
      - sectname:        __stuf
        segname:         __DATA
        addr:            0x1003F8000
        size:            36
        offset:          0x3F8000
        align:           2
        reloff:          0x0
        nreloc:          0
        flags:           0x00000000
        reserved1:       0x0
        reserved2:       0x0
        reserved3:       0x0
        content:         FF8300D1F44F00A9FD7B01A905000094FD7B41A9F44F40A9FF830091C0035FD6C0035FD6
  - cmd:             LC_SEGMENT_64
    cmdsize:         72
    segname:         __LINKEDIT
    vmaddr:          4295032832
    vmsize:          32768
    fileoff:         4177920
    filesize:        18672
    maxprot:         1
    initprot:        1
    nsects:          0
    flags:           0
  - cmd:             LC_UUID
    cmdsize:         24
    uuid:            2B57DC2F-4029-3EA3-A1B5-B0FC06927842
  - cmd:             LC_BUILD_VERSION
    cmdsize:         32
    platform:        1
    minos:           983040
    sdk:             983552
    ntools:          1
    Tools:
      - tool:            3
        version:         73074435
  - cmd:             LC_SOURCE_VERSION
    cmdsize:         16
    version:         0
  - cmd:             LC_MAIN
    cmdsize:         24
    entryoff:        16188
    stacksize:       0
  - cmd:             LC_LOAD_DYLIB
    cmdsize:         56
    dylib:
      name:            24
      timestamp:       2
      current_version: 87556096
      compatibility_version: 65536
    Content:         '/usr/lib/libSystem.B.dylib'
    ZeroPadBytes:    6
  - cmd:             LC_CODE_SIGNATURE
    cmdsize:         16
    dataoff:         4177920
    datasize:        18672
...

Repro:

yaml2obj repro.yaml -o a.out
llvm-objdump --headers ./a.out
# success
llvm-strip ./a.out -o ./b.out 
llvm-objdump: error: './b.out': truncated or malformed object (cryptoff field plus cryptsize field of LC_ENCRYPTION_INFO_64 command 0 extends past the end of the file)

Reproed with llvm-21.

How should encryption command look like?
It should include whole __TEXT segment physical representation, skipping header page and the __oslogstring section:
https://github.com/apple-oss-distributions/ld64/blob/1a4389663d65d6630e4b3e31ace2a86b6183b452/src/ld/OutputFile.cpp#L4210

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions