HookCase 9.0 now supports macOS 15 (Sequoia).
In HookCase 8.0.0 I added code to parse build ids, to deal with breakage caused by unexpected kernel changes in macOS 12.7.1 and 13.6.1. But my implementation was too simple, and ended up passing the wrong version information when run on macOS 13.7. HookCase 8.0.2 fixes this problem, and resolves Issue #49.
macOS 14.4 broke HookCase by making changes to an internal structure
(struct proc
) and to two internal function calls. These are the
kinds of changes that normally only happen in a major
release. HookCase 8.0.1 works around them. This resolves
Issue #48.
HookCase 8.0 now supports macOS 14 (Sonoma).
It also fixes breakage caused by the macOS 13.6.1 and 12.7.1 updates.
HookCase 7.3 now works with the OpenCore Legacy Patcher. This environment is something of a torture test for HookCase. It needed several new sanity checks. But it also needs a much larger kernel stack size. For more information see Using the OpenCore Legacy Patcher
HookCase 7.2.1 has further improvements in watchpoint support. There are now three different kinds, including two that can catch both read and write accesses.
HookCase 7.2 has improved support for watchpoints. Its documentation describes their use and limitations more precisely. The watchpoints example has been expanded.
macOS 13.3 broke HookCase by making changes to an internal structure
(struct proc
) that normally only happen in a major release. HookCase
7.1.3 works around these changes.
As of macOS 12 (Monterey) Apple supports two new kinds of sandboxing -- system call filtering and message filtering. These can interfere with hook library logging and the production of stack traces. So HookCase 7.1.2 disables them for processes that contain a hook library.
macOS Monterey changed how dyld
calls C++ and Objective-C
initializers, such that initializers for the hook library and its
dependents are no longer called automatically. HookCase 6.0 introduced
a workaround -- call the hook library's initializers explicitly. But
doing this doesn't also trigger calls to all of its dependent
frameworks' initializers. HookCase 7.1.2 introduces a different
workaround, which does ensure that all the relevant initializers are
called. This resolves
Issue #44.
HookCase 7.1.2 fixes issues with execv()
and fork()
. This resolves
Issue #45.
As best I can tell system call filtering and message filtering aren't
(yet) documented. But the *.sb
file syntax can be seen in a
WebKit file
Search on "syscall-unix", "syscall-mach" and "apply-message-filter".
macOS 13 (Ventura) made changes to some system dylibs and frameworks that break HookCase's support for setting interpose hooks on methods called from them. I didn't notice this at first, since interpose hooks still worked in some system modules. But the bug was reported at Issue #40, and I've now implemented a workaround in HookCase 7.1.1.
As of macOS 12 (Monterey), HookCase uses a mach-o module's "__got" section to implement interpose hooks. "GOT" stands for "global offset table". It's also called the lazy pointer table. It contains the addresses of functions in other modules. It's used to resolve calls to these functions. Interpose hooks are set by overwriting entries in the lazy pointer table.
As of macOS 13 (Ventura), some modules' "__got" sections have been "optimized" away, and no longer contain usable information. The lazy pointer tables haven't disappeared: They've just been moved to new locations, where they can be shared by more than one module. But they're now only (indirectly) accessible via something called the stubs table. HookCase 7.1.1 knows how to use the stubs table to implement interpose hooks.
HookCase 7.1 now supports a powerful new feature -- the HC_ADDKIDS
enviroment variable. Sometimes you're trying to debug the interaction
between an application and some kind of server or daemon process. The
daemon isn't a child of the application. So it would have been
difficult or impossible to use previous versions of HookCase to load a
hook library into it. But if you can arrange for the daemon to restart
while the application is running, you can use HC_ADDKIDS
to get
HookCase.kext
to count it as one of the application's children, and
load into the daemon the same hook library as was loaded into the
application.
I've rewritten two of HookCase's examples to take advantage of this new feature -- the secinitd subsystem example and the kernel logging example. The previous versions of both examples had stopped working as of macOS 11.
HookCase 7.1 is also significantly better at working with dynamic patch hooks and virtual serial ports (as provided by PySerialPortLogger).
HookCase 7.0 now supports macOS 13 (Ventura).
It also makes some changes to better support PySerialPortLogger. Specifically, it stops hook libraries from triggering sandbox errors when opening virtual serial ports created by this utility.
HookCase 6.0.5 introduces a new way to "catch" logging output from hook libraries: As an option, you can now redirect it to a virtual serial port created by PySerialPortLogger. This helps get around inherent problems logging from a hook library, and Apple's increasing efforts to block even system logging in such an environment. This change resolves Issue #39.
Version 6.0.5 also makes minor changes to the code HookCase.kext
uses to track the parentage of potentially "hookable" processes, to
make it more resilient.
Here's more information on how to use PySerialPortLogger.
macOS 12.5 and macOS 10.15.7 build 19H2026 both broke HookCase. The
Catalina breakage was minor and easily fixed. The Monterey breakage
was larger, and once again resulted from a change of the kind that
normally only happens in major releases. This time none of the
internal kernel structures used by HookCase were altered. But the
interpretation of vm_map_entry.vme_object
did change -- from a
union of simple pointers to one of "packed" pointers.
For more information see Issue #35 and Issue #36.
macOS 12.4 once again broke HookCase, by making changes that normally only happen in major releases. This time none of the breakage was caused by changes to internal kernel structures (though some of those used by HookCase did change). Instead it was caused by two changes in behavior. HookCase 6.0.3 works around them.
For more information see Issue #34.
macOS 12.3 once again broke HookCase, by making changes that normally only happen in major release. These included several changes to internal kernel structures. HookCase 6.0.2 works around these changes.
For more information see Issue #33.
macOS 12.1 broke HookCase, by making lots of changes to internal kernel structures, of the kind that normally only happen in a major release. HookCase 6.0.1 alters its copies of these structures to reflect the changes.
It also fixes incorrect entries in two of the kernel structures used on macOS 12.0.1. This flaw didn't effect the behavior of HookCase 6.0 on macOS 12.0.1: Not realizing the flaw was my own, I added code to HookCase 6.0 to work around it. These workarounds are no longer necessary, and have been removed.
For more information see Issue #31.
HookCase now supports macOS 12 (Monterey).
Note that, on macOS 12, as on macOS 11, HookCase now requires the
keepsyms=1
boot arg. To set this you'll need to turn off SIP at least
temporarily.
sudo nvram boot-args="keepsyms=1"
macOS 11.4 broke HookCase, just like macOS 11.3 did. macOS 11.4 made
further changes to struct thread
, of a kind that normally only takes
place in a new major release. These changes caused a kernel panic
every time you tried to load a hook library into an application. The
problem is fixed by HookCase 5.0.5. struct thread
is one of several
kernel structures that HookCase needs to access directly. For more
information see
Issue #28.
This version of HookCase fixes a bug that caused intermittent instability, though not kernel panics. I fixed it by tweaking the code at the heart of HookCase's watchpoint support. See Issue #26 for more information.
HookCase's watchpoint code is quite complex. So if you see any sort of instability short of kernel panics, especially if it resembles what's reported at Issue #26, you should try disabling watchpoint support.
This release deals with changes in macOS 11.3 that broke HookCase. The
11.3 update changed two kernel structures whose fields HookCase needs
to access directly. Major changes were made to struct task
, and
struct thread
seems to have been completely redesigned. This kind of
change normally only takes place in a new major release, so HookCase
wasn't "expecting" it. HookCase now does separate version checks for
macOS 11 and macOS 11.3. This fixes
Issue #27.
This version of HookCase fixes a bug that caused some interpose hooks
to be skipped on macOS 11 (Big Sur)
(Issue #24).
HookCase uses a structure called the lazy pointer table to implement
interpose hooks. In the past it was always located in the __DATA
segment. But in Big Sur it's sometimes located in the __DATA_CONST
segment. HookCase now looks for it in both places.
This version of HookCase fixes a bug that caused intermittent kernel
panics in set_interpose_hooks_for_module()
(Issue #22).
They seem to have been particularly likely to occur with hook
libraries containing lots of interpose hooks, particularly ones that
are invoked both before and after the CoreFoundation framework is
initialized.
HookCase now supports macOS 11 (Big Sur).
Note that, on macOS 11, HookCase now requires the keepsyms=1
boot
arg. To set this you'll need to turn off SIP at least temporarily.
sudo nvram boot-args="keepsyms=1"
This version of HookCase contains several tweaks to its watchpoint support. Together they merit a bump in the version number. The most significant of them are:
Remove all watchers on process exit
Make watchpoint example work with multiple graphics cards at once
Check if a watchpoint has already been set or unset
This version of HookCase supports watchpoints. You can now set a watchpoint on a location in memory and gather information (including a stack trace) about the code that writes to that location. For more information see config_watcher() in the hook library template, Hooked_watcher_example() in the hook library template and the watchpoints example.
This version of HookCase fixes a bug which caused some patch hooks not
to work properly. If the original function didn't have a standard
prologue, the hook's call to reset_hook()
would fail and the hook
would only be called once. For more information see
Issue #17
My version 4.0.3 patch didn't fix that kernel panic, either (the one
in vn_authorize_open_existing()
). Now I really think I've found the
problem -- one that dates back to the earliest HookCase release. It's
only by chance that it didn't become visible earlier. I've done a week
of hard testing without seeing any more kernel panics. For more
information see
Really really fix kernel panic reported at issue #14
and
Issue #14.
It turns out my version 4.0.2 patch didn't fix one of the kernel panics it was supposed to. This version's patch really does fix it, as best I can tell after several days of testing. See Issue #14.
This version of HookCase fixes two intermittent kernel panics. For more information see Issue #14.
This version of HookCase documents how to use sudo mount -uw /
to
temporarily make system files and directories writable on macOS
Catalina (10.15). It also updates
one of the examples for Catalina.
HookCase now supports macOS Catalina (10.15).
This version of HookCase tightens up the code that supports dynamically adding patch hooks. Among other things, it completely fixes a race condition that effected interactions between a hook library and the HookCase kernel extension, particularly in the get_dynamic_caller() methods. (Previous code just minimized its effect.) For more information see the following commit:
Actual fix for race condition in get_dynamic_caller() and elsewhere
HookCase now supports dynamically adding patch hooks for raw function pointers. This is useful in hooks for methods that use callbacks -- for example CFMachPortCreate() and CFRunLoopObserverCreate(). For more information see dynamic_patch_example() in the hook library template and the dynamic patch hooks example.
Version 3.2.1 fixes some bugs, and restores support for the debug kernel on macOS 10.14. For more information see Issue #11 and the following commit:
Resume resetting iotier_override, and restore support for debug kernel on 10.14
Version 3.2 works around changes in macOS 10.14.5 that broke HookCase. These were part of Apple's workaround for Intel's MDS bug. For more information see Issue #9.
HookCase now supports enabling all parts of "system integrity protection" (SIP) but the protection against loading unsigned kernel extensions.
Though Apple has never documented it, since OS X 10.11 (El Capitan) it's been possible to enable parts of SIP. So, for example, you can use the following command (when booted from the recovery partition) to enable everything but "kernel extension protection":
csrutil enable --without kext
I only became aware of this recently, thanks to the reporter of Issue #7. That bug report also revealed problems using HookCase on macOS 10.14 (Mojave) with this configuration. Version 3.1 fixes these problems.
Note that, for HookCase to work properly on macOS 10.14 with this
configuration, you will need to codesign your hook libraries (using
something like codesign -s "Your Name" hook.dylib
). For this you'll
need to get a Mac Developer codesigning certificate from Apple,
presumably by joining their
Apple Developer Program.
HookCase now supports macOS Mojave (10.14).
But Mojave's Debug kernel is currently very flaky -- lots of panics, with and without HookCase. So support for the Debug kernel has been disabled, at least temporarily.
HookCase now works properly with VMware Fusion running as a host. This
required changing the range of software interrupts used internally by
HookCase (from 0x20-0x23
to 0x30-0x33
). See
Issue #5 for
more information.
To make existing hook libraries fully compatible with version 2.1,
their reset_hook() methods will need to be changed to use int 0x32
instead of int 0x22
, as follows:
void reset_hook(void *hook)
{
__asm__ ("int %0" :: "N" (0x32));
}
-
HookCase now supports macOS High Sierra (10.13).
-
HookCase now supports creating a patch hook for an (un-named) method at a particular address in a given module. This means that HookCase can now hook methods that aren't in their module's symbol table. For more information see Hooked_sub_123abc() in the hook library template.
-
Version 2.0 fixes a bug that prevented interpose hooks from working outside the shared cache of system modules.
-
Version 2.0 fixes a previously undiscovered edge case of an Apple kernel panic bug that was partially fixed in version 1.
-
Version 2.0 fixes a premature-release bug in the "System Events" example's hook library.