diff --git a/src/macho/ChainedStartsInImage.go b/src/macho/ChainedStartsInImage.go index ea026cf..684f601 100644 --- a/src/macho/ChainedStartsInImage.go +++ b/src/macho/ChainedStartsInImage.go @@ -1,9 +1,9 @@ package macho -const ChainedStartsInImageSize = 8 +const ChainedStartsInImageSize = 4 + NumSegments*4 // ChainedStartsInImage describes which segments contain fixups. type ChainedStartsInImage struct { SegCount uint32 - SegInfoOffset [1]uint32 + SegInfoOffset [NumSegments]uint32 } \ No newline at end of file diff --git a/src/macho/MachO.go b/src/macho/MachO.go index c422087..e90a7c1 100644 --- a/src/macho/MachO.go +++ b/src/macho/MachO.go @@ -33,6 +33,7 @@ func Write(writer io.WriteSeeker, build *config.Build, codeBytes []byte, dataByt imports := x.Sections[2] arch, microArch := Arch(build.Arch) imports.Bytes = createLinkeditSegment(build, code) + chainedFixupsSize := ChainedFixupsHeaderSize + ChainedStartsInImageSize + NumSegments*ChainedStartsInSegmentSize m := &MachO{ Header: Header{ @@ -128,13 +129,13 @@ func Write(writer io.WriteSeeker, build *config.Build, codeBytes []byte, dataByt LoadCommand: LcDyldChainedFixups, Length: LinkeditDataCommandSize, DataOffset: uint32(imports.FileOffset), - DataSize: ChainedFixupsHeaderSize + ChainedStartsInImageSize + ChainedStartsInSegmentSize, + DataSize: uint32(chainedFixupsSize), }, CodeSignature: LinkeditDataCommand{ LoadCommand: LcCodeSignature, Length: LinkeditDataCommandSize, - DataOffset: uint32(imports.FileOffset) + 64, - DataSize: uint32(len(imports.Bytes) - 64), + DataOffset: uint32(imports.FileOffset + chainedFixupsSize), + DataSize: uint32(len(imports.Bytes) - chainedFixupsSize), }, Linker: DylinkerCommand{ LoadCommand: LcLoadDylinker, diff --git a/src/macho/createLinkeditSegment.go b/src/macho/createLinkeditSegment.go index 4540457..f730649 100644 --- a/src/macho/createLinkeditSegment.go +++ b/src/macho/createLinkeditSegment.go @@ -47,17 +47,26 @@ func createLinkeditSegment(build *config.Build, code *exe.Section) []byte { }) binary.Write(&buffer, binary.LittleEndian, &ChainedStartsInImage{ - SegCount: 1, - SegInfoOffset: [1]uint32{ChainedStartsInImageSize}, + SegCount: NumSegments, + + // TODO: This is very prone to breaking, make this more robust + SegInfoOffset: [NumSegments]uint32{ + ChainedStartsInImageSize, + ChainedStartsInImageSize + ChainedStartsInSegmentSize, + ChainedStartsInImageSize + ChainedStartsInSegmentSize*2, + ChainedStartsInImageSize + ChainedStartsInSegmentSize*3, + }, }) - binary.Write(&buffer, binary.LittleEndian, &ChainedStartsInSegment{ - Size: ChainedStartsInSegmentSize, - PageSize: uint16(build.MemoryAlign()), - PageCount: 1, - PageStarts: [1]uint16{DYLD_CHAINED_PTR_START_NONE}, - PointerFormat: DYLD_CHAINED_PTR_64, - }) + for range NumSegments { + binary.Write(&buffer, binary.LittleEndian, &ChainedStartsInSegment{ + Size: ChainedStartsInSegmentSize, + PageSize: uint16(build.MemoryAlign()), + PageCount: 1, + PageStarts: [1]uint16{DYLD_CHAINED_PTR_START_NONE}, + PointerFormat: DYLD_CHAINED_PTR_64, + }) + } // Superblob superBlob := bytes.Buffer{}