Skip to content

Instantly share code, notes, and snippets.

@Quiark

Quiark/sandbox.h

Created Jan 2, 2020
Embed
What would you like to do?
restricted version of sbtool that is compilable
// courtesy of clang
// https://github.com/applesrc/clang/blob/bb8f644/src/projects/compiler-rt/lib/sanitizer_common/sanitizer_mac_spi.cc
enum sandbox_filter_type {
SANDBOX_FILTER_NONE,
SANDBOX_FILTER_PATH,
SANDBOX_FILTER_GLOBAL_NAME,
SANDBOX_FILTER_LOCAL_NAME,
SANDBOX_FILTER_APPLEEVENT_DESTINATION,
SANDBOX_FILTER_RIGHT_NAME,
SANDBOX_FILTER_PREFERENCE_DOMAIN,
SANDBOX_FILTER_KEXT_BUNDLE_ID,
SANDBOX_FILTER_INFO_TYPE,
SANDBOX_FILTER_NOTIFICATION
};
extern const enum sandbox_filter_type SANDBOX_CHECK_NO_REPORT;
extern const enum sandbox_filter_type SANDBOX_CHECK_CANONICAL;
int sandbox_check(pid_t pid, const char *operation, enum sandbox_filter_type type, ...);
// code by Jonathan Levin
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <signal.h> // kill(2)
#include <string.h> // strcmp, etc.
#include "sandbox.h" // Mine
#include <dlfcn.h>
void *g_sblibHandle = NULL;
char* operation_names[] = {
"default",
"appleevent-send",
"authorization-right-obtain",
"device*",
"device-camera",
"device-microphone",
"distributed-notification-post",
"file*",
"file-chroot",
"file-ioctl",
"file-issue-extension",
"file-map-executable",
"file-mknod",
"file-mount",
"file-read*",
"file-read-data",
"file-read-metadata",
"file-read-xattr",
"file-revoke",
"file-search",
"file-unmount",
"file-write*",
"file-write-create",
"file-write-data",
"file-write-flags",
"file-write-mode",
"file-write-owner",
"file-write-setugid",
"file-write-times",
"file-write-unlink",
"file-write-xattr",
"generic-issue-extension",
"qtn-user",
"qtn-download",
"qtn-sandbox",
"hid-control",
"iokit*",
"iokit-issue-extension",
"iokit-open",
"iokit-set-properties",
"iokit-get-properties",
"ipc*",
"ipc-posix*",
"ipc-posix-issue-extension",
"ipc-posix-sem",
"ipc-posix-shm*",
"ipc-posix-shm-read*",
"ipc-posix-shm-read-data",
"ipc-posix-shm-read-metadata",
"ipc-posix-shm-write*",
"ipc-posix-shm-write-create",
"ipc-posix-shm-write-data",
"ipc-posix-shm-write-unlink",
"ipc-sysv*",
"ipc-sysv-msg",
"ipc-sysv-sem",
"ipc-sysv-shm",
"job-creation",
"load-unsigned-code",
"lsopen",
"mach*",
"mach-bootstrap",
"mach-issue-extension",
"mach-lookup",
"mach-per-user-lookup",
"mach-priv*",
"mach-priv-host-port",
"mach-priv-task-port",
"mach-register",
"mach-task-name",
"network*",
"network-inbound",
"network-bind",
"network-outbound",
"user-preference*",
"user-preference-read",
"user-preference-write",
"process*",
"process-exec*",
"process-exec-interpreter",
"process-fork",
"process-info*",
"process-info-listpids",
"process-info-pidinfo",
"process-info-pidfdinfo",
"process-info-pidfileportinfo",
"process-info-setcontrol",
"process-info-dirtycontrol",
"process-info-rusage",
"pseudo-tty",
"signal",
"sysctl*",
"sysctl-read",
"sysctl-write",
"system*",
"system-acct",
"system-audit",
"system-chud",
"system-debug",
"system-fsctl",
"system-info",
"system-kext*",
"system-kext-load",
"system-kext-unload",
"system-lcid",
"system-mac-label",
"system-nfssvc",
"system-privilege",
"system-reboot",
"system-sched",
"system-set-time",
"system-socket",
"system-suspend-resume",
"system-swap",
"system-write-bootstrap",
NULL
};
void usage()
{
fprintf(stderr,"Johnny's Sandbox Utility, v0.1\n");
fprintf(stderr,"Usage: %s _pid_ [what]...\n", getprogname());
fprintf(stderr,"Where: what = all: All operations (not ready yet)\n");
fprintf(stderr," mach: Check all known mach ports\n");
fprintf(stderr," file: Check file access (Requires dir or file argument)\n");
fprintf(stderr," inspect: Call syscall_inspect on this PID\n");
fprintf(stderr," vtrace: Call syscall_vtrace on this PID\n");
fprintf(stderr,"\n");
}
int checkAll (pid_t Pid)
{
int op = 0;
while (operation_names[op])
{
int denied = sandbox_check (Pid, operation_names[op], SANDBOX_CHECK_NO_REPORT, NULL);
printf("%s: %s\n", operation_names[op], denied ? "deny" : "allow");
op++;
}
return 0;
}
int main(int argc, char **argv)
{
// First open libsandbox.1.dylib. Yes, we're linked with it,
// but No, versions change significantly between 3xx and 459+
// If we can't find it, no biggy - the inspect feature will just be disabled.
char *libsb = getenv ("LIBSB");
if (!libsb) libsb = "libsandbox.1.dylib";
g_sblibHandle = dlopen (libsb, RTLD_GLOBAL);
if (argc < 2) { usage(); exit(1);}
// If first argument is a PID, go for sandbox_check
uint32_t pid = 0;
int rc = 0;
char container[1024];
char *path = "/tmp";
rc = sscanf (argv[1], "%d", &pid);
if (rc != 1)
{
fprintf(stderr,"Expecting a PID as the first argument. \"%s\" sure as heck isn't\n",
argv[1]);
usage();
exit(5);
}
char buf[4096];
// Does PID exist? a simple check
rc = kill (pid, 0);
if (rc < 0) { fprintf (stderr, "%d: No such process\n", pid); exit(2);}
// Do a quick check to see if the process is at all sandboxed
if (pid)
{
rc = sandbox_check (pid, NULL, 0);
if (rc == 0) { fprintf(stderr,"Process %d is not sandboxed. All further checks are moot (everything allowed).\n",pid);
if (strcmp(argv[2], "inspect")) exit(0);
}
// If we have a PID, maybe it is contained?
container[0] = '\0';
int len = 0x339;
uint64_t pid64 = pid;
rc = sandbox_container_path_for_pid (pid, container, 1024);
if (rc == 0) {
printf("PID %d Container: %s\n", pid, container);
}
else printf("PID %d is sandboxed, but not containerized\n",pid);
}
// If no more arguments, then we're done.
if (argc == 2) { return 0; };
if (argc == 3) {
if (strcmp(argv[2],"file") == 0)
{
fprintf(stderr,"file: options requires an argument (file or folder to check)\n");
exit(5);
}
#ifdef SB459
if (strncmp(argv[2], "vtrace", strlen(argv[2])) == 0)
{
int rc = sandbox_vtrace_enable();
fprintf(stderr,"RC: %d\n",rc);
char *rep = sandbox_vtrace_report();
fprintf(stderr,"rep: %p\n",rep);
exit(rc);
}
#endif
if (strncmp(argv[2], "inspect", strlen(argv[2])) == 0)
{
//int rc = __sandbox_ms("Sandbox",0x10, &pid2,pid2,buf, 4096);
//printf("RC: %d, Buf: %s\n", rc,buf);
typedef int sbip_func(int, char **buf, int *size);
sbip_func *sandbox_inspect_pid = dlsym(g_sblibHandle, "sandbox_inspect_pid");
if (sandbox_inspect_pid) {
int size = 0;
char *buf = NULL;
rc = sandbox_inspect_pid(pid,&buf,&size);
if (rc == 0) fprintf(stdout,"%s\n", buf);
else
fprintf(stderr,"sandbox_inspect_pid failed (RC: %d)\n", rc);
}
else { fprintf (stderr," Cant find sandbox_inspect_pid in libsandbox.\nLikely iOS version too old or too new (though you can try __sandbox_ms (0x10) directly)\n"); }
}
if (strcmp(argv[2],"mach") == 0)
{
fprintf(stderr,"Checking Mach services for %d....\n",pid);
char **services = NULL; // get_launchd_endpoints(1);
int s = 0;
for (s = 0;
services[s];
s++)
{
int mach_check = sandbox_check (pid,
"mach-lookup",
SANDBOX_FILTER_RIGHT_NAME | SANDBOX_CHECK_NO_REPORT,
services[s]);
printf("%s: %s\n", services[s], mach_check ?"Nope": "Yep");
}
return 0;
}
if (strcmp(argv[2], "all") == 0) { exit(checkAll(pid)); }
path = realpath(argv[2],NULL);
}
// Check if the path exists, otherwise sandbox_check will fail (for the wrong reason)
if (strcmp(argv[2],"file") == 0)
{
path = argv[3];
if (!path) { fprintf(stderr,"Path %s doesn't exist\n", argv[2]); exit(1); }
int read_denied = sandbox_check (pid, "file-read-data", SANDBOX_FILTER_PATH | SANDBOX_CHECK_NO_REPORT, path);
int write_denied = sandbox_check (pid, "file-write-data", SANDBOX_FILTER_PATH | SANDBOX_CHECK_NO_REPORT, path);
// I like verbose messages. And tertiary operators. Even if nested
printf("The sandbox is %s restricting PID %d from reading %s writing to %s\n",
read_denied ? "" :"not",
pid,
write_denied ? (read_denied ? "and" : "but is restricting") :
(read_denied ? "but not restricting" : "or"),
path);
// For those of you wanting to script this, the return value says all
exit ( (read_denied ? 0x10 : 0) + (write_denied ? 0x20 : 0));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.