13#include <mach-o/dyld.h>
14#include <mach/host_info.h>
16#include <mach/mach_host.h>
18#include <sys/sysctl.h>
20#include <sys/ptrace.h>
33int xnu_write(
int pid,
void* addr,
unsigned char*
data,
size_t dsize)
36 assert(addr !=
nullptr);
37 assert(
data !=
nullptr);
39 auto* ptxt = (
unsigned char*)malloc(dsize);
41 assert(ptxt !=
nullptr);
42 memcpy(ptxt,
data, dsize);
45 mach_msg_type_number_t dataCunt = dsize;
47 kern_return_t kret = task_for_pid(mach_task_self(),
pid, &task);
48 if (kret != KERN_SUCCESS) {
49 printf(
"task_for_pid failed: %s. Are you root?", mach_error_string(kret));
53 vm_protect(task, (vm_address_t)addr, (vm_size_t)dsize, 0,
54 VM_PROT_READ | VM_PROT_WRITE | VM_PROT_ALL);
56 kret = vm_write(task, (vm_address_t)addr, (pointer_t)ptxt, dataCunt);
61int xnu_write(
int pid,
void* addr,
unsigned char*
data,
size_t dsize)
63 if ((ptrace(PTRACE_ATTACH,
pid, NULL, NULL)) < 0) {
64 perror(
"ptrace(ATTACH)");
68 int waitRes = waitpid(
pid, &waitStat, WUNTRACED);
69 if (waitRes !=
pid || !WIFSTOPPED(waitStat)) {
71 printf(
"Something went wrong...\n");
75 if ((ptrace(PTRACE_POKEDATA,
pid, addr,
data))) {
79 if ((ptrace(PTRACE_DETACH,
pid, NULL, NULL) < 0)) {
80 perror(
"ptrace(DETACH)");
90int main(
int argc,
char** argv)
96 static struct option long_options[] = {
97 {
"pid", required_argument,
nullptr,
'p'},
98 {
"address", required_argument,
nullptr,
'a'},
99 {
"stacktrace", required_argument,
nullptr,
's'},
100 {
nullptr, 0,
nullptr, 0}};
105 while ((opt = getopt_long(argc, argv,
"p:a:", long_options,
nullptr)) != -1) {
111 addr = (
void*)strtoul(optarg,
nullptr, 16);
114 stacktrace = strtol(optarg,
nullptr, 10);
117 printf(
"Usage: %s -p pid -a address [-s level]\n", argv[0]);
121 xnu_write(
pid, addr, (
unsigned char*)&stacktrace, 4);