Skip to content

Instantly share code, notes, and snippets.

@n0kovo
Last active September 8, 2026 00:45
Show Gist options
  • Select an option

  • Save n0kovo/d8a2ff95065bdd48d2967b19b3a26961 to your computer and use it in GitHub Desktop.

Select an option

Save n0kovo/d8a2ff95065bdd48d2967b19b3a26961 to your computer and use it in GitHub Desktop.
Allow debugging binaries on macOS
#!/usr/bin/env zsh
_dbgsign_ents() { # $1 = target, $2 = output plist, uses $ents
print -u2 -- "\nCleaning quarantine and extracting entitlements for: $1"
codesign -d --entitlements - --xml "$1" > "$2"
if [[ ! -s $2 ]] || ! /usr/libexec/PlistBuddy -c Print "$2"; then
print -r -- '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict/></plist>' > "$2"
fi
local e
for e in $ents; do
/usr/libexec/PlistBuddy -c "Add :$e bool true" "$2" \
|| /usr/libexec/PlistBuddy -c "Set :$e true" "$2"
done
}
emulate -L zsh
setopt local_options null_glob
local app=${1:A} id=${2:--} ent rc=0
[[ -e $app ]] || { print -u2 "dbgsign: not found: $1"; return 1 }
print -u2 -- "Stripping extended attributes from $app"
xattr -cr "$app"
find "$app" -name '._*' -type f -delete # AppleDouble stragglers
local -a ents=(
com.apple.security.get-task-allow
com.apple.security.cs.allow-dyld-environment-variables
com.apple.security.cs.disable-library-validation
com.apple.security.cs.allow-unsigned-executable-memory
)
if [[ ! -d $app ]]; then
# plain Mach-O
print -u2 -- "Signing plain Mach-O: $app"
ent=$(mktemp)
_dbgsign_ents "$app" "$ent"
print -u2 -- "codesign (plain Mach-O): $app"
codesign -f -s "$id" --entitlements "$ent" "$app"
rc=$?
rm -f "$ent"
(( rc )) && print -u2 -- "Failed signing $app"
return $rc
fi
# every loose Mach-O anywhere in the tree
local f
for f in "$app"/**/*(.N); do
[[ $(file -b --mime-type "$f") == application/x-mach-binary ]] || continue
codesign -f -s "$id" "$f" || { print -u2 -- "Failed to sign $f"; return 1; }
done
# nested bundles, deepest first
local -a bundles=( "$app"/**/*.(framework|app|xpc|appex|prefpane|mdimporter|component|bundle|kext|lproj|dsym|aplibrary|plugin|xcodeproj|systemextension|playground|qlgenerator)(/N) )
local b v
for b in ${(Oa)bundles}; do
if [[ -d $b/Versions ]]; then
# versioned framework
for v in $b/Versions/*(/N); do
[[ ${v:t} == Current ]] && continue
print -u2 -- " Signing framework version: $v"
codesign -f -s "$id" "$v" || { print -u2 -- "Failed to sign $v"; return 1; }
done
else
ent=$(mktemp)
_dbgsign_ents "$b" "$ent"
codesign -f -s "$id" --entitlements "$ent" "$b" || {
print -u2 -- "Failed to sign $b"
rm -f "$ent"
return 1
}
rm -f "$ent"
fi
done
# outer bundle
print -u2 -- "Signing outer bundle: $app"
ent=$(mktemp)
_dbgsign_ents "$app" "$ent"
codesign -f -s "$id" --entitlements "$ent" "$app"
rc=$?
rm -f "$ent"
(( rc )) && { print -u2 -- "Failed signing outer bundle $app"; return $rc; }
print -u2 -- "Verifying signed bundle: $app"
codesign -vvv --deep --strict "$app"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment