BSD Layer
BSD layer cung cấp POSIX APIs, process model, credentials, và file systems. Quan trọng nhất cho post-exploitation: thay đổi credentials để escalate privileges (root, unsandbox).
Process Model
struct proc
struct proc {
pid_t p_pid; // Process ID
struct task *task; // Mach task (1:1)
struct ucred *p_ucred; // Credentials (uid, gid)
struct filedesc *p_fd; // File descriptors
struct pgrp *p_pgrp; // Process group
struct session *p_session; // Session
char p_comm[17]; // Process name
uint32_t p_flag; // Flags (P_TRACED, P_SYSTEM, ...)
int p_csflags; // Code signing flags
// ...
struct proc *p_pptr; // Parent process
struct vnode *p_textvp; // Executable vnode
uint64_t p_uniqueid; // Unique process ID
void *p_sandbox; // Sandbox slot ← target for unsandbox
};
struct ucred (Credentials)
struct ucred {
u_long cr_ref; // Reference count
uid_t cr_uid; // Effective user ID ← target: set to 0 = root
uid_t cr_ruid; // Real user ID
uid_t cr_svuid; // Saved user ID
gid_t cr_gid; // Effective group ID
gid_t cr_rgid; // Real group ID
gid_t cr_svgid; // Saved group ID
short cr_ngroups; // Number of groups
gid_t cr_groups[16]; // Groups
struct label *cr_label; // MAC label (entitlements, sandbox)
// ...
};
Post-Exploitation: Get Root
Với kernel read/write:
1. Tìm current process's proc struct trong kernel memory
- allproc linked list: kernel symbol → iterate
- Hoặc: current_proc() → p_pid match
2. Đọc p_ucred pointer
3. Ghi cr_uid = 0, cr_ruid = 0, cr_svuid = 0
4. Ghi cr_gid = 0
→ Process giờ có UID 0 = root!
Post-Exploitation: Unsandbox
Với kernel read/write:
1. Tìm proc struct
2. Set p_sandbox = NULL (hoặc replace với permissive profile)
→ Process không còn bị sandbox!
Hoặc:
1. Tìm ucred → cr_label
2. Modify MAC label slots cho sandbox
File Descriptors & VFS
File Descriptor Table
struct filedesc {
struct fileproc **fd_ofiles; // Array of file descriptors
int fd_nfiles; // Number of open files
// ...
};
struct fileproc {
struct fileglob *fp_glob; // Global file structure
// ...
};
struct fileglob {
int fg_flag; // Flags (O_RDONLY, O_WRONLY, ...)
file_type_t fg_type; // DTYPE_VNODE, DTYPE_SOCKET, DTYPE_PIPE, ...
void *fg_data; // Type-specific data (vnode, socket, pipe, ...)
struct ucred *fg_cred; // Credentials at open time
off_t fg_offset; // Current offset
// ...
};
Pipe-Based Kernel R/W (Classic Technique)
1. pipe(fds) → create pipe pair
Kernel allocates pipe buffer (struct pipe)
2. Trigger vulnerability → corrupt pipe buffer metadata:
- Modify buffer address → point to kernel address
- Modify buffer size → large enough
3. read(pipe_fd) → kernel reads from corrupted buffer address
→ kernel read primitive!
4. write(pipe_fd) → kernel writes to corrupted buffer address
→ kernel write primitive!
Syscall Interface
Syscall Types
| Type | Entry | Number range | Ví dụ |
|---|---|---|---|
| BSD syscalls | SVC #0x80 |
Positive | read, write, open, fork |
| Mach traps | SVC #0x80 |
Negative | mach_msg, task_for_pid |
| Machine-dependent | Various | Platform-specific | thread_fast_set_cthread_self |
Syscall Table
// bsd/kern/syscalls.master — master syscall definition file
// Format: number type name(args...)
0 AUE_NULL ALL { int nosys(void); } // unused
1 AUE_EXIT ALL { void exit(int rval); }
2 AUE_FORK ALL { int fork(void); }
3 AUE_NULL ALL { user_ssize_t read(int fd, ...) }
4 AUE_NULL ALL { user_ssize_t write(int fd, ...) }
5 AUE_OPEN ALL { int open(const char *path, int flags, int mode) }
// ...
Networking (Brief)
Kernel networking stack là attack surface vì:
- Complex protocol implementations (TCP, UDP, ICMP, Multipath TCP)
- Socket options handling (
setsockopt,getsockopt) necp(Network Extension Control Policy) — newer, less audited
Ví dụ lịch sử:
- Multipath TCP exploit (Keen Lab, iOS 11)
- Socket options heap overflow (various CVEs)
Tài Nguyên
- XNU source:
bsd/kern/kern_proc.c,bsd/kern/kern_credential.c - XNU source:
bsd/kern/syscalls.master(syscall definitions) - Jonathan Levin — macOS and iOS Internals Vol. II (BSD chapters)