123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- //
- // 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)
- }
- }
|