I am writing a logic to detect whether selected file contains malware threaten file or now. Currently by using below code, I am always getting malware detected results even success case. Please help me on this
rules.yara
rule TestMalware {
strings:
$malware = "malicious pattern"
condition:
$malware // Match only if the string is found
}
ViewController.swift
import Cocoa
class ViewController: NSViewController {
private var yaraRules: UnsafeMutablePointer<YR_RULES>?
override func viewDidLoad() {
super.viewDidLoad()
if !initializeYARA() {
handleError("YARA initialization failed.")
}
}
deinit {
cleanupYARA()
}
private func initializeYARA() -> Bool {
// Initialize YARA library
guard yr_initialize() == ERROR_SUCCESS else {
handleError("Failed to initialize YARA.")
return false
}
// Get the rule file path from the bundle
guard let ruleFilePath = Bundle.main.path(forResource: "rules", ofType: "yara") else {
handleError("Could not find YARA rule file in bundle.")
yr_finalize()
return false
}
print("Rule file path: \(ruleFilePath)")
// Open the rules file
guard let cString = ruleFilePath.cString(using: .utf8),
let fileHandle = fopen(cString, "r") else {
handleError("Failed to open rules 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("Failed to create YARA compiler.")
yr_finalize()
return false
}
defer {
yr_compiler_destroy(compiler)
}
// Add rules file to compiler
if yr_compiler_add_file(compiler, fileHandle, nil, nil) != ERROR_SUCCESS {
handleError("Failed to compile YARA rules.")
yr_finalize()
return false
}
// Get compiled rules
guard yr_compiler_get_rules(compiler, &yaraRules) == ERROR_SUCCESS else {
handleError("Failed to load compiled YARA rules.")
yr_finalize()
return false
}
print("YARA rules successfully loaded.")
return true
}
@IBAction func actionYARAScanButtonTapped(_ sender: Any) {
guard yaraRules != nil else {
handleError("YARA rules not initialized. Please initialize first.")
return
}
runMalwareScan()
}
}
extension ViewController {
private func runMalwareScan() {
let openPanel = NSOpenPanel()
openPanel.message = "Select a file to scan for malware"
openPanel.canChooseFiles = true
openPanel.canChooseDirectories = false
openPanel.allowsMultipleSelection = false
openPanel.begin { [weak self] result in
guard result == .OK, let filePath = openPanel.url?.path else { return }
print("Selected file for scanning: \(filePath)")
if let isMalicious = self?.scanFile(at: filePath), isMalicious {
self?.showScanResult("⚠️ Malware Detected!", "The selected file has a suspicious extension.")
} else {
self?.showScanResult("✅ File Clean", "No suspicious extensions were detected in the selected file.")
}
}
}
func scanFile(at path: String) -> Bool {
guard let rules = yaraRules else {
handleError("YARA rules not initialized")
return false
}
// Read file content into memory
guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
handleError("Failed to read file content at path: \(path)")
return false
}
// Print file content for debugging
if let fileContent = String(data: fileData, encoding: .utf8) {
print("File content: \(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 result = fileData.withUnsafeBytes { bytes in
yr_rules_scan_mem(
rules,
bytes.baseAddress,
fileData.count,
SCAN_FLAGS_FAST_MODE,
callback,
&matchFound,
0
)
}
guard result == ERROR_SUCCESS else {
handleError("Scan failed with error: \(result)")
return false
}
print("Match found: \(matchFound)") // Debugging match result
return matchFound
}
private func cleanupYARA() {
if let rules = yaraRules {
yr_rules_destroy(rules)
}
yr_finalize()
}
private func showScanResult(_ title: String, _ message: String) {
DispatchQueue.main.async {
let alert = NSAlert()
alert.messageText = title
alert.informativeText = message
alert.alertStyle = .informational
alert.addButton(withTitle: "OK")
alert.runModal()
}
}
}
extension ViewController {
private 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()
}
}