Skip to content

Instantly share code, notes, and snippets.

@zhuowei
Last active June 14, 2022 02:02
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zhuowei/5711502ec43141839e6e0ff8c0d9c90d to your computer and use it in GitHub Desktop.
Save zhuowei/5711502ec43141839e6e0ff8c0d9c90d to your computer and use it in GitHub Desktop.

For enabling Universal Control on older Macs, there are three ways.

(All of these requires you to enable the feature flag and disable SIP)

(I haven't tried this but it looks like it'd work)

  • use DYLD_INSERT_LIBRARIES:
clang -o liboverride_model.dylib override_model.c -framework IOKit -framework CoreFoundation -shared
sudo launchctl debug gui/$UID/com.apple.ensemble --environment DYLD_INSERT_LIBRARIES="/Users/zhuowei/liboverride_model.dylib"
launchctl stop com.apple.ensemble
launchctl start com.apple.ensemble
  • use lldb:
sudo launchctl debug gui/$UID/com.apple.ensemble --start-suspended
launchctl stop com.apple.ensemble
launchctl start com.apple.ensemble
lldb -n UniversalControl
b PlatformModelIsSupported
c
thread return 1
c
thread return 1
c
#include <IOKit/IOKitLib.h>
#define DYLD_INTERPOSE(_replacement,_replacee) \
__attribute__((used)) static struct{ const void* replacement; const void* replacee; } _interpose_##_replacee \
__attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacement, (const void*)(unsigned long)&_replacee }
CFTypeRef hook_IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options) {
if (CFEqual(key, CFSTR("model"))) {
return CFSTR("MacBookPro17,1");
}
return IORegistryEntryCreateCFProperty(entry, key, allocator, options);
}
DYLD_INTERPOSE(hook_IORegistryEntryCreateCFProperty, IORegistryEntryCreateCFProperty);
@jacklukem
Copy link

jacklukem commented Sep 2, 2021

Hello, great work in finding how to unlock the Universal Control, I tested your method on Monterey beta 6 build 21A5506j and using just that feature flag (codename Ensemble) worked and allowed to detect on Displays prefpane the Advanced tab for Universal Control.

But I'd want to try also your other method on an unsupported Monterey Mac, that is through "liboverride_model.dylib", so both csrutil and amfi disabled, I build that dylib (compiled size 50 KB), insert that dyld library getting this output "Service configured for next launch", then relaunch the process ensemble but opening the Displays prefpane no advanced tab is shown.

Another question, after inserting your dyld library is supposed to show the spoofed supported Universal Control Mac model identifier also on system profiler ?

edit:
even if Displays Advanced tab is not shown seems that Universal Control service is running, moreover your liboverride_model.dylib unlocked also Sidecar prefpane.

@zhuowei
Copy link
Author

zhuowei commented Sep 2, 2021

opening the Displays prefpane no advanced tab is shown.

I didn't override the check for the Display pane with the dylib method (it's an XPC service and I don't know how to inject code into them). You'll have to connect either by moving your mouse to the side or using the Display panel from a supported computer.

The Kext linked in the other gist would probably work for that, although I haven't tested it. Using lldb to attach to the XPC service also works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment