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: TODO 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
- Analysis Options
- Mach-O Shell (Mash)
- Environment Variables
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:
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
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
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
-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
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
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.
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
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.
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.
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
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 Symbols: 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 _rl_filename_completion_function.ac 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 Symbols: 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.
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
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
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.
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
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:
There are a few generic commands to know about first of all. Starting with,
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.
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.
version command gives a version summary for mash in a similar format of HTool’s
q command does what it says on the tin - it will quit back to the command line - and
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
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
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):
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
– 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.
– 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.
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.