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.