From ed97f0f2d932df80396ca98a7cc4921d3dad0823 Mon Sep 17 00:00:00 2001 From: ZomkaDEV Date: Tue, 12 May 2026 00:33:20 +0300 Subject: [PATCH 1/2] Add .DS_Store to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3354bfb..ad5518c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .claude dist/ .grepai/ +.DS_Store From bdc2a0921f0cb1d0b6267e8ca13a45e263345341 Mon Sep 17 00:00:00 2001 From: ZomkaDEV Date: Tue, 12 May 2026 17:42:37 +0300 Subject: [PATCH 2/2] feat: improve support for semi-jailbreaks (nathanlr) --- cmd/ipadecrypt/bootstrap.go | 2 + cmd/ipadecrypt/decrypt.go | 33 ++++- cmd/ipadecrypt/main.go | 2 + helper/entitlements.plist | 11 ++ helper/helper.c | 13 +- internal/device/ipadecrypt-helper-arm64 | Bin 90096 -> 74448 bytes internal/device/ops.go | 184 ++++++++++++++++++++++-- 7 files changed, 232 insertions(+), 13 deletions(-) diff --git a/cmd/ipadecrypt/bootstrap.go b/cmd/ipadecrypt/bootstrap.go index 8c46954..264ff9b 100644 --- a/cmd/ipadecrypt/bootstrap.go +++ b/cmd/ipadecrypt/bootstrap.go @@ -256,6 +256,7 @@ func bootstrapHandler(cmd *cobra.Command, args []string) { tui.Bullet("AppSync Unified bypasses installd's signature check") tui.Bullet(" add repo: https://lukezgd.github.io/repo") tui.Bullet("appinst installs modified IPAs on the device") + tui.Bullet("dpkg installs the trusted helper package on rootless jailbreaks") tui.Bullet("zip packages the decrypted IPA on-device") tui.Info("A reboot may be needed after installing; that's fine, we'll reconnect.") @@ -285,6 +286,7 @@ func bootstrapHandler(cmd *cobra.Command, args []string) { }{ {"AppSync Unified", pdev.LocateAppSync}, {"appinst", pdev.LocateAppinst}, + {"dpkg", func() (string, error) { return pdev.LocateBinary("dpkg") }}, {"zip", func() (string, error) { return pdev.LocateBinary("zip") }}, } for _, c := range checks { diff --git a/cmd/ipadecrypt/decrypt.go b/cmd/ipadecrypt/decrypt.go index 7984a65..6a6ec18 100644 --- a/cmd/ipadecrypt/decrypt.go +++ b/cmd/ipadecrypt/decrypt.go @@ -542,7 +542,7 @@ func runDecryptOnBundle(dev *device.Client, helperPath, bundleID, bundlePath, ve helperStderr = stderrNoter } - _, _, code, err := dev.RunHelper(helperPath, bundleID, bundlePath, outRemote, onEvent, helperStderr) + _, _, code, err := dev.RunHelper(helperPath, bundleID, bundlePath, outRemote, decryptSkipAppex, onEvent, helperStderr) if stderrNoter != nil { stderrNoter.Flush() @@ -617,6 +617,19 @@ func runDecryptOnBundle(dev *device.Client, helperPath, bundleID, bundlePath, ve return } + ignoredEncrypted := 0 + if decryptSkipAppex && len(res.Encrypted) > 0 { + encrypted := res.Encrypted[:0] + for _, n := range res.Encrypted { + if isAppexPath(n) { + ignoredEncrypted++ + continue + } + encrypted = append(encrypted, n) + } + res.Encrypted = encrypted + } + if len(res.Encrypted) > 0 { live.Fail("%d binary(ies) still have cryptid != 0", len(res.Encrypted)) @@ -631,6 +644,9 @@ func runDecryptOnBundle(dev *device.Client, helperPath, bundleID, bundlePath, ve if len(res.Skipped) > 0 { suffix = fmt.Sprintf(" (%d skipped)", len(res.Skipped)) } + if ignoredEncrypted > 0 { + suffix += fmt.Sprintf(" (%d encrypted appex ignored)", ignoredEncrypted) + } live.OK("%d Mach-O(s) verified cryptid=0%s", res.Scanned, suffix) } @@ -670,6 +686,16 @@ func runDecryptOnBundle(dev *device.Client, helperPath, bundleID, bundlePath, ve cleanupDecrypt(dev, decryptNoCleanup, stagingRemote, outRemote) } +func isAppexPath(name string) bool { + for _, part := range strings.Split(name, "/") { + if strings.HasSuffix(part, ".appex") { + return true + } + } + + return false +} + func lookupTargetApp(as *appstore.Client, acc *appstore.Account, target decryptTarget) (appstore.App, error) { if target.appId != "" { return as.LookupByAppID(acc, target.appId) @@ -1106,6 +1132,11 @@ func (p *helperProgress) HandleEvent(ev device.Event) helperUpdate { case "spawn_failed": return helperUpdate{note: fmt.Sprintf("could not spawn %s (skipped)", path.Base(ev.Attr("src")))} + case "appex": + if ev.Attr("phase") == "skipped" { + return helperUpdate{note: "skipped app extensions"} + } + case "dyld": switch ev.Attr("phase") { case "resuming": diff --git a/cmd/ipadecrypt/main.go b/cmd/ipadecrypt/main.go index 617117c..47b4fa0 100644 --- a/cmd/ipadecrypt/main.go +++ b/cmd/ipadecrypt/main.go @@ -25,6 +25,7 @@ var ( decryptUseInstalled bool decryptPatchDevType bool decryptVerbose bool + decryptSkipAppex bool versionsLogResponses bool ) @@ -61,6 +62,7 @@ func main() { decrypt.Flags().BoolVarP(&decryptFromAppStore, "from-appstore", "f", false, "fetch from App Store and reinstall, ignoring what's installed on the device") decrypt.Flags().BoolVar(&decryptUseInstalled, "use-installed", false, "decrypt the installed build directly; skip the App Store path even if a newer version exists") decrypt.Flags().BoolVar(&decryptPatchDevType, "patch-device-type", false, "if the IPA's UIDeviceFamily excludes this device, append the device's family (iPadOS apps then run on iOS)") + decrypt.Flags().BoolVar(&decryptSkipAppex, "skip-appex", false, "skip app extension (.appex) launch/decrypt attempts") decrypt.Flags().BoolVarP(&decryptVerbose, "verbose", "v", false, "stream the on-device helper's LOG/ERR lines to stderr (useful for debugging decryption failures)") versions := &cobra.Command{ diff --git a/helper/entitlements.plist b/helper/entitlements.plist index cc4e5c7..a61c7b0 100644 --- a/helper/entitlements.plist +++ b/helper/entitlements.plist @@ -2,6 +2,9 @@ + get-task-allow + + task_for_pid-allow @@ -9,6 +12,12 @@ com.apple.private.cs.debugger + com.apple.private.thread-set-state + + com.apple.system-task-ports + + com.apple.system-task-ports.control + platform-application + com.apple.private.security.container-required + com.apple.private.security.no-sandbox com.apple.private.security.no-container diff --git a/helper/helper.c b/helper/helper.c index b0747d2..a0fab6e 100644 --- a/helper/helper.c +++ b/helper/helper.c @@ -7,7 +7,7 @@ // hijack. Patches cryptid=0, packs IPA. Walks PlugIns/*.appex + // Extensions/*.appex separately. // -// CLI: ipadecrypt-helper-arm64 [-v] +// CLI: ipadecrypt-helper-arm64 [-v] [--skip-appex] // bundle-id - CFBundleIdentifier; "" skips the main-app pass (appex only). // Used for SpringBoard SBS launch - launchd-lineage spawn that // bypasses Sandbox kext's hook_execve gate on Dopamine. @@ -122,6 +122,7 @@ extern char **environ; // ----- logging --------------------------------------------------------- static int g_verbose = 0; +static int g_skip_appex = 0; #define LOG(...) do { if (g_verbose) fprintf(stderr, __VA_ARGS__); } while (0) #define ERR(fmt, ...) fprintf(stderr, "[helper] ERROR: " fmt "\n", ##__VA_ARGS__) @@ -1975,7 +1976,6 @@ static int decrypt_bundle(const char *bundle_src, const char *bundle_dst, EVT("event=spawn_failed src=\"%s\"", bundle_src); return 0; // non-fatal; continue with rest of the IPA } - // 1) Dump the main exec. Fingerprint runtime arch from the loaded // mach_header so slice selection matches what dyld actually mapped. // FairPlay decrypts on page fault during mach_vm_read_overwrite, @@ -2231,11 +2231,12 @@ int main(int argc, char **argv) { int pi = 1; while (pi < argc && argv[pi][0] == '-') { if (strcmp(argv[pi], "-v") == 0) { g_verbose = 1; pi++; continue; } + if (strcmp(argv[pi], "--skip-appex") == 0) { g_skip_appex = 1; pi++; continue; } break; } if (argc - pi != 3) { fprintf(stderr, - "usage: %s [-v] \n" + "usage: %s [-v] [--skip-appex] \n" " bundle-id CFBundleIdentifier (for SBS), or \"\" to skip main app\n" " bundle-src absolute path to the installed .app on disk\n" " out-ipa where to write the decrypted IPA\n", @@ -2273,7 +2274,11 @@ int main(int argc, char **argv) { if (bundle_id && bundle_id[0]) { decrypt_bundle(bundle_src, bundle_dst, bundle_id); } - decrypt_appexes(bundle_src, bundle_dst); + if (g_skip_appex) { + EVT("event=appex phase=skipped"); + } else { + decrypt_appexes(bundle_src, bundle_dst); + } LOG("[helper] zipping → %s\n", out_ipa); EVT("event=pack phase=start ipa=\"%s\"", out_ipa); diff --git a/internal/device/ipadecrypt-helper-arm64 b/internal/device/ipadecrypt-helper-arm64 index 32f2c017dfd79c2292fbc706f0e8fb78c581b7fa..b5564f9cd026d88ac91afa67d6afdc3309ad3e19 100755 GIT binary patch literal 74448 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 N;ZOf9;(0~5{y&>hjbi`+ literal 90096 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\n") + writeArMember(&deb, "debian-binary", []byte("2.0\n"), 0o644) + writeArMember(&deb, "control.tar.gz", controlTar, 0o644) + writeArMember(&deb, "data.tar.gz", dataTar, 0o644) + + return deb.Bytes(), nil +} + +type tarEntry struct { + body []byte + mode int64 + dir bool +} + +func gzipTar(entries map[string]tarEntry) ([]byte, error) { + var buf bytes.Buffer + gz := gzip.NewWriter(&buf) + tw := tar.NewWriter(gz) + + for name, entry := range entries { + typ := byte(tar.TypeReg) + size := int64(len(entry.body)) + if entry.dir { + typ = tar.TypeDir + size = 0 + } + if err := tw.WriteHeader(&tar.Header{ + Name: name, + Mode: entry.mode, + Size: size, + Typeflag: typ, + ModTime: time.Unix(0, 0), + Uid: 0, + Gid: 0, + Uname: "root", + Gname: "wheel", + }); err != nil { + return nil, err + } + if !entry.dir { + if _, err := tw.Write(entry.body); err != nil { + return nil, err + } + } + } + if err := tw.Close(); err != nil { + return nil, err + } + if err := gz.Close(); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +func writeArMember(w *bytes.Buffer, name string, body []byte, mode int64) { + if len(name) > 15 { + name = name[:15] + } + fmt.Fprintf(w, "%-16s%-12d%-6d%-6d%-8o%-10d`\n", name, 0, 0, 0, mode, len(body)) + w.Write(body) + if len(body)%2 != 0 { + w.WriteByte('\n') + } +} + +func (c *Client) helperInstallRoot() string { + if c.Exists("/var/jb") { + return "/var/jb/usr/local/libexec/ipadecrypt/helpers" + } + + return path.Join(RemoteRoot, "helpers") +} + // HashFile computes the sha256 of a path on-device. Installed bundles under // /var/containers are readable only by root + _installd, hence sudo. Relies // on a `shasum` binary being on PATH (procursus/dopamine/palera1n all ship @@ -294,27 +442,47 @@ func (c *Client) FindInstalled(appDirName string) (string, error) { // should exit 2 with a usage string we can recognize. Catches common issues // (binary not executable, sudo denied, missing codesign). func (c *Client) VerifyHelper(helperPath string) error { - cmd := fmt.Sprintf("%s 2>&1 | head -1", helperPath) + cmd := fmt.Sprintf("sh -c %q", helperPath+" 2>&1") - out, _, _, err := c.RunSudo(cmd) + out, errOut, code, err := c.RunSudo(cmd) if err != nil { return fmt.Errorf("verify helper: %w", err) } if !strings.Contains(out, "usage:") { - return fmt.Errorf("helper didn't respond with usage (got %q)", strings.TrimSpace(out)) + got := strings.TrimSpace(out) + if got == "" { + got = strings.TrimSpace(errOut) + } + if got == "" { + got = fmt.Sprintf("exit %d with no output", code) + } + + return fmt.Errorf("helper didn't respond with usage (got %q)", firstLine(got)) } return nil } +func firstLine(s string) string { + if i := strings.IndexByte(s, '\n'); i >= 0 { + return s[:i] + } + + return s +} + type EventHandler func(Event) // RunHelper spawns the on-device helper for a bundle. bundleID goes to the // SpringBoard SBS SPI (only accepted for the main app; empty string skips // the main-app pass and just decrypts PlugIns/*.appex + Extensions/*.appex). -func (c *Client) RunHelper(helperPath, bundleID, bundlePath, outIPA string, onEvent EventHandler, humanFallback io.Writer) (string, string, int, error) { - cmd := fmt.Sprintf("%s -v %q %q %q", helperPath, bundleID, bundlePath, outIPA) +func (c *Client) RunHelper(helperPath, bundleID, bundlePath, outIPA string, skipAppex bool, onEvent EventHandler, humanFallback io.Writer) (string, string, int, error) { + flags := "-v" + if skipAppex { + flags += " --skip-appex" + } + cmd := fmt.Sprintf("%s %s %q %q %q", helperPath, flags, bundleID, bundlePath, outIPA) // @evt lines on stdout → splitter; LOG/ERR on stderr → humanFallback. splitter := newEventSplitter(onEvent, humanFallback) defer splitter.Close()