diff --git a/SecurityToolkitExample/SecurityToolkitExample/Resources/en.lproj/Localizable.strings b/SecurityToolkitExample/SecurityToolkitExample/Resources/en.lproj/Localizable.strings index 5a78803..d9aa6b6 100644 --- a/SecurityToolkitExample/SecurityToolkitExample/Resources/en.lproj/Localizable.strings +++ b/SecurityToolkitExample/SecurityToolkitExample/Resources/en.lproj/Localizable.strings @@ -5,6 +5,8 @@ "threat.hooks.description" = "Intercept system or application calls and then modify them (modify the return value of a function call for example)"; "threat.simulator.title" = "Simulator"; "threat.simulator.description" = "Running the application in a simulator"; +"threat.debugger.title" = "Debugger"; +"threat.debugger.description" = "A tool that allows developers to inspect and modify the execution of a program in real-time, potentially exposing sensitive data or allowing unauthorized control."; // MARK: Threat List "threat.list.title" = "Protection"; diff --git a/SecurityToolkitExample/SecurityToolkitExample/Sources/ThreatStatus.swift b/SecurityToolkitExample/SecurityToolkitExample/Sources/ThreatStatus.swift index 9cc9854..306cf4f 100644 --- a/SecurityToolkitExample/SecurityToolkitExample/Sources/ThreatStatus.swift +++ b/SecurityToolkitExample/SecurityToolkitExample/Sources/ThreatStatus.swift @@ -22,6 +22,11 @@ struct ThreatStatus: Hashable { description: R.string.localizable.threatSimulatorDescription(), isDetected: ThreatDetectionCenter.isSimulatorDetected ), + ThreatStatus( + title: R.string.localizable.threatDebuggerTitle(), + description: R.string.localizable.threatDebuggerDescription(), + isDetected: ThreatDetectionCenter.isDebuggerDetected + ), ] } diff --git a/Sources/DebuggerDetection.swift b/Sources/DebuggerDetection.swift new file mode 100644 index 0000000..7d3026b --- /dev/null +++ b/Sources/DebuggerDetection.swift @@ -0,0 +1,25 @@ +import Foundation + +// MARK: - Internal +internal final class DebuggerDetection { + + static func threatDetected() -> Bool? { + hasTracerFlagSet() + } +} + +// MARK: - Private +fileprivate extension DebuggerDetection { + + /// Check P_TRACED flag from Darwin Kernel + /// if the process is traced + private static func hasTracerFlagSet() -> Bool? { + var info = kinfo_proc() + var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()] // Kernel info, process info, specific process by PID, get current process ID + var size = MemoryLayout.stride(ofValue: info) + + let unixStatusCode = sysctl(&mib, u_int(mib.count), &info, &size, nil, 0) + + return unixStatusCode == 0 ? (info.kp_proc.p_flag & P_TRACED) != 0 : nil + } +} diff --git a/Sources/ThreatDetectionCenter.swift b/Sources/ThreatDetectionCenter.swift index ecd3745..72ab0a7 100644 --- a/Sources/ThreatDetectionCenter.swift +++ b/Sources/ThreatDetectionCenter.swift @@ -14,6 +14,21 @@ public final class ThreatDetectionCenter { SimulatorDetection.threatDetected() } + /// Will check if your application is being traced by a debugger. + /// + /// - Returns: + /// `true`: If a debugger is detected. + /// `false`: If no debugger is detected. + /// `nil`: The detection process did not produce a definitive result. This could happen due to system limitations, lack of required permissions, or other undefined conditions. + /// + /// A debugger is a tool that allows developers to inspect and modify the execution of a program in real-time, potentially exposing sensitive data or allowing unauthorized control. + /// + /// ## Notes + /// Please note that Apple itself may require a debugger for the app review process. + public static var isDebuggerDetected: Bool? { + DebuggerDetection.threatDetected() + } + // MARK: - Async Threat Detection @@ -22,6 +37,7 @@ public final class ThreatDetectionCenter { case rootPrivileges case hooks case simulator + case debugger } /// Stream that contains possible threats that could be detected @@ -40,6 +56,10 @@ public final class ThreatDetectionCenter { continuation.yield(.simulator) } + if DebuggerDetection.threatDetected() ?? false { + continuation.yield(.debugger) + } + continuation.finish() } }