3.5 C
New York
Saturday, February 22, 2025

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 the moment through the use of 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 {

personal var yaraRules: UnsafeMutablePointer?

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

deinit {
    cleanupYARA()
}

personal 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.important.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?
    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 {

personal 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] end in
        guard outcome == .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 = strive? 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 outcome = fileData.withUnsafeBytes { bytes in
        yr_rules_scan_mem(
            guidelines,
            bytes.baseAddress,
            fileData.depend,
            SCAN_FLAGS_FAST_MODE,
            callback,
            &matchFound,
            0
        )
    }
    
    guard outcome == ERROR_SUCCESS else {
        handleError("Scan failed with error: (outcome)")
        return false
    }
    
    print("Match discovered: (matchFound)")  // Debugging match outcome
    return matchFound
}

personal func cleanupYARA() {
    if let guidelines = yaraRules {
        yr_rules_destroy(guidelines)
    }
    yr_finalize()
}

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

extension ViewController {
personal 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()
}
}

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles