This repository has been archived by the owner on Aug 18, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
shaders2.m
75 lines (59 loc) · 2.46 KB
/
shaders2.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
// dump all GL shaders compiled by WindowServer
// difficult since GLEngine uses a function pointer system that prevents interposing
// quite possibly sets a new personal record for cursed-ness...
// clang -fmodules -dynamiclib shaders2.m -o /tmp/amyshaders.dylib && codesign -fs - /tmp/amyshaders.dylib && sudo launchctl setenv DYLD_INSERT_LIBRARIES /tmp/amyshaders.dylib && sudo killall -9 WindowServer
@import Foundation;
@import Darwin;
int file;
void (*real)(void*,void*,int,char**,int*);
void mine(void* rdi,void* shader,int count,char** strings,int* lengths)
{
NSMutableString* message=NSMutableString.alloc.init;
[message appendFormat:@"date: %@\n",NSDate.date.description];
[message appendFormat:@"count: %d\n",count];
for(int index=0;index<count;index++)
{
[message appendFormat:@"code (%d): %s\n",index,strings[index]];
}
[message appendFormat:@"stack: %@\n",NSThread.callStackSymbols];
[message appendString:@"----------\n"];
write(file,message.UTF8String,message.length);
real(rdi,shader,count,strings,lengths);
}
char* swizzle(char* victim,char* fake)
{
char* base=victim-(long)victim%0x1000;
assert(mprotect(base,0x2000,PROT_READ|PROT_WRITE|PROT_EXEC)==0);
// TODO: blindly moves 12 bytes at the start of the victim function
// unlikely to work for arbitrary other functions
char* backup=malloc(0x2000);
backup+=0x1000-(long)backup%0x1000;
assert(mprotect(backup,0x1000,PROT_READ|PROT_WRITE|PROT_EXEC)==0);
memcpy(backup,victim,12);
char* back=victim+12;
memcpy(backup+12,"\x48\xb8",2);
memcpy(backup+14,&back,8);
memcpy(backup+22,"\xff\xe0",2);
// movabs rax,<fake>
// jmp rax
memcpy(victim,"\x48\xb8",2);
memcpy(victim+2,&fake,8);
memcpy(victim+10,"\xff\xe0",2);
return backup;
}
__attribute__((constructor)) void load()
{
if([NSProcessInfo.processInfo.arguments[0] containsString:@"WindowServer"])
{
NSString* name=[NSString stringWithFormat:@"/tmp/amy.shaders.%d.log",getpid()];
file=open(name.UTF8String,O_RDWR|O_CREAT|O_TRUNC);
assert(file>0);
// TODO: needless to say, this will only work on the particular OpenGL used in non-Metal
// since the function is private and hardcoded offsets were used
char* library=dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLEngine.bundle/GLEngine",RTLD_NOW);
char* reference=dlsym(library,"gleFinishCommandBuffer");
assert(reference);
char* victim=(reference-0xfb5ae)+0x78386;
real=(void (*)(void*,void*,int,char**,int*))swizzle(victim,(char*)mine);
}
}