1*a325d9c4SApple OSS Distributions #include <TargetConditionals.h>
2*a325d9c4SApple OSS Distributions #include <errno.h>
3*a325d9c4SApple OSS Distributions #include <stdio.h>
4*a325d9c4SApple OSS Distributions #include <stdlib.h>
5*a325d9c4SApple OSS Distributions #include <string.h>
6*a325d9c4SApple OSS Distributions #include <unistd.h>
7*a325d9c4SApple OSS Distributions
8*a325d9c4SApple OSS Distributions #if __has_include(<ptrauth.h>)
9*a325d9c4SApple OSS Distributions #include <ptrauth.h>
10*a325d9c4SApple OSS Distributions #endif
11*a325d9c4SApple OSS Distributions
12*a325d9c4SApple OSS Distributions #include <sys/mman.h>
13*a325d9c4SApple OSS Distributions #include <sys/syslimits.h>
14*a325d9c4SApple OSS Distributions
15*a325d9c4SApple OSS Distributions char *cmdname;
16*a325d9c4SApple OSS Distributions
17*a325d9c4SApple OSS Distributions int
main(int argc,char * argv[])18*a325d9c4SApple OSS Distributions main(
19*a325d9c4SApple OSS Distributions int argc,
20*a325d9c4SApple OSS Distributions char *argv[])
21*a325d9c4SApple OSS Distributions {
22*a325d9c4SApple OSS Distributions uint32_t page_size;
23*a325d9c4SApple OSS Distributions void *page;
24*a325d9c4SApple OSS Distributions int ch;
25*a325d9c4SApple OSS Distributions int opt_interactive;
26*a325d9c4SApple OSS Distributions
27*a325d9c4SApple OSS Distributions cmdname = argv[0];
28*a325d9c4SApple OSS Distributions
29*a325d9c4SApple OSS Distributions opt_interactive = 0;
30*a325d9c4SApple OSS Distributions while ((ch = getopt(argc, argv, "i")) != -1) {
31*a325d9c4SApple OSS Distributions switch (ch) {
32*a325d9c4SApple OSS Distributions case 'i':
33*a325d9c4SApple OSS Distributions opt_interactive = 1;
34*a325d9c4SApple OSS Distributions break;
35*a325d9c4SApple OSS Distributions case '?':
36*a325d9c4SApple OSS Distributions default:
37*a325d9c4SApple OSS Distributions fprintf(stdout,
38*a325d9c4SApple OSS Distributions "Usage: %s [-i]\n"
39*a325d9c4SApple OSS Distributions "\t-i: interactive\n",
40*a325d9c4SApple OSS Distributions cmdname);
41*a325d9c4SApple OSS Distributions exit(1);
42*a325d9c4SApple OSS Distributions }
43*a325d9c4SApple OSS Distributions }
44*a325d9c4SApple OSS Distributions
45*a325d9c4SApple OSS Distributions page_size = getpagesize();
46*a325d9c4SApple OSS Distributions page = mmap(NULL, page_size, PROT_READ | PROT_EXEC, MAP_ANON | MAP_SHARED, -1, 0);
47*a325d9c4SApple OSS Distributions if (!page) {
48*a325d9c4SApple OSS Distributions fprintf(stderr, "%s:%d mmap() error %d (%s)\n",
49*a325d9c4SApple OSS Distributions cmdname, __LINE__,
50*a325d9c4SApple OSS Distributions errno, strerror(errno));
51*a325d9c4SApple OSS Distributions exit(1);
52*a325d9c4SApple OSS Distributions }
53*a325d9c4SApple OSS Distributions if (opt_interactive) {
54*a325d9c4SApple OSS Distributions fprintf(stdout, "allocated page at %p\n",
55*a325d9c4SApple OSS Distributions page);
56*a325d9c4SApple OSS Distributions }
57*a325d9c4SApple OSS Distributions
58*a325d9c4SApple OSS Distributions if (mprotect(page, page_size, PROT_READ | PROT_WRITE) != 0) {
59*a325d9c4SApple OSS Distributions fprintf(stderr, "%s:%d mprotect(RW) error %d (%s)\n",
60*a325d9c4SApple OSS Distributions cmdname, __LINE__,
61*a325d9c4SApple OSS Distributions errno, strerror(errno));
62*a325d9c4SApple OSS Distributions exit(1);
63*a325d9c4SApple OSS Distributions }
64*a325d9c4SApple OSS Distributions
65*a325d9c4SApple OSS Distributions #if __arm64__
66*a325d9c4SApple OSS Distributions // arm64 chdir() syscall
67*a325d9c4SApple OSS Distributions char chdir_code[] = {
68*a325d9c4SApple OSS Distributions 0x90, 0x01, 0x80, 0xd2, // movz x16, #0xc
69*a325d9c4SApple OSS Distributions 0x01, 0x10, 0x00, 0xd4, // svc #0x80
70*a325d9c4SApple OSS Distributions 0xc0, 0x03, 0x5f, 0xd6, // ret
71*a325d9c4SApple OSS Distributions };
72*a325d9c4SApple OSS Distributions #elif __arm__
73*a325d9c4SApple OSS Distributions // armv7 chdir() syscall
74*a325d9c4SApple OSS Distributions char chdir_code[] = {
75*a325d9c4SApple OSS Distributions 0x0c, 0xc0, 0xa0, 0xe3, // mov r12 #0xc
76*a325d9c4SApple OSS Distributions 0x80, 0x00, 0x00, 0xef, // svc #0x80
77*a325d9c4SApple OSS Distributions 0x1e, 0xff, 0x2f, 0xe1, // bx lr
78*a325d9c4SApple OSS Distributions };
79*a325d9c4SApple OSS Distributions #elif __x86_64__
80*a325d9c4SApple OSS Distributions // x86_64 chdir() syscall
81*a325d9c4SApple OSS Distributions char chdir_code[] = {
82*a325d9c4SApple OSS Distributions 0xb8, 0x0c, 0x00, 0x00, 0x02, // movl $0x200000c, %eax
83*a325d9c4SApple OSS Distributions 0x49, 0x89, 0xca, // movq %rcx, %r10
84*a325d9c4SApple OSS Distributions 0x0f, 0x05, // syscall
85*a325d9c4SApple OSS Distributions 0xc3, // retq
86*a325d9c4SApple OSS Distributions };
87*a325d9c4SApple OSS Distributions #elif __i386__
88*a325d9c4SApple OSS Distributions // i386 chdir() syscall
89*a325d9c4SApple OSS Distributions char chdir_code[] = {
90*a325d9c4SApple OSS Distributions 0x90, // nop
91*a325d9c4SApple OSS Distributions 0xc3, // retq
92*a325d9c4SApple OSS Distributions };
93*a325d9c4SApple OSS Distributions #endif
94*a325d9c4SApple OSS Distributions memcpy(page, chdir_code, sizeof chdir_code);
95*a325d9c4SApple OSS Distributions
96*a325d9c4SApple OSS Distributions if (opt_interactive) {
97*a325d9c4SApple OSS Distributions fprintf(stdout,
98*a325d9c4SApple OSS Distributions "changed page protection to r/w and copied code at %p\n",
99*a325d9c4SApple OSS Distributions page);
100*a325d9c4SApple OSS Distributions fprintf(stdout, "pausing...\n");
101*a325d9c4SApple OSS Distributions fflush(stdout);
102*a325d9c4SApple OSS Distributions getchar();
103*a325d9c4SApple OSS Distributions }
104*a325d9c4SApple OSS Distributions
105*a325d9c4SApple OSS Distributions if (mprotect(page, page_size, PROT_READ | PROT_EXEC) != 0) {
106*a325d9c4SApple OSS Distributions fprintf(stderr, "%s:%d mprotect(RX) error %d (%s)\n",
107*a325d9c4SApple OSS Distributions cmdname, __LINE__,
108*a325d9c4SApple OSS Distributions errno, strerror(errno));
109*a325d9c4SApple OSS Distributions exit(1);
110*a325d9c4SApple OSS Distributions }
111*a325d9c4SApple OSS Distributions
112*a325d9c4SApple OSS Distributions if (opt_interactive) {
113*a325d9c4SApple OSS Distributions fprintf(stdout,
114*a325d9c4SApple OSS Distributions "changed page protection to r/x at %p\n",
115*a325d9c4SApple OSS Distributions page);
116*a325d9c4SApple OSS Distributions fprintf(stdout, "pausing...\n");
117*a325d9c4SApple OSS Distributions fflush(stdout);
118*a325d9c4SApple OSS Distributions getchar();
119*a325d9c4SApple OSS Distributions }
120*a325d9c4SApple OSS Distributions
121*a325d9c4SApple OSS Distributions char origdir[PATH_MAX];
122*a325d9c4SApple OSS Distributions getcwd(origdir, sizeof(origdir) - 1);
123*a325d9c4SApple OSS Distributions
124*a325d9c4SApple OSS Distributions chdir("/");
125*a325d9c4SApple OSS Distributions if (opt_interactive) {
126*a325d9c4SApple OSS Distributions fprintf(stdout, "cwd before = %s\n", getwd(NULL));
127*a325d9c4SApple OSS Distributions }
128*a325d9c4SApple OSS Distributions
129*a325d9c4SApple OSS Distributions void (*mychdir)(char *) = page;
130*a325d9c4SApple OSS Distributions #if __has_feature(ptrauth_calls)
131*a325d9c4SApple OSS Distributions mychdir = ptrauth_sign_unauthenticated(mychdir, ptrauth_key_function_pointer, 0);
132*a325d9c4SApple OSS Distributions #endif
133*a325d9c4SApple OSS Distributions mychdir(getenv("HOME"));
134*a325d9c4SApple OSS Distributions if (opt_interactive) {
135*a325d9c4SApple OSS Distributions fprintf(stdout, "cwd after = %s\n", getwd(NULL));
136*a325d9c4SApple OSS Distributions fprintf(stdout, "pausing...\n");
137*a325d9c4SApple OSS Distributions fflush(stdout);
138*a325d9c4SApple OSS Distributions getchar();
139*a325d9c4SApple OSS Distributions }
140*a325d9c4SApple OSS Distributions
141*a325d9c4SApple OSS Distributions fprintf(stdout, "%s: WARNING: unsigned code was executed\n",
142*a325d9c4SApple OSS Distributions cmdname);
143*a325d9c4SApple OSS Distributions
144*a325d9c4SApple OSS Distributions /* fail: unsigned code was executed */
145*a325d9c4SApple OSS Distributions fprintf(stdout, "%s: FAIL\n", cmdname);
146*a325d9c4SApple OSS Distributions exit(1);
147*a325d9c4SApple OSS Distributions }
148