-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTweak.x
More file actions
143 lines (121 loc) · 4.56 KB
/
Copy pathTweak.x
File metadata and controls
143 lines (121 loc) · 4.56 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
#import <Foundation/Foundation.h>
#import <Foundation/NSUserDefaults+Private.h>
#import <SpringBoard/SBApplicationInfo.h>
#import <SpringBoard/SBLeafIcon.h>
#import <UIKit/UIKit.h>
@interface FBSSignatureValidationService
- (NSInteger)trustStateForApplication:(SBApplicationInfo*)info;
@end
@interface SBApplication
- (NSString*)displayName;
- (SBApplicationInfo*)info;
@end
typedef NS_ENUM(NSInteger, TOAppPermission) {
TOAppPermissionNever = 0,
TOAppPermissionAllowOnce,
TOAppPermissionAllow
};
static FBSSignatureValidationService* validationService = nil;
static NSInteger (*orig_trustStateForApplication)(FBSSignatureValidationService*, SEL, SBApplicationInfo*) = nil;
NSInteger trustStateForApplication(SBApplicationInfo* info) {
return orig_trustStateForApplication(validationService, @selector(trustStateForApplication:), info);
}
NSInteger* getPermissionForApp(NSString* bundleId) {
// TODO: get from preferences
NSInteger* permission = malloc(sizeof(NSInteger));
*permission = TOAppPermissionAllowOnce;
return permission;
}
BOOL shouldAppAskToRun(NSString* bundleId) {
NSInteger* permission = getPermissionForApp(bundleId);
return permission == nil || *permission == TOAppPermissionAllowOnce;
}
BOOL isAppAllowedToRun(NSString* bundleId) {
NSInteger* permission = getPermissionForApp(bundleId);
return permission != nil && permission != TOAppPermissionNever;
}
%hook SBApplication
- (void)didActivateWithTransactionID:(id)arg1 {
NSLog(@"Intercepted didActivateWithTransactionID call arg1=%@", arg1);
%orig;
}
%end
// TODO: find a better class to hook that covers launches from notifications or siri
%hook SBLeafIcon
- (void)launchFromLocation:(id)location context:(id)context {
NSLog(@"Intercepted launchFromLocation call location=%@, context=%@", location, context);
if (trustStateForApplication([self.application info]) == 8 || !shouldAppAskToRun([self applicationBundleID])) {
%orig;
return;
}
// BUG: app is null when launched from spotlight search
UIAlertController* alert = [UIAlertController
alertControllerWithTitle:[NSString stringWithFormat:@"Allow “%@” to run?", [self.application displayName]]
message:@"This app is not trusted because its provisioning profile has expired." // TODO: different message depending on trust state
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* alwaysAllowButton = [UIAlertAction
actionWithTitle:@"Always Allow"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* action) {
// TODO: save preference
%orig;
}];
UIAlertAction* allowOnceButton = [UIAlertAction
actionWithTitle:@"Allow Once"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* action) {
// TODO: save preference
%orig;
}];
UIAlertAction* disallowButton = [UIAlertAction
actionWithTitle:@"Don’t Allow"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* action) {
// TODO: save preference
}];
[alert addAction:alwaysAllowButton];
[alert addAction:allowOnceButton];
[alert addAction:disallowButton];
alert.preferredAction = disallowButton;
// BUG: no scene is found the first time this is called after a respring
// BUG: can't swipe down to access notification center after first launch
NSSet* connectedScenes = [UIApplication sharedApplication].connectedScenes;
int i = 1;
for (UIScene* scene in connectedScenes) {
NSLog(@">>>> scene %i", i++);
if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) {
UIWindowScene* windowScene = (UIWindowScene*)scene;
int j = 1;
for (UIWindow* window in windowScene.windows) {
NSLog(@">>>> window %i", j++);
UIViewController* viewController = [window rootViewController];
[viewController presentViewController:alert animated:YES completion:nil];
[window makeKeyAndVisible];
break;
}
}
}
}
%end
%hook FBSSignatureValidationService
- (NSInteger)trustStateForApplication:(SBApplicationInfo*)info {
NSLog(@"Intercepted trustStateForApplication call info=%@", info);
// TODO: i don't like how there's colocated logic here
if (orig_trustStateForApplication == nil && info == nil) {
orig_trustStateForApplication = &%orig;
return 1;
}
NSInteger trustState = %orig;
return trustState == 8 || isAppAllowedToRun([info bundleIdentifier])
? 8
: trustState;
}
%end
%ctor {
%init;
// TODO: move this into its own function?
// also, maybe look for a better dummy value to pass that's not nil. perhaps
// the info for an app that's always there, like settings
validationService = [[%c(FBSSignatureValidationService) alloc] init];
[validationService trustStateForApplication:nil];
}