HTool is a simple analysis tool originally based on otool, which is shipped with Xcode Developer Tools, and inspired by jtool created by Jonathan Levin. In the long term, I plan for HTool to have a wide range of functionality from analysing Mach-O files, Kernel’s, iBoot and SecureROM, quick disassembly of binaries, working with DYLD Shared Cache’s etc. HTool will also ship with Mash, or Mach-O Shell, which aims at providing an lldb-like interface for analysing the types of binary that I’ve just mentioned, along with disassembly. HTool is designed to primarily run on macOS and iOS, however support for Linux is being actively worked out and will come soon.

There are no dependencies. You will be able to download and run with (hopefully) no issues. HTool heavily relies on Libhelper for it’s Mach-O capabilities, which is Opensource. You can check out Libhelper here. However, unlike Libhelper I have no current plans to Opensource HTool, but please refer to the FAQ for more on this. You can also skip to Downloads if you aren’t interested in the docs.

h3@kirkwood % htool --help
HTool Beta (2) - Built Sat Feb 15 20:45:22 2020

Usage: htool [options] FILE

otool(1) Legacy Options:
   -h:		Dump Mach-O (or DYLD Shared Cache) header
   -f:		Dump FAT header
   -l:		List Load Command/Segments in the binary
   -L:		List shared libraries used

nm(1) Legacy Options:
   -S:		List Symbols
     -sym-dgb	Include Debug Symbols
     -sym-sect	Include Defined Symbols Section

Analysis Options:
   --mash:	Mach-O Shell (Pre-Alpha)
   --hex:	Hexdump
   -k		List Kernel Extensions (KEXTs)
   -K		Extract Kernel Extension by Bundle ID
   -s		Split a SEPOS Firmware image

HTool Information:
   --version	Print HTool Version
   --help	Print HTool Help

Disassembly Options:

Environment Variables:
   H_ARCH		Select an Architecture. x86_64, arm64, arm64e.

I’ll go over each of these options one-by-one and briefly discuss the uses for each.

OTool Legacy Options

I decided to implement a number of otool’s standard features, the majority of which I’ve built on and expanded so now fall under other areas. However, a couple haven’t changed much so that’s what I’ll cover first.

Dump a Mach-O Header

As I have already discussed in my first blog post about Mach-O files, they have formatted headers so one can identify what the file does, how much data it holds and how to load it. Printing this header is easy - run htool with the -h command, followed by a path to a file. In the case of the next few examples, I shall use lldb as the file path which can be identified using the following command: $(which lldb).

HTool `-h` command example.

HTool -h command example.

The output is fairly self-explainatory. One can see the files magic, which should be 0xfeedfacf in the case of a 64-bit file, and 0xfeedface in the case of 32-bit files. Again, as I outlined in my article there are multiple types of Mach-O and this is identified by the Type: Mach Executable line. The CPU type, this being a single-architecture binary (more on that later), is shown as arm64, however this output can also represent sub-architectures such as arm64e or arm64_32. Finally are the number of Load Commands and the size of the region containing them.

Now, there are multi-architecture Mach-O’s. They’re FAT files, or Universal Binary as they’re called by Apple. They have a small header which details each architecture and where it begins. HTool can handle these too and prints them out in a fashion similar to file.

h3@kirkwood % htool -h <some_fat_file>

[*] /Users/h3adsh0tzz/Research/binaries/some_fat_file: Mach-O Universal Binary. Found 4 architectures.
	/Users/h3adsh0tzz/Research/binaries/some_fat_file (for architecture x86_64):		Mach-O 64-bit Executable x86_64
	/Users/h3adsh0tzz/Research/binaries/some_fat_file (for architecture arm64_32):	Mach-O 32-bit Executable arm64_32
	/Users/h3adsh0tzz/Research/binaries/some_fat_file (for architecture arm64):		Mach-O 64-bit Executable arm64
	/Users/h3adsh0tzz/Research/binaries/some_fat_file (for architecture arm64e):		Mach-O 64-bit Executable arm64e

To actually use HTool on one of the listed architectures, see the H_ARCH environment variable.

Dump a FAT Header

Although the -h option will print information about a FAT header, with -f one can get a brief overview of a FAT archive providing a valid file is passed to it.

h3@kirkwood % htool -f <some_fat_file>

[*] /Users/h3adsh0tzz/Research/binaries/some_fat_file: Mach-O Universal Binary. Found 4 architectures.
	x86_64 arm64_32 arm64 arm64

Dump Mach-O Load Commands

Load Commands define a lot about a Mach-O, and especially for iOS Kernel analysis they can be a useful source of information as Apple add and remove a range of segments between major versions. You can print all the commands in a file with the -l option. Each command is labelled from 0 to however many commands there are, this is in the order of which they appear in the raw binary. As much data is put onto a single line as possible, so one can grep through. The way this is formatted is inspired by jtool.

HTool `-l` command example.

HTool -l command example.

Added in v1.0.0 Beta 2, the memory protection of each section is now denoted to the left of each Segment name. For example, a segment with Read-Execute permission is described as r-x/r-x.

A quick example of using grep on HTool output, the following demonstrates using grep to find the __DATA segment from the output. The command grep -5 displays 5 lines before and after the thing you’re looking for is found.

HTool `-l` command example (`grep`).

HTool -l command example (grep).

Please note, not every single command is implemented. If you are working with a file and the data beside the load commands name is blank please report it to me so I can add that command to both HTool and Libhelper.

Another thing you will have most likely noticed is the (placeholder) string next to each section. This is a planned feature that will display a short description of the sections, for example __TEXT.__text will have (Normal) beside it, __TEXT.__cstring will have (C-String Literals) etc. The (placeholder) text was removed in v1.0.0 Beta 2 and will be re-introduced once the described functionality is added.

Dump Mach-O Shared Libraries

The LC_LOAD_DYLIB commands from the -l output can be viewed in more detail with -L, which prints the Shared Libraries. Some extra version information is printed with this command.

HTool `-L` command example.

HTool -L command example.

List Symbols

The symbol listing functionality is similar to that of nm. This is still a bit of a shakey feature as some of it’s functionality is not implemented, or not implemented fully, nevertheless it’s included in this beta.

You can list the symbols of a Mach-O with the -S option along with the path to the file.

HTool `-S` command example.

HTool -S command example.

With HTool v1.0.0 Beta 2, two optional flags have been added for the -S option. The first being -sym-dbg. This will include debugging symbols which are usually omitted from standard htool and nm outputs. These debug symbols are clearly differenciated from regular symbols with the - symbol, and the type of debug symbol to the right of that.

h3@kirkwood % htool -S -sym-dbg src/htool

0000000100004540  T  _find_stab
0000000100005ec0  T  _bh_memmem
00000001000083b0  T  _mash_print_symbol__opt_specify
00000001000083f0  T  _mash_print_symbol__help
0000000100018cb0  -  STSYM   _SplitPath.DOT
0000000100018d88  -  STSYM   _el_complete_func
0000000100018d90  -  STSYM   _rl_filename_completion_function.av
0000000100018d98  -  STSYM   _rl_filename_completion_function.i
0000000100018da0  -  STSYM
0000000100018da8  -  STSYM   _el_list_possib_func
                  -  GSYM   _rl_attempted_completion_over
                  -  GSYM   _rl_attempted_completion_function
                  -  GSYM   _rl_completion_entry_function
                  -  SO   /Users/h3adsh0tzz/Sources/htool/build/../libs/editline/
                  -  SO   sysunix.c
                  -  OSO   /Users/h3adsh0tzz/Sources/htool/build/libs/editline/libeditline.a(sysunix.c.o)
0000000100013560  -  FUN   _rl_ttyset
0000000100013700  -  FUN   _getattr
0000000100013790  -  FUN   _setattr
0000000100013820  -  FUN   _rl_add_slash
0000000100018db0  -  STSYM   _rl_ttyset.old
000000010000cf50  T  _dyld_cache_create
000000010000cfa0  T  _dyld_cache_create_from_file
000000010000d1b0  T  _dyld_cache_free
000000010000d1e0  T  _dyld_cache_header_create

The second flag that has been added is -sym-sect which will include the section of the Mach-O in which a given symbol is defined.

h3@kirkwood % htool -S -sym-sect src/htool

0000000100004540  T  (__TEXT.__text)	_find_stab
0000000100005ec0  T  (__TEXT.__text)	_bh_memmem
00000001000083b0  T  (__TEXT.__text)	_mash_print_symbol__opt_specify
00000001000083f0  T  (__TEXT.__text)	_mash_print_symbol__help
00000001000084a0  T  (__TEXT.__text)	_mash_print_symbol__opt_all
00000001000084d0  T  (__TEXT.__text)	_mash_print_symbol__opt_debug
0000000100008510  T  (__TEXT.__text)	_mash_print_symbol__opt_sect

Please note, these two flags do not work together. If you attempt to use them together it will take only the first one you provide. This will change in the future, but currently is how things work.

Analysis Options


During testing I wrote a hexdump rip-off to check areas of files I had loaded, and ended up implementing it as it’s own operation. It acts the same as the hexdump command.

HTool `--hex` command example.

HTool --hex command example.

List Kernel Extensions

Handling kernel extensions is - so far - the most advanced feature. HTool can handle both styles of iOS Kernel Cache with Split and Merged KEXTs. There are two options currently, listing and extracting. You can list the KEXTs within a kernelcache with -k.

HTool `-k` command example.

HTool -k command example.

Each KEXT is listed with it’s kernel pointer, Bundle ID and version. In the case of the new, Merged-style caches the pointers are untagged because it’s easier that way, but I can change that if enough people request it.

Part of my Kernel cache analysis framework(?) is demonstrated here. The type, version and compile date can be detected, along with the amount of KEXTs contained. I’ll expand this further in the coming weeks.

Extract a Kernel Extension

Once you have a list of the KEXTs, or if you already know which one, use the -K options to extract it. The format for this command should be -K BundleID filename.

HTool `-K BundleID filename` command example.

HTool -K BundleID filename command example.

Also in this example I demonstrate some of the features I’ve already covered for identifying and confirming that the extracted file is indeed a Kernel extension.

Split SEPOS Firmware

Last, but certainly not least, is extracting SEPOS components from a decrypted Image4. This functionality is currently available in Img4Helper, however I felt it was more at-home in HTool. I won’t be removing it from Img4Helper, or at least not anytime soon.

To extract a SEPOS firmware image, use the -s option. Ensure you get the case correct, because -S is nm.

HTool `-s` command example.

HTool -s command example.

Again I expand on this a bit more with some very basic analysis by looking at the header of the SEP kernel and it’s __DATA segment. I’m planning to get analysis for SEP, iBoot and other firmware components like was demonstrated with the Kernel and KEXTs.

Mach-O Shell (Mash)

Mach-O Shell, or Mash, is console for interacting and manipulating Mach-O files. There are a number of features planned for Mash, including an in-depth disassembler and possibly decompiler, however for now, the following features are available.

Please note: Mash is versioned differently to HTool, and may be split into a seperate binary in the future. It is currently in Alpha, so commands are likely to be changed, added or removed. More documentation on how to use Mash will be released once it has entered either the Beta stage, or fully released.

Mash has a number of primary commands, with some of those having “sub-commands”. Most commands have both full, and short-hand types, for example the command print segment all can also be written as p s all. Mash also makes use of Editline, so has tab-completion when working with files.

Mash uses “sessions”, so currently you cannot reload, nor load a new file while in the same session. To begin working on a new file, either quit out of the current session, or open a new command line window. The aim of sessions is to be able to save progress and/or changes to a file while working in Mash.

Forgive the fairly brief overview of commands, the reason for this is that I’m constantly changing how Mash works, so command names and functionality change. With it’s release I will include The following is the current set of Mash Commands that I will discuss:

HTool `--mash` command example.

HTool --mash command example.

Generic commands.

There are a few generic commands to know about first of all. Starting with, help, or h. This will simply print a help menu with a summary of all the primary commands, this includes the full command name, the short name, and a description.

Next is list, or ls. This is simply a wrapper around ls(1) and allows one to use ls for finding files when trying to load a Mach-O into Mash.

The version command gives a version summary for mash in a similar format of HTool’s --version command.

The quit or q command does what it says on the tin - it will quit back to the command line - and load, or l, will load and verify a Mach-O file for that particular session. A file can also be loaded when running the command, like so: htool --mash <file>.

The Print command is used to print particular parts of a load Mach-O file, and is the first of the primary commands for working with Mach-O files that I’m implementing. Firstly, is the Help command, similarly called with either print help or p h. Note: When using the short names, they are interchangable, for example the command print h will work just fine. If you enter a command without it’s option flag, for example print segment, a small help menu will be shown to guide you to entering the correct option.

To start, the Load Commands of a Mach-O can be printed using print commands <opt>, or p lc <opt>, with the <opt> being either the keyword all, or the name of a load command, such as LC_SOURCE_VERSION. The output of this will be similar to the output of htool -l <file> just with Segment Commands removed.

Segment commands can be printed in a similar way using print segment <opt>, or p s <opt>. Again, with <opt> being either all or all segments, or the name of the segment, e.g. __TEXT. And again, the output will be similar to htool -l <file> with the Load Commands removed.

A loaded file’s Symbols can be printed using print symbol <opt> or p sym <opt>. In this case, <opt> has a few more options. With the standard htool -S option, there are flags for printing debug symbols and for including the section each symbol is defined in. With Mash, that same functionality is included. To print all symbols, replace <opt> with all, for debug symbols replace with all-dbg, and for section defines, replace with all-sect. Again, with the -S option, these cannot be used together - yet.

Finally, libraries. This is a very simple command, as there is not options to give it. It will print all linked libraries, like the htool -L command. It can be invoked either with print libs, or p l.

Environment Variables

There is only one environment variable implemented at the moment, that is H_ARCH. There will be more in the future if more are needed.


Not much to discuss here, if you are working with a FAT file just make sure you set this env to the architecture you want to work with, for example (Apologies for the spelling mistake):

HTool `H_ARCH` env example.

HTool H_ARCH env example.


If you read through all of this, thank you. I hope I made sense but if there is anything you’re still unclear about then feel free to ask me. These docs will be updated as I release new versions of HTool.

(Expected) Frequently Asked Questions

  • Opensource?
    – No, not yet at least. I haven’t made my mind up whether I’ll opensource it or not. With Libhelper I felt there was a good use for it being opensource. I may turn some of HTool into a library but that’s not a promise.

  • Does it support 32-bit files?
    – No, again not yet. This, however, is on my list of TODOs because it annoys me too. This is primarily a change that needs to be made to Libhelper, so feel free to contribute and help me out :-).

  • Where is Mash?
    – Mash is still in early development and I’m prototyping things. I’d hope to have a beta released sometime in Feburary.

  • It’s crashed
    – I’m not suprised, it’s early days. Let me know on Twitter and I’ll get it fixed for the next release. Please give as much detail as you can, and test on the latest version if you can - since I may have already fixed it.


I’ll keep historical downloads here in case I break something with a new release.

Version 1.0.0 (Beta 2)

Second Beta release of HTool. Most functionality is still limited, but this version introduces Mach-O Shell (Mash), and improves on a number of other features. Beta 2 currently only supports macOS, however Linux support has not been ditched.

There are currently some issues with the iOS version of HTool, so Beta 2 will be released for macOS only for this beta.

Platform Version Link
macOS htool-v1.0.0-b2 Download Latest

Version 1.0.0 (Beta 1)

Initial release of HTool, currently most functionality is either limited, not included or buggy, but it’s in a fair state for a beta release (at least by Apple’s standards). New functionality will be added with subsequent releases.

Linux support is on the way, but don’t hold your breath for it.

Platform Version Link
macOS htool-v1.0.0-b1 Download Latest
iOS htool-v1.0.0-b1 Download Latest