-
Notifications
You must be signed in to change notification settings - Fork 51
/
lsym.m
executable file
·159 lines (145 loc) · 5.37 KB
/
lsym.m
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
153
154
155
156
157
158
159
#include "lsym.h"
#import <Foundation/Foundation.h>
#include <IOKit/IOKitLib.h>
struct segment_command_64 *find_segment_64(struct mach_header_64 *mh, const char *segname);
struct section_64 *find_section_64(struct segment_command_64 *seg, const char *name);
struct load_command *find_load_command(struct mach_header_64 *mh, uint32_t cmd);
extern CFDictionaryRef OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef);
extern CFDictionaryRef OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef);
#ifdef FIND_KERNEL_SLIDE
static lsym_offset_t kaslr_slide=0;
static char kaslr_slide_found =0;
#endif
__attribute__((always_inline))
lsym_kern_pointer_t kext_pointer(const char* identifier){
return (lsym_kern_pointer_t)[((NSNumber*)(((__bridge NSDictionary*)OSKextCopyLoadedKextInfo(NULL, NULL))[[NSString stringWithUTF8String:identifier]][@"OSBundleLoadAddress"])) unsignedLongLongValue];
}
__attribute__((always_inline))
lsym_map_t *lsym_map_file(const char *path) {
int fd=open(path, O_RDONLY);
if(fd < 0) return 0;
struct stat sb;
fstat(fd, &sb);
if (sb.st_size < 0x1000) {
return 0;
}
void* map = mmap(NULL, sb.st_size & 0xFFFFFFFF, PROT_READ, MAP_SHARED, fd, 0);
lsym_map_t* ret = (lsym_map_t*)malloc(sizeof(lsym_map_t));
ret->map = map;
ret->path = path;
ret->sz = sb.st_size & 0xFFFFFFFF;
return ret;
}
__attribute__((always_inline))
lsym_kern_pointer_t lsym_find_gadget(lsym_map_t *mapping, const char *bytes, const uint32_t size, const lsym_gadget_flags flags) {
lsym_offset_t off=(lsym_offset_t)memmem(mapping->map, mapping->sz, bytes, size);
if (!off) {
puts("[-] Couldn't find a ROP gadget, aborting.");
exit(1);
}
return lsym_slide_pointer(((flags & LSYM_DO_NOT_REBASE) == 0 ? lsym_kernel_base(mapping) : 0)+(off - (lsym_offset_t) mapping->map));
}
__attribute__((always_inline))
lsym_kern_pointer_t lsym_kernel_base(lsym_map_t *mapping) {
struct mach_header_64 *mh = mapping->map;
struct segment_command_64 *text = find_segment_64(mh, SEG_TEXT);
return (lsym_kern_pointer_t)text->vmaddr;
}
__attribute__((always_inline))
lsym_kern_pointer_t lsym_find_symbol(lsym_map_t *mapping, const char *name) {
struct mach_header_64 *mh = mapping->map;
struct symtab_command *symtab = NULL;
struct segment_command_64 *linkedit = NULL;
/*
* Check header
*/
if (mh->magic != MH_MAGIC_64) {
return (lsym_kern_pointer_t)NULL;
}
/*
* Find the LINKEDIT and SYMTAB sections
*/
linkedit = find_segment_64(mh, SEG_LINKEDIT);
if (!linkedit) {
return (lsym_kern_pointer_t)NULL;
}
symtab = (struct symtab_command *)find_load_command(mh, LC_SYMTAB);
if (!symtab) {
return (lsym_kern_pointer_t)NULL;
}
void* symtabp = symtab->stroff + 4 + (char*)mh;
void* symtabz = symtab->stroff + (char*)mh;
void* symendp = symtab->stroff + (char*)mh + symtab->strsize - 0xA;
uint32_t idx = 0;
while (symtabp < symendp) {
if(strcmp(symtabp, name) == 0) goto found;
symtabp += strlen((char*)symtabp) + 1;
idx++;
}
printf("[-] symbol %s not resolved.\n", name); exit(0);
return (lsym_kern_pointer_t)NULL;
found:;
struct nlist_64* nlp = (struct nlist_64*) (((uint32_t)(symtab->symoff)) + (char*)mh);
uint64_t strx = ((char*)symtabp - (char*)symtabz);
unsigned int symp = 0;
while(symp <= (symtab->nsyms)) {
uint32_t strix = *((uint32_t*)nlp);
if(strix == strx)
goto found1;
nlp ++; //sizeof(struct nlist_64);
symp++;
}
printf("[-] symbol not found: %s\n", name);
exit(-1);
found1:
//printf("[+] found symbol %s at 0x%016llx\n", name, nlp->n_value);
return (lsym_kern_pointer_t)nlp->n_value;
}
__attribute__((always_inline))
struct segment_command_64 *find_segment_64(struct mach_header_64 *mh, const char *segname)
{
struct load_command *lc;
struct segment_command_64 *s, *fs = NULL;
lc = (struct load_command *)((uint64_t)mh + sizeof(struct mach_header_64));
while ((uint64_t)lc < (uint64_t)mh + (uint64_t)mh->sizeofcmds) {
if (lc->cmd == LC_SEGMENT_64) {
s = (struct segment_command_64 *)lc;
if (!strcmp(s->segname, segname)) {
fs = s;
break;
}
}
lc = (struct load_command *)((uint64_t)lc + (uint64_t)lc->cmdsize);
}
return fs;
}
__attribute__((always_inline))
struct section_64 *find_section_64(struct segment_command_64 *seg, const char *name)
{
struct section_64 *sect, *fs = NULL;
uint32_t i = 0;
for (i = 0, sect = (struct section_64 *)((uint64_t)seg + (uint64_t)sizeof(struct segment_command_64));
i < seg->nsects;
i++, sect = (struct section_64 *)((uint64_t)sect + sizeof(struct section_64)))
{
if (!strcmp(sect->sectname, name)) {
fs = sect;
break;
}
}
return fs;
}
__attribute__((always_inline))
struct load_command *find_load_command(struct mach_header_64 *mh, uint32_t cmd)
{
struct load_command *lc, *flc;
lc = (struct load_command *)((uint64_t)mh + sizeof(struct mach_header_64));
while ((uint64_t)lc < (uint64_t)mh + (uint64_t)mh->sizeofcmds) {
if (lc->cmd == cmd) {
flc = (struct load_command *)lc;
break;
}
lc = (struct load_command *)((uint64_t)lc + (uint64_t)lc->cmdsize);
}
return flc;
}