Skip to content

Instantly share code, notes, and snippets.

@shellcromancer
Last active February 23, 2023 04:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shellcromancer/1192b537e690a1cceee7c057529b9d59 to your computer and use it in GitHub Desktop.
Save shellcromancer/1192b537e690a1cceee7c057529b9d59 to your computer and use it in GitHub Desktop.
Run the XProtect.yara ruleset over the Objective-See malware collection.
#!/usr/bin/env python3
# author: @shellcromancer
# Day 53 of #100DaysofYARA
import io
import os
import requests
import zipfile
import yara
import logging
import matplotlib.pyplot as plt
import numpy as np
rules = yara.compile('/Library/Apple/System/Library/CoreServices/XProtect.bundle/Contents/Resources/XProtect.yara')
base_path = 'tmp/'
try:
os.makedirs(base_path)
except FileExistsError:
pass
def pull_objc_malware() -> None:
response = requests.get(r"https://objective-see.com/malware.json")
data = response.json().get('malware', [])
for sample in data:
dl_url, name = sample.get('download'), sample.get('name')
if dl_url is None or dl_url == '#':
continue
dl_path = os.path.join(base_path, name)
if os.path.isdir(dl_path):
continue
try:
with requests.get(dl_url, stream=True) as r:
r.raise_for_status()
z = zipfile.ZipFile(io.BytesIO(r.content))
z.setpassword(b"infect3d")
z.extractall(dl_path)
except (requests.RequestException, zipfile.BadZipFile) as e:
logging.error(f"failed to download {name}: {e}")
def scan_directory(dirname: str) -> bool:
for folder,_, files in os.walk(dirname):
for file in files:
path = os.path.join(folder, file)
try:
with open(path, 'rb') as f:
matches = rules.match(data=f.read())
if len(matches) > 0:
return True
except Exception as e:
print(e)
pass
return False
def scan_objc_malware() -> dict[str, bool]:
dirs = next(os.walk(base_path))[1]
coverage = {}
for d in dirs:
result = scan_directory(os.path.join(base_path, d))
coverage[d] = result
return coverage
def plot(coverage: dict[str, bool]):
detected = sum(coverage.values())
labels = ['Detected', 'Not Detected']
data = [detected, len(coverage) - detected]
def func(pct, allvals):
absolute = int(np.round(pct/100.*np.sum(allvals)))
return f"{pct:.1f}%\n({absolute:d})"
fig, ax = plt.subplots(figsize =(10, 7))
ax.pie(data, labels=labels, autopct=lambda pct: func(pct, data))
version = os.popen('/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" /Library/Apple/System/Library/CoreServices/XProtect.bundle/Contents/version.plist').read().strip()
ax.set_title(f"XProtect (Version: {version}) Objective-See Detections")
plt.savefig('xprotect-detections.png')
if __name__ == "__main__":
pull_objc_malware()
coverage = scan_objc_malware()
plot(coverage)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment