Pocket Poster 3.3.0: worse_query port for iOS 26-27.2
Build IPA / Build unsigned IPA (push) Canceled after 0s
Release IPA / Build and release IPA (push) Canceled after 0s

- Replace bad_query with forcequitOS/worse_query (App Group based)
- Read the App Group from the code signature entitlements
- Add pathleak container enumeration and iOS 27 system container lookup
- Route descriptor/CarPlay writes through worse_query
- Add sign_personal.sh and POCKET_POSTER_SELFTEST diagnostics
- Keep bad_query as an iOS 26 fallback
This commit is contained in:
admin committed 2026-11-10 15:51:27 +08:00
1 parent 2472fdc48b
commit 4c7d968d49
18 files changed
+1026 -355

No files matched your search

+82
View File
@@ -0,0 +1,82 @@
//
// pathleak.m
// worse_query
//
// Created by Taj C on 9/2/26.
//
/*
pathleak - The dumbest arbitrary path enumeration.
Copyright (C) 2026 Taj C (forcequit)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#import <Foundation/Foundation.h>
#include <sys/fsgetpath.h>
#include <sys/mount.h>
// This is just a rewrite of bad_query_list to return an NSString array and run faster
// The way this works is literally just brute-forcing inodes and doing fsgetpath until it gets a matching path, lol.
// Which is still, obviously, dramatically faster than brute-forcing UUIDs.
// It might be possible to derive a sane inode value automagically by just creating a file, doing stat() on it, getting *that* file's inode, then using that for the max_inode count.
NSArray<NSString *> *pathleak(NSString *path, uint64_t max_inode) {
// Sanity checks
if (path.length == 0 || max_inode < 1) return nil;
NSString *dir = path;
while (dir.length > 1 && [dir hasSuffix: @"/"]) { // Trim trailing slash (if present)
dir = [dir substringToIndex: dir.length - 1];
}
// Set everything up
struct statfs sfs;
if (statfs(dir.fileSystemRepresentation, &sfs) != 0) {
// Sandboxed apps may not be allowed to statfs an arbitrary container
// root, but the volume is the same as /private/var.
if (statfs("/private/var", &sfs) != 0 && statfs("/var", &sfs) != 0) return nil;
}
fsid_t fsid = sfs.f_fsid;
char prefix[PATH_MAX];
if (![dir getFileSystemRepresentation: prefix maxLength: sizeof(prefix)]) return nil;
size_t prefix_length = strlen(prefix);
if (prefix_length == 1 && prefix[0] == '/') prefix_length = 0;
NSFileManager *files = [NSFileManager defaultManager];
NSMutableArray<NSString *> *result = [NSMutableArray array];
char buffer[PATH_MAX];
// Brute-force inodes to their corresponding paths
// I'd like to make this multithreaded at some point, but I don't think it'll help.
for (uint64_t inode = 1; inode <= max_inode; inode++) {
ssize_t n = fsgetpath(buffer, sizeof(buffer), &fsid, inode);
if (n <= 0) continue;
// fsgetpath can return /private/var/... while callers pass /var/...
const char *path = buffer;
if (strncmp(path, "/private/var/", 13) == 0 && strncmp(prefix, "/var/", 5) == 0) {
path += 8;
}
if (strncmp(path, prefix, prefix_length) != 0) continue;
if (path[prefix_length] != '/') continue;
if (strchr(path + prefix_length + 1, '/')) continue;
NSString *string = [files stringWithFileSystemRepresentation: path length: strlen(path)];
if (string) [result addObject: string];
}
return result;
}