Created
December 23, 2019 00:54
-
-
Save steeve/7887175a9895e1fd849dd1c9267ab7d8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"debug/macho" | |
"encoding/binary" | |
"fmt" | |
"io" | |
"os" | |
) | |
const ( | |
LoadCmdCodeSignature macho.LoadCmd = 0x1d | |
) | |
const ( | |
CSMAGIC_REQUIREMENT = 0xfade0c00 /* single Requirement blob */ | |
CSMAGIC_REQUIREMENTS = 0xfade0c01 /* Requirements vector (internal requirements) */ | |
CSMAGIC_CODEDIRECTORY = 0xfade0c02 /* CodeDirectory blob */ | |
CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0 /* embedded form of signature data */ | |
CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1 /* multi-arch collection of embedded signatures */ | |
CSSLOT_CODEDIRECTORY = 0 /* slot index for CodeDirectory */ | |
) | |
type CodeSignatureCmd struct { | |
Cmd macho.LoadCmd | |
Len uint32 | |
Offset uint32 | |
Size uint32 | |
} | |
type CodeSignature struct { | |
Magic uint32 | |
Length uint32 | |
Count uint32 | |
} | |
type CodeSignatureBlobIndex struct { | |
Type uint32 | |
Offset uint32 | |
} | |
type CodeSignatureBlobBase struct { | |
Magic uint32 | |
Length uint32 | |
} | |
type CodeDirectory struct { | |
Magic uint32 /* magic number (CSMAGIC_CODEDIRECTORY) */ | |
Length uint32 /* total length of CodeDirectory blob */ | |
Version uint32 /* compatibility version */ | |
Flags uint32 /* setup and mode flags */ | |
HashOffset uint32 /* offset of hash slot element at index zero */ | |
IdentOffset uint32 /* offset of identifier string */ | |
NSpecialSlots uint32 /* number of special hash slots */ | |
NCodeSlots uint32 /* number of ordinary (code) hash slots */ | |
CodeLimit uint32 /* limit to main image signature range */ | |
HashSize uint8 /* size of each hash in bytes */ | |
HashType uint8 /* type of hash (cdHashType* constants) */ | |
Spare1 uint8 /* unused (must be zero) */ | |
PageSize uint8 /* log2(page size in bytes); 0 => infinite */ | |
Spare2 uint32 /* unused (must be zero) */ | |
/* followed by dynamic content as located by offset fields above */ | |
} | |
type MachoFileEx struct { | |
*macho.File | |
io.ReaderAt | |
codeSigData []byte | |
} | |
func (f *MachoFileEx) CodeSignatureBytes() []byte { | |
if f.codeSigData != nil { | |
return f.codeSigData | |
} | |
for _, load := range f.Loads { | |
data := load.Raw() | |
cmd := macho.LoadCmd(f.ByteOrder.Uint32(data[0:4])) | |
switch cmd { | |
case LoadCmdCodeSignature: | |
buf := bytes.NewBuffer(data) | |
csCmd := &CodeSignatureCmd{} | |
binary.Read(buf, f.ByteOrder, csCmd) | |
f.codeSigData = make([]byte, int(csCmd.Size)) | |
f.ReadAt(f.codeSigData, int64(csCmd.Offset)) | |
} | |
} | |
return f.codeSigData | |
} | |
func (f *MachoFileEx) CodeSignature() { | |
buf := bytes.NewBuffer(f.CodeSignatureBytes()) | |
cs := &CodeSignature{} | |
binary.Read(buf, binary.BigEndian, cs) | |
if cs.Magic != CSMAGIC_EMBEDDED_SIGNATURE { | |
panic("wrong CSMAGIC_EMBEDDED_SIGNATURE") | |
} | |
for i := 0; i < int(cs.Count); i++ { | |
blobIdx := &CodeSignatureBlobIndex{} | |
binary.Read(buf, binary.BigEndian, blobIdx) | |
data := f.CodeSignatureBytes() | |
magic := binary.BigEndian.Uint32(data[blobIdx.Offset : blobIdx.Offset+4]) | |
blobLen := binary.BigEndian.Uint32(data[blobIdx.Offset+4 : blobIdx.Offset+8]) | |
blobData := data[blobIdx.Offset : blobIdx.Offset+blobLen] | |
blobBuf := bytes.NewBuffer(blobData) | |
_ = blobBuf | |
switch magic { | |
case CSMAGIC_CODEDIRECTORY: | |
dir := &CodeDirectory{} | |
binary.Read(blobBuf, binary.BigEndian, dir) | |
ident := CString(blobData[dir.IdentOffset:]) | |
fmt.Println("Ident:", ident) | |
} | |
} | |
} | |
func CString(buf []byte) string { | |
idx := bytes.IndexByte(buf, 0) | |
return string(buf[:idx-1]) | |
} | |
func main() { | |
f, err := os.Open(os.Args[1]) | |
if err != nil { | |
panic(err) | |
} | |
defer f.Close() | |
machoFile, err := macho.NewFile(f) | |
if err != nil { | |
panic(err) | |
} | |
f2 := MachoFileEx{ | |
File: machoFile, | |
ReaderAt: f, | |
} | |
f2.CodeSignature() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment