Mach-O Helper Toolset.


As some of you may have already been aware, for the past few weeks I have been working on Libhelper. This is a small library aimed at assisting the handling and parsing of Mach-O files, Image4 files and other things related to iOS Security analysis.

To test the library I had been writing a few tools - two of which I'm releasing today. I've also been working on HTool but that is still a little while off yet.

The tools I'm releasing today as part of the "Mach-O Helper Toolset" are macho-section and macho-split. There is not much to go over with the tools themselves, so I'll give some quick usage information and then discuss the toolset and my plan for it in the future.

Mach-O Section Tool

The aim of macho-section is to quickly carve out a segment/section of a Mach-O file. So, for example, if you would like to rip __TEXT.__const from a Mach-O you can do so like so:

$ macho-section kernel.macho __TEXT __const
-----------------------------------------------------
 macho-section 1.0.0 (macho-helper-100.14.1) - Built Thu Jan  9 00:00:33 2020
-----------------------------------------------------
Attempting to seperate __TEXT.__const from kernel.macho
Wrote file to __TEXT.__const.dat
$

You'll then have the relevant file available, so if you extracted a section with executable code you could pass that to a disassembler.

Mach-O Split Tool

The macho-split tool takes a Universal Binary / FAT file that contains multiple Mach-O's of different architectures and splits them into individual Mach-O files. Here is an example:

$ macho-split some_fat_fil
-----------------------------------------------------
 macho-split 1.0.0 (macho-helper-100.14.1) - Built Thu Jan  9 00:03:15 2020
-----------------------------------------------------
[*] some_fat_file: Mach-O Universal Binary. Found 4 architectures.
    some_fat_file (for architecture x86_64):    Mach-O 64-bit Executable x86_64
    some_fat_file (for architecture arm64_32):    Mach-O 32-bit Executable arm64_32
    some_fat_file (for architecture arm64):     Mach-O 64-bit Executable arm64
    some_fat_file (for architecture arm64e):    Mach-O 64-bit Executable arm64e
[*] macho-split00.x86_64     ...done
[*] macho-split01.arm64_32     ...done
[*] macho-split02.arm64     ...done
[*] macho-split03.arm64e     ...done

You can then handle the Mach-O's how you'd like. The following example demonstrates HTool analysing the segment commands for macho-split-01.arm64

$ htool -l macho-split01.arm64
HTool Version 1.0.0~Alpha; Tue Jan  7 22:39:25 2020; libhelper-1000.836.27.12/BETA_X86_64 x86_64

LC 0: LC_SEGMENT_64    Off: 0x000000000-0x100000000    __PAGEZERO
    No Section 64 data
LC 1: LC_SEGMENT_64    Off: 0x100000000-0x100084000    __TEXT
    Off: 0x100004b30-0x10004ed20    303600 bytes        __TEXT.__text    
    Off: 0x10004ed20-0x10004effc    732 bytes        __TEXT.__stubs    
    Off: 0x10004effc-0x10004f2f0    756 bytes        __TEXT.__stub_helper    
    Off: 0x10004f2f0-0x10004f9c0    1744 bytes        __TEXT.__const    
    Off: 0x10004f9c0-0x100083c6e    213678 bytes        __TEXT.__cstring    
    Off: 0x100083c70-0x100083ff8    904 bytes        __TEXT.__unwind_info    
LC 2: LC_SEGMENT_64    Off: 0x100084000-0x1000d0000    __DATA
    Off: 0x100084000-0x100084020    32 bytes        __DATA.__got    
    Off: 0x100084020-0x100084208    488 bytes        __DATA.__la_symbol_ptr    
    Off: 0x100084208-0x1000842a8    160 bytes        __DATA.__const    
    Off: 0x1000842a8-0x1000c0ebc    248852 bytes        __DATA.__data    
    Off: 0x1000c0ec0-0x1000c9684    34756 bytes        __DATA.__common    
    Off: 0x1000c9688-0x1000ce420    19864 bytes        __DATA.__bss    
LC 3: LC_SEGMENT_64    Off: 0x1000d0000-0x1000d7000    __LINKEDIT
    No Section 64 data
...

Mach-O Helper Toolset

Now to discuss my aims for this "Toolset". As I develop and test libhelper I'll probably write more of these - in fact if you look at the sourcecode you'll see macho-dump which aims at dumping bytes from a start address for a given size. So more of these tools will be added.

Next is the way I'm versioning the toolset. All the tools are built from the same source file, libhelper/tools/macho_toolset.c to be specific, so I decided I needed a way of both keeping track of individual versions of the tools, and that single codebase as a whole. Therefore, there is the toolset version, and the actual tools version. Here's an example:

$ macho-section -v
MachO-Helper macho-section Version 1.0.0 (macho-helper-100.14.1)
  Build Time:        Thu Jan  9 00:00:33 2020
  Default Target:    darwin-x86_64
  Libhelper:        libhelper-1000.836.27.12
  Toolset:        macho-helper-100.14.1

This is the -v version output for macho-section. First we see the version for macho-section as version 1.0.0, beside that the version of the toolset - macho-helper-100.14.1. Underneath is some more detailed information such as the compile time (to further help me keep track of things), the target as this will eventually work on both arm64 and Linux and the version of Libhelper linked against the toolset.

Summary

So, time for the download links! You can grab the tools from the Downloads which will also list historical downloads. Libhelper is not yet available as a pre-compiled library, however feel free to compile it and submit any changes you'd like to see on it's GitHub.

Thanks for checking this out, let me know about any suggestions and/or issue you have on Twitter.