CodeColorist
Abusing tclsh to Load (Remote) Shellcode on macOS

Abusing tclsh to Load (Remote) Shellcode on macOS

Background

I have collected macOS entitlement databases from OS X Lion (10.7) to macOS Tahoe and now host them on https://codecolor.ist/entdb/.

Here are the results for com.apple.security.cs.allow-unsigned-executable-memory on macOS Tahoe. With this entitlement, it is possible to use classic mprotect to map shellcode.

Python 2 was marked deperecated and finally removed from macOS preinstalled binaries. However in terms of abuse, this tclsh is way more interesting than it. In addiction to unsigned executable memory, it is also granted com.apple.security.cs.disable-library-validation that can load dylib without codesign enforcement.

LOOBins already showed an example to load payload as plugins.

echo "load bad.dylib" | tclsh

Shellcode Loader

On macOS, Tcl comes with Ffidl preinstalled, which is an ffi library. In other words, we can execute arbitrary native calls.

Here is an example of putting 1024 0x41 bytes as shellcode and execute them. Of course the program will crash for unknown instructions.

img

Remote Payload

Tcl on macOS also ships with http and tls packages. Very useful to download resource from remote URL.

Putting all together we can use this genuine system binary to download and execute shellcode without dropping anything on disk, and even chain one more reflective loader on top of it.

Detection

There are already es_event_mprotect_t and es_event_mmap_t events in Endpoint Security API.

PAC?

Unfortunately we cannot use it to sign code pointers (for LPE exploitation). There are few hardcoded bundle names in XNU source code that will not get PAC key enabled.

xnu/bsd/kern/mach_loader.c

Should've wrapped this to another OBTS talk...

References

  1. tclsh
  2. LOOBins
  3. Dylib Loads that Tickle your Fancy