Skip to content

Instantly share code, notes, and snippets.

@wesmatlock
Created October 28, 2025 14:25
Show Gist options
  • Select an option

  • Save wesmatlock/edcc88ede54e5196cb976653fb0e6a36 to your computer and use it in GitHub Desktop.

Select an option

Save wesmatlock/edcc88ede54e5196cb976653fb0e6a36 to your computer and use it in GitHub Desktop.
RASPManager
import Foundation
import CryptoKit
import UIKit
import os.log
import Darwin
public final class RASPManager {
public static let shared = RASPManager()
private let logger = Logger(subsystem: "com.app.security", category: "RASP")
private var monitoringTimer: Timer?
private var isMonitoring = false
private init() {}
public enum ThreatLevel: Int {
case none = 0
case low = 1
case medium = 2
case high = 3
case critical = 4
}
public struct ThreatDetection {
let type: String
let level: ThreatLevel
let timestamp: Date
let details: [String: Any]
}
public func startMonitoring() {
guard !isMonitoring else { return }
isMonitoring = true
logger.info("RASP monitoring started")
monitoringTimer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: true) { [weak self] _ in
self?.performSecurityChecks()
}
setupNotificationObservers()
performInitialChecks()
}
public func stopMonitoring() {
isMonitoring = false
monitoringTimer?.invalidate()
monitoringTimer = nil
logger.info("RASP monitoring stopped")
}
private func performInitialChecks() {
checkDebuggerAttachment()
checkCodeIntegrity()
checkRuntimeManipulation()
checkMemoryIntegrity()
}
private func performSecurityChecks() {
DispatchQueue.global(qos: .background).async { [weak self] in
self?.checkDebuggerAttachment()
self?.checkRuntimeManipulation()
self?.checkMemoryIntegrity()
self?.checkNetworkInterception()
}
}
private func checkDebuggerAttachment() {
var info = kinfo_proc()
var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
var size = MemoryLayout<kinfo_proc>.stride
let result = sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0)
if result == 0 && (info.kp_proc.p_flag & P_TRACED) != 0 {
handleThreatDetection(ThreatDetection(
type: "Debugger Attached",
level: .critical,
timestamp: Date(),
details: ["process_flag": info.kp_proc.p_flag]
))
}
if isBeingDebugged() {
handleThreatDetection(ThreatDetection(
type: "Debugger Detected (ptrace)",
level: .critical,
timestamp: Date(),
details: [:]
))
}
}
private func isBeingDebugged() -> Bool {
var name: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
var info = kinfo_proc()
var info_size = MemoryLayout<kinfo_proc>.size
if sysctl(&name, 4, &info, &info_size, nil, 0) != 0 {
return false
}
return (info.kp_proc.p_flag & P_TRACED) != 0
}
private func checkCodeIntegrity() {
guard let executablePath = Bundle.main.executablePath else { return }
do {
let data = try Data(contentsOf: URL(fileURLWithPath: executablePath))
let hash = SHA256.hash(data: data)
let hashString = hash.compactMap { String(format: "%02x", $0) }.joined()
if let storedHash = UserDefaults.standard.string(forKey: "executable_hash") {
if hashString != storedHash {
handleThreatDetection(ThreatDetection(
type: "Code Integrity Violation",
level: .critical,
timestamp: Date(),
details: ["expected": storedHash, "actual": hashString]
))
}
} else {
UserDefaults.standard.set(hashString, forKey: "executable_hash")
}
} catch {
logger.error("Failed to check code integrity: \(error.localizedDescription)")
}
}
private func checkRuntimeManipulation() {
let handle = dlopen(nil, RTLD_NOW)
defer { if let h = handle { dlclose(h) } }
let suspiciousFunctions = [
"MSHookFunction",
"MSFindSymbol",
"MSGetImageByName",
"substitute_hook_functions"
]
for function in suspiciousFunctions {
var symbolFound = false
function.withCString { cString in
if let h = handle, dlsym(h, cString) != nil {
symbolFound = true
}
}
if symbolFound {
handleThreatDetection(ThreatDetection(
type: "Runtime Manipulation",
level: .high,
timestamp: Date(),
details: ["function": function]
))
}
}
}
private func checkMemoryIntegrity() {
let criticalClasses = [
"URLSession",
"SecKeychain",
"LAContext"
]
for className in criticalClasses {
guard let cls = NSClassFromString(className) else { continue }
let methodCount = class_getInstanceMethod(cls, NSSelectorFromString("init"))
if methodCount == nil {
handleThreatDetection(ThreatDetection(
type: "Memory Tampering",
level: .medium,
timestamp: Date(),
details: ["class": className]
))
}
}
}
private func checkNetworkInterception() {
if let proxySettings = CFNetworkCopySystemProxySettings()?.takeRetainedValue() as? [String: Any] {
var interceptors: [String] = []
let httpEnableKey = "HTTPEnable"
let httpProxyKey = "HTTPProxy"
let httpsEnableKey = "HTTPSEnable"
let httpsProxyKey = "HTTPSProxy"
if let httpEnabled = proxySettings[httpEnableKey] as? NSNumber, httpEnabled.boolValue,
let httpProxy = proxySettings[httpProxyKey] as? String, !httpProxy.isEmpty {
interceptors.append("HTTP: \(httpProxy)")
}
if let httpsEnabled = proxySettings[httpsEnableKey] as? NSNumber, httpsEnabled.boolValue,
let httpsProxy = proxySettings[httpsProxyKey] as? String, !httpsProxy.isEmpty {
interceptors.append("HTTPS: \(httpsProxy)")
}
if !interceptors.isEmpty {
handleThreatDetection(ThreatDetection(
type: "Network Interception",
level: .medium,
timestamp: Date(),
details: ["proxies": interceptors]
))
}
}
}
private func setupNotificationObservers() {
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationDidBecomeActive),
name: UIApplication.didBecomeActiveNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationWillResignActive),
name: UIApplication.willResignActiveNotification,
object: nil
)
}
@objc private func applicationDidBecomeActive() {
performSecurityChecks()
}
@objc private func applicationWillResignActive() {
checkMemoryIntegrity()
}
private func handleThreatDetection(_ detection: ThreatDetection) {
logger.warning("Threat detected: \(detection.type) - Level: \(detection.level.rawValue)")
switch detection.level {
case .critical:
terminateApplication()
case .high:
disableSensitiveFeatures()
notifySecurityTeam(detection)
case .medium:
logSecurityEvent(detection)
increaseMonitoring()
case .low:
logSecurityEvent(detection)
case .none:
break
}
}
private func terminateApplication() {
logger.critical("Critical threat detected. Terminating application.")
DispatchQueue.main.async {
let alert = UIAlertController(
title: "Security Alert",
message: "A security issue has been detected. Please reinstall the app.",
preferredStyle: .alert
)
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let rootViewController = windowScene.windows.first?.rootViewController {
rootViewController.present(alert, animated: true) {
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
exit(0)
}
}
} else {
exit(0)
}
}
}
private func disableSensitiveFeatures() {
NotificationCenter.default.post(name: .disableSensitiveFeatures, object: nil)
}
private func notifySecurityTeam(_ detection: ThreatDetection) {
// Implement security team notification
}
private func logSecurityEvent(_ detection: ThreatDetection) {
logger.info("Security event: \(detection.type) at \(detection.timestamp)")
}
private func increaseMonitoring() {
monitoringTimer?.invalidate()
monitoringTimer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { [weak self] _ in
self?.performSecurityChecks()
}
}
}
extension Notification.Name {
static let disableSensitiveFeatures = Notification.Name("DisableSensitiveFeatures")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment