Skip to content

Instantly share code, notes, and snippets.

@janodev
Created July 3, 2024 13:07
Show Gist options
  • Save janodev/474ec593c4aded82dc3081904284cabe to your computer and use it in GitHub Desktop.
Save janodev/474ec593c4aded82dc3081904284cabe to your computer and use it in GitHub Desktop.
Reads a Mach-O header
import Foundation
import MachO.dyld
func readMachOHeader(path: String) {
guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
print("Failed to read file")
return
}
data.withUnsafeBytes { rawBufferPointer in
guard let baseAddress = rawBufferPointer.baseAddress else {
print("Failed to get base address")
return
}
let header = baseAddress.assumingMemoryBound(to: mach_header_64.self).pointee
if header.magic == MH_MAGIC_64 {
printHeader64Info(data: data)
} else {
print("Not a valid 64-bit Mach-O file.")
}
}
}
func printHeader64Info(data: Data) {
data.withUnsafeBytes { (rawBufferPointer: UnsafeRawBufferPointer) in
guard let header = rawBufferPointer.bindMemory(to: mach_header_64.self).baseAddress?.pointee else {
print("Failed to read header")
return
}
print("Mach-O Header Information:")
print("Magic: 0x\(String(format: "%X", header.magic))")
print("CPU Type: \(header.cputype)")
print("CPU Subtype: \(header.cpusubtype)")
print("File Type: \(header.filetype)")
print("Number of Load Commands: \(header.ncmds)")
print("Size of Load Commands: \(header.sizeofcmds)")
print("Flags: 0x\(String(format: "%X", header.flags))")
let headerSize = MemoryLayout<mach_header_64>.size
var offset = headerSize
for _ in 0..<header.ncmds {
let loadCmd = rawBufferPointer.loadUnaligned(fromByteOffset: offset, as: load_command.self)
print("\nLoad Command:")
print(" Type: \(loadCmd.cmd)")
print(" Size: \(loadCmd.cmdsize)")
if loadCmd.cmd == LC_SEGMENT_64 {
let segmentCmd = rawBufferPointer.loadUnaligned(fromByteOffset: offset, as: segment_command_64.self)
let segmentName = withUnsafeBytes(of: segmentCmd.segname) { bytes in
String(bytes: bytes.prefix(while: { $0 != 0 }), encoding: .ascii) ?? ""
}
print(" Segment Name: \(segmentName)")
print(" VM Address: 0x\(String(format: "%llX", segmentCmd.vmaddr))")
print(" VM Size: \(segmentCmd.vmsize)")
print(" File Offset: \(segmentCmd.fileoff)")
print(" File Size: \(segmentCmd.filesize)")
}
offset += Int(loadCmd.cmdsize)
}
}
}
let path = "/Users/jano/Desktop/Hello/UseHello"
readMachOHeader(path: path)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment