kevin 1 ヶ月 前
コミット
72aadff96f

+ 8 - 1
ExampleCode/ExampleCode/SceneDelegate.swift

@@ -6,6 +6,7 @@
 //
 
 import UIKit
+import NexilisLite
 
 class SceneDelegate: UIResponder, UIWindowSceneDelegate {
 
@@ -16,7 +17,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
         // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
         // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
         // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
-        guard let _ = (scene as? UIWindowScene) else { return }
+        guard let windowScene = (scene as? UIWindowScene) else { return }
+        self.window = UIWindow(windowScene: windowScene)
+                    
+        // Run the security checks
+        // APIS.checkClone(window: &self.window)
+                    
+        self.window?.makeKeyAndVisible()
     }
 
     func sceneDidDisconnect(_ scene: UIScene) {

+ 138 - 0
NexilisLite/CloneCheck.swift

@@ -0,0 +1,138 @@
+//
+//  CloneCheck.swift
+//  Pods
+//
+//  Created by Maronakins on 25/08/25.
+//
+
+import UIKit
+import Darwin
+
+final class CloneCheck {
+    
+    // MARK: - Expected values (replace with your own)
+    private static let expectedBundleId = "com.yourcompany.yourapp"
+    private static let expectedTeamId   = "ABCDE12345" // <-- Your real Apple Team ID
+    
+    // MARK: - Public
+    
+    /// Run this at startup, e.g. in AppDelegate didFinishLaunching
+    static func enforceAllChecks(window: inout UIWindow?) {
+        if isJailbroken() {
+            showBlockAlertAndExit(window: &window)
+        } else {
+            if !isValidOrigin() {
+                showWarningAlert(window: &window,
+                                 message: "This app build may not be official. Please use the version from the App Store.")
+            } else if !isFromAppStore() {
+                showWarningAlert(window: &window,
+                                 message: "This app was not installed from the App Store. For security, we recommend using the official App Store version.")
+            }
+        }
+    }
+    
+    // MARK: - Jailbreak detection
+    
+    private static func isJailbroken() -> Bool {
+        return hasSuspiciousFiles() ||
+               canWriteOutsideSandbox()
+    }
+    
+    private static func hasSuspiciousFiles() -> Bool {
+        let suspiciousPaths = [
+            "/Applications/Cydia.app",
+            "/Library/MobileSubstrate/MobileSubstrate.dylib",
+            "/bin/bash",
+            "/usr/sbin/sshd",
+            "/etc/apt"
+        ]
+        
+        for path in suspiciousPaths {
+            if FileManager.default.fileExists(atPath: path) {
+                return true
+            }
+        }
+        return false
+    }
+    
+    private static func canWriteOutsideSandbox() -> Bool {
+        let testPath = "/private/jb_test.txt"
+        do {
+            try "test".write(toFile: testPath, atomically: true, encoding: .utf8)
+            try FileManager.default.removeItem(atPath: testPath)
+            return true
+        } catch {
+            return false
+        }
+    }
+    
+    // MARK: - Build origin checks
+    
+    private static func isValidOrigin() -> Bool {
+        return isBundleIdValid() && isTeamIdValid()
+    }
+    
+    private static func isBundleIdValid() -> Bool {
+        let bundleId = Bundle.main.bundleIdentifier ?? ""
+        return bundleId == expectedBundleId
+    }
+    
+    private static func isTeamIdValid() -> Bool {
+        guard let dict = Bundle.main.infoDictionary,
+              let teamId = dict["com.apple.developer.team-identifier"] as? String else {
+            return false
+        }
+        return teamId == expectedTeamId
+    }
+    
+    // MARK: - App Store check
+    
+    private static func isFromAppStore() -> Bool {
+        // App Store builds don’t have a provisioning profile
+        if Bundle.main.path(forResource: "embedded", ofType: "mobileprovision") != nil {
+            return false
+        }
+        
+        // App Store builds have "Store" receipt
+        if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL?.lastPathComponent {
+            return appStoreReceiptURL == "receipt"
+        }
+        
+        return false
+    }
+    
+    // MARK: - Alerts
+    
+    private static func showBlockAlertAndExit(window: inout UIWindow?) {
+        let alert = UIAlertController(
+            title: "Security Warning",
+            message: "This app cannot run on jailbroken devices.",
+            preferredStyle: .alert
+        )
+        
+        window = UIWindow(frame: UIScreen.main.bounds)
+        window?.rootViewController = UIViewController()
+        window?.makeKeyAndVisible()
+        
+        window?.rootViewController?.present(alert, animated: true) {
+            DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
+                exit(0)
+            }
+        }
+    }
+    
+    private static func showWarningAlert(window: inout UIWindow?, message: String) {
+        let alert = UIAlertController(
+            title: "Notice",
+            message: message,
+            preferredStyle: .alert
+        )
+        alert.addAction(UIAlertAction(title: "OK", style: .default))
+        
+        window = UIWindow(frame: UIScreen.main.bounds)
+        window?.rootViewController = UIViewController()
+        window?.makeKeyAndVisible()
+        
+        window?.rootViewController?.present(alert, animated: true)
+    }
+}

+ 4 - 0
NexilisLite/NexilisLite/Source/APIS.swift

@@ -1869,6 +1869,10 @@ public class APIS: NSObject {
             }
         }
     }
+
+    public static func checkClone(window: inout UIWindow?) {
+        CloneCheck.enforceAllChecks(window: &window)
+    }
     
     public static func checkAppStateisBackground() -> Bool {
         let state = UIApplication.shared.applicationState