Swift – YARA Malware Detection for any file macOS or iOS

Swift – YARA Malware Detection for any file macOS or iOS


I’m writing a logic to detect whether or not chosen file comprises malware threaten file or now. At present by utilizing beneath code, I’m at all times getting malware detected outcomes even success case. Please assist me on this

guidelines.yara

rule TestMalware {
strings:
    $malware = "malicious sample"
situation:
    $malware  // Match provided that the string is discovered
}

ViewController.swift

import Cocoa

class ViewController: NSViewController {

non-public var yaraRules: UnsafeMutablePointer<YR_RULES>?

override func viewDidLoad() {
    tremendous.viewDidLoad()
    if !initializeYARA() {
        handleError("YARA initialization failed.")
    }
}

deinit {
    cleanupYARA()
}

non-public func initializeYARA() -> Bool {
    // Initialize YARA library
    guard yr_initialize() == ERROR_SUCCESS else {
        handleError("Didn't initialize YARA.")
        return false
    }
    
    // Get the rule file path from the bundle
    guard let ruleFilePath = Bundle.fundamental.path(forResource: "guidelines", ofType: "yara") else {
        handleError("Couldn't discover YARA rule file in bundle.")
        yr_finalize()
        return false
    }
    
    print("Rule file path: (ruleFilePath)")
    
    // Open the foundations file
    guard let cString = ruleFilePath.cString(utilizing: .utf8),
          let fileHandle = fopen(cString, "r") else {
        handleError("Didn't open guidelines file.")
        yr_finalize()
        return false
    }
    
    defer {
        fclose(fileHandle)
    }
    
    // Create the YARA compiler
    var compiler: UnsafeMutablePointer<YR_COMPILER>?
    guard yr_compiler_create(&compiler) == ERROR_SUCCESS else {
        handleError("Didn't create YARA compiler.")
        yr_finalize()
        return false
    }
    
    defer {
        yr_compiler_destroy(compiler)
    }
    
    // Add guidelines file to compiler
    if yr_compiler_add_file(compiler, fileHandle, nil, nil) != ERROR_SUCCESS {
        handleError("Didn't compile YARA guidelines.")
        yr_finalize()
        return false
    }
    
    // Get compiled guidelines
    guard yr_compiler_get_rules(compiler, &yaraRules) == ERROR_SUCCESS else {
        handleError("Didn't load compiled YARA guidelines.")
        yr_finalize()
        return false
    }
    
    print("YARA guidelines efficiently loaded.")
    return true
}

@IBAction func actionYARAScanButtonTapped(_ sender: Any) {
    guard yaraRules != nil else {
        handleError("YARA guidelines not initialized. Please initialize first.")
        return
    }
    runMalwareScan()
}
}

extension ViewController {

non-public func runMalwareScan() {
    let openPanel = NSOpenPanel()
    openPanel.message = "Choose a file to scan for malware"
    openPanel.canChooseFiles = true
    openPanel.canChooseDirectories = false
    openPanel.allowsMultipleSelection = false
    
    openPanel.start { [weak self] lead to
        guard consequence == .OK, let filePath = openPanel.url?.path else { return }
        print("Chosen file for scanning: (filePath)")
        
        if let isMalicious = self?.scanFile(at: filePath), isMalicious {
            self?.showScanResult("⚠️ Malware Detected!", "The chosen file has a suspicious extension.")
        } else {
            self?.showScanResult("✅ File Clear", "No suspicious extensions have been detected within the chosen file.")
        }
    }
}

func scanFile(at path: String) -> Bool {
    guard let guidelines = yaraRules else {
        handleError("YARA guidelines not initialized")
        return false
    }
    
    // Learn file content material into reminiscence
    guard let fileData = attempt? Knowledge(contentsOf: URL(fileURLWithPath: path)) else {
        handleError("Didn't learn file content material at path: (path)")
        return false
    }
    
    // Print file content material for debugging
    if let fileContent = String(information: fileData, encoding: .utf8) {
        print("File content material: (fileContent)")
    }
    
    var matchFound = false
    
    let callback: YR_CALLBACK_FUNC = { context, message, rule, userData in
        guard let userData = userData else { return CALLBACK_ERROR }
        let matchFoundPtr = userData.assumingMemoryBound(to: Bool.self)
        matchFoundPtr.pointee = true
        
        if let rule = rule {
            let rulePointer = rule.assumingMemoryBound(to: YR_RULE.self)
            let ruleIdentifier = String(cString: rulePointer.pointee.identifier)
            print("[YARA Match] Rule matched: (ruleIdentifier)")  // Debugging matched rule
        }
        
        return CALLBACK_CONTINUE
    }
    
    let consequence = fileData.withUnsafeBytes { bytes in
        yr_rules_scan_mem(
            guidelines,
            bytes.baseAddress,
            fileData.depend,
            SCAN_FLAGS_FAST_MODE,
            callback,
            &matchFound,
            0
        )
    }
    
    guard consequence == ERROR_SUCCESS else {
        handleError("Scan failed with error: (consequence)")
        return false
    }
    
    print("Match discovered: (matchFound)")  // Debugging match consequence
    return matchFound
}

non-public func cleanupYARA() {
    if let guidelines = yaraRules {
        yr_rules_destroy(guidelines)
    }
    yr_finalize()
}

non-public func showScanResult(_ title: String, _ message: String) {
    DispatchQueue.fundamental.async {
        let alert = NSAlert()
        alert.messageText = title
        alert.informativeText = message
        alert.alertStyle = .informational
        alert.addButton(withTitle: "OK")
        alert.runModal()
    }
}
}

extension ViewController {
non-public func handleError(_ message: String) {
    print("[YARA Error] (message)")
    let alert = NSAlert()
    alert.messageText = "YARA Error"
    alert.informativeText = message
    alert.alertStyle = .warning
    alert.addButton(withTitle: "OK")
    alert.runModal()
}
}

author avatar
roosho Senior Engineer (Technical Services)
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog. 
rooshohttps://www.roosho.com
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog. 

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here


Latest Articles

author avatar
roosho Senior Engineer (Technical Services)
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog.