Skip to content

Instantly share code, notes, and snippets.

@sheagcraig
Last active November 27, 2021 23:51
Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save sheagcraig/69a473f00ce434fffd5b to your computer and use it in GitHub Desktop.
Save sheagcraig/69a473f00ce434fffd5b to your computer and use it in GitHub Desktop.
Check for Adware per Apple Kbase article
#!/usr/bin/python
"""Identify or remove files known to be involved in Adware/Malware
infection.
Most of the code applies to building a list of malware files. Thus,
both extension attribute and removal handling are included.
Cleans files as a Casper script policy; thus, it expects four total
arguments, the first three of which it doesn't use, followed by
--remove
"""
import glob
import os
import re
import shutil
import sys
import syslog
# https://support.apple.com/en-us/ht203987
known_malware = {
'/System/Library/Frameworks/v.framework',
'/System/Library/Frameworks/VSearch.framework',
'/Library/PrivilegedHelperTools/Jack',
'/Library/InputManagers/CTLoader/',
'/Library/Application Support/Conduit/',
'/Applications/SearchProtect.app',
'/private/etc/launchd.conf',
'/Applications/Genieo',
'/Applications/InstallMac',
'/Applications/Uninstall Genieo',
'/Applications/Uninstall IM Completer.app',
'/usr/lib/libgenkit.dylib',
'/usr/lib/libgenkitsa.dylib',
'/usr/lib/libimckit.dylib',
'/usr/lib/libimckitsa.dylib',
'/Library/PrivilegedHelperTools/com.genieoinnovation.macextension.client',
'/Library/Frameworks/GenieoExtra.framework',
'/Library/LaunchAgents/com.genieo.completer.update.plist',
'/Library/LaunchAgents/com.genieo.engine.plist',
'/Library/LaunchAgents/com.genieoinnovation.macextension.client.plist',
'/Library/LaunchAgents/com.genieoinnovation.macextension.plist',
'/Library/LaunchDaemons/com.genieoinnovation.macextension.client.plist',
'/Library/LaunchDaemons/Jack.plist'
'/Users/*/Library/Internet Plug-Ins/ConduitNPAPIPlugin.plugin',
'/Users/*/Library/Internet Plug-Ins/TroviNPAPIPlugin.plugin',
'/Users/*/Library/Application Support/Genieo/',
'/Users/*/Library/Application Support/com.genieoinnovation.Installer/',
'/Users/*/Conduit/',
'/Users/*/Trovi/',
'/Users/*/Library/Caches/com.Conduit.takeOverSearchAssetsMac',
'/Users/*/Library/Caches/com.VSearch.bulk.installer',
'/Users/*/Library/Caches/com.VSearch.VSinstaller',
'/Users/*/Library/LaunchAgents/com.genieo.completer.download.plist',
'/Users/*/Library/LaunchAgents/com.genieo.completer.ltvbit.plist',
'/Users/*/Library/LaunchAgents/com.genieo.completer.update.plist',
'/Users/*/Library/Preferences/com.genieo.global.settings.plist.lockfile',
'/Users/*/Library/Preferences/com.geneio.settings.plist.lockfile',
'/Users/*/Library/Preferences/com.geneio.global.settings.plist',
'/Users/*/Library/Saved Application State/com.genieo.RemoveGenieoMac.savedState',
'/Users/*/Library/Saved Application State/com.VSearch.bulk.installer.savedstate',
'/Users/*/Library/LaunchAgents/com.jdibackup.ZipCloud.autostart.plist'}
found_malware = {match for filename in known_malware for match in
glob.glob(filename)}
# Look for "ProjectX" variants.
# This adware seems to have a different name each time it pops up.
# Apple's solution is too broad. We look at the files Apple suggests,
# but then also search within to see if they are calling a known
# binary file, "agent.app/Contents/MacOS/agent".
projectx_files = {
'/Library/LaunchAgents/com.*.agent.plist',
'/Library/LaunchDaemons/com.*.helper.plist',
'/Library/LaunchDaemons/com.*.daemon.plist',
}
projectx_candidates = {match for filename in projectx_files for match in
glob.glob(filename)}
agent_regex = re.compile('.*/Library/Application Support/(.*)/Agent/agent.app/Contents/MacOS/agent')
for candidate in projectx_candidates:
with open(candidate, 'r') as candidate_file:
launchd_job = candidate_file.read()
if re.search(agent_regex, launchd_job):
found_malware.add(candidate)
# If we find a Launch[Agent|Daemon] that has ProgramArguments
# which runs "agent", find the unique name for this instance.
# We can then use it to find the Application Support folder.
obfuscated_name = re.search(agent_regex, launchd_job).group(1)
found_malware.add('/Library/Application Support/%s' % obfuscated_name)
# Is this an EA or a script execution (Casper scripts always have 3
# args, so we can't just use the first argument.
if len(sys.argv) == 1:
# Extension attribute (First arg is always script name).
result = '<result>'
if found_malware:
result += 'True\n'
for item in enumerate(found_malware):
result += "%d: %s\n" % item
else:
result += 'False'
print('%s</result>' % result)
elif "--remove" in sys.argv:
# Removal script.
syslog.syslog(syslog.LOG_ALERT, "Looking for malware")
for item in found_malware:
try:
if os.path.isdir(item):
shutil.rmtree(item)
elif os.path.isfile(item):
os.remove(item)
syslog.syslog(syslog.LOG_ALERT, "Removed malware file: %s" % item)
except OSError as e:
syslog.syslog(syslog.LOG_ALERT,
"Failed to remove malware file: %s, %s" % (item, e))
@arubdesu
Copy link

They missed at least another two:

'/Users/*/Library/LaunchAgents/com.jdibackup.ZipCloud.autostart.plist',
'/Users/*/Library/LaunchAgents/com.zeobit.MacKeeper.Helper.plist',

@arubdesu
Copy link

uh, and I think you're missing from re import match?

@sheagcraig
Copy link
Author

Oh thanks! Was going to dig out your other gists for the MacKeeper stuff. Does it install any frameworks/binaries anywhere else?

match is not a builtin or reserved, so the match above is just a temporary variable name, not re.match.

@gregneagle
Copy link

I found a few machines with these:
/Applications/SearchProtect/Data
/Applications/SearchProtect/SearchProtect.app
/Applications/SearchProtect/Uninstaller.app
/Applications/SearchProtect/takeOverSearchAssetsMac.app

@haircut
Copy link

haircut commented Mar 30, 2015

I installed Genieo fresh this morning and they've changed some of the files in use. This is going to be a moving target :/

/Users/*/Library/Application Support/IM.Installer/
/Users/*/Library/LaunchAgents/com.Installer.completer.download.plist
/Users/*/Library/LaunchAgents/com.Installer.completer.ltvbit.plist
/Users/*/Library/LaunchAgents/com.Installer.completer.update.plist
/Users/*/Library/Preferences/com.genieo.settings.plist
/Users/*/Library/Preferences/com.IM.partner.settings.plist
/Users/*/Library/Preferences/com.installmc.global.settings.plist
/Users/*/Library/Preferences/com.installmc.settings.plist

@Chalcahuite
Copy link

Just installed MacKeeper and it's now /Users//Library/LaunchAgents/com.mackeeper.MacKeeper.Helper.plist
Also Spigot installs a Safari extension here: /Users/
/Library/Safari/Extensions/Searchme.safariextz

@JonMunford
Copy link

Hey Shea, I found that this is still missing quite a bit of adware. I modified your version with more definitions and added a section so it will delete chrome and firefox preferences files if adware is found.
Not sure how to post the code properly so here ya go.

!/usr/bin/python

"""Identify or remove files known to be involved in Adware/Malware
infection.

Most of the code applies to building a list of malware files. Thus,
both extension attribute and removal handling are included.

Cleans files as a Casper script policy; thus, it expects four total
arguments, the first three of which it doesn't use, followed by
--remove
"""

import glob
import os
import re
import shutil
import sys
import syslog

known_malware = {

#SearchMe
'/Users//Library/Safari/Extensions/Searchme.safariextz',

#ZipCloud
 '/Users/*/Library/LaunchAgents/com.jdibackup.ZipCloud.autostart.plist',


#MacKeeper
'/Users/*/Library/LaunchAgents/com.zeobit.MacKeeper.Helper.plist',
'/Users/*/Library/Preferences/com.installmc.global.settings.plist',
'/Users/*/Library/Preferences/com.installmc.settings.plist',
'/Users//Library/LaunchAgents/com.mackeeper.MacKeeper.Helper.plist',

#VSearch
'/Users/*/Library/Caches/com.VSearch.bulk.installer',
'/Users/*/Library/Caches/com.VSearch.VSinstaller',
'/Users/*/Library/Saved Application State/com.VSearch.bulk.installer.savedstate',

#IM Installer
'/Users/*/Library/Application Support/IM.Installer/',
'/Users/*/Library/Preferences/com.IM.partner.settings.plist',

#Installer Completer
'/Users/*/Library/LaunchAgents/com.Installer.completer.download.plist',
'/Users/*/Library/LaunchAgents/com.Installer.completer.ltvbit.plist',
'/Users/*/Library/LaunchAgents/com.Installer.completer.update.plist',


# FkCodec
'/Users/*/Library/Application Support/Codec-M',
'/Users/*/Library/LaunchAgents/com.codecm.uploader.plist',
'/Applications/Codec-M.app',

#Yontoo
'/Users/*/Library/Application Support/Google/Chrome/YontooLayers.crx',

#ChatZum
'/Applications/ChatZumUninstaller.pkg',
'/Library/Application Support/SIMBL/Plugins/SafariOmnibar.bundle',
'/Library/Internet Plug-Ins/uid.plist',
'/Library/Internet Plug-Ins/zako.plugin',

#Spigot
'/Users/*/Library/Application Support/Spigot/',

#SaveKeep
'/Applications/Savekeep.app',

#Conduit
'/Users/*/Library/Application Support/Google/Chrome/Default/Extensions/cbmjmfcldbpelhknnfjbkobmabafpoed',
'/Library/InputManagers/CTLoader/',
'/Library/LaunchAgents/com.conduit.loader.agent.plist',
'/Library/LaunchDaemons/com.perion.searchprotectd.plist',
'/Library/Application Support/SIMBL/Plugins/CT2285220.bundle',
'/Library/Application Support/Conduit/',
'/Applications/SearchProtect.app',
'/Applications/SearchProtect/',
'/Users/*/Conduit/',
'/Users/*/Trovi/',
'/Users/*/Library/Application Support/Conduit',
'/Users/*/Library/Internet Plug-Ins/ConduitNPAPIPlugin.plugin',
'/Users/*/Library/Internet Plug-Ins/TroviNPAPIPlugin.plugin',
'/Users/*/Library/Application Support/Firefox/searchplugins/MyBrand.xml',
'/Users/*/Library/Application Support/Firefox/searchplugins/conduit.xml',
'/Users/*/Library/Application Support/Firefox/searchplugins/"Conduit Customized Web Search".xml',
'/Users/*/Library/Application Support/Firefox/takeOverNewTab.txt',
'/Users/*/Library/Application Support/Firefox/abstraction.js',
'/Users/*/Library/Caches/com.Conduit.takeOverSearchAssetsMac',

#Downlite
'/Library/Application Support/VSearch',
'/Library/LaunchAgents/com.vsearch.agent.plist',
'/Library/LaunchDaemons/com.vsearch.daemon.plist',
'/Library/LaunchDaemons/com.vsearch.helper.plist',
'/Library/LaunchDaemons/Jack.plist',
'/Library/PrivilegedHelperTools/Jack',
'/System/Library/Frameworks/VSearch.framework',
'/System/Library/Frameworks/v.framework',

#SearchProtect
'/Applications/SearchProtect/Data',
'/Applications/SearchProtect/SearchProtect.app',
'/Applications/SearchProtect/Uninstaller.app',
'/Applications/SearchProtect/takeOverSearchAssetsMac.app', 

#GoPhoto
'/Users/*/Library/Application Support/Google/Chrome/External Extensions/ccfjbdjailljfihgkoccfbiljjapiijb.json',

#Genieo
'/Users/*/Library/LaunchAgents/com.genieo.completer.download.plist',
'/Users/*/Library/LaunchAgents/com.genieo.completer.update.plist',
'/Users/*/Library/LaunchAgents/com.genieo.completer.ltvbit.plist',
'/Library/LaunchAgents/com.genieoinnovation.macextension.plist',
'/Library/LaunchAgents/com.genieoinnovation.macextension.client.plist',
'/Library/LaunchAgents/com.genieo.engine.plist',
'/Library/LaunchAgents/com.genieo.completer.update.plist',
'/Library/LaunchDaemons/com.genieoinnovation.macextension.client.plist',
'/Applications/Genieo',
'/Applications/Genieo.app',
'/Applications/InstallMac',
'/Applications/InstallMac.app',
'/Applications/InstallGenieo',
'/Applications/InstallGenieo.app',
'/Applications/Reset Search',
'/Applications/Reset Search.app',
'/Applications/Uninstall Genieo',
'/Applications/Uninstall Genieo.app',
'/Applications/Uninstall IM Completer',
'/Applications/Uninstall IM Completer.app',
'/Users/*/Library/Application Support/com.genieoinnovation.Installer',
'/Users/*/Library/Application Support/Genieo',
'/Library/PrivilegedHelperTools/com.genieoinnovation.macextension.client',
'/Library/Frameworks/GenieoExtra.framework',
'/Users/*/Library/Application Support/Firefox/searchplugins/my-homepage.xml',
'/Users/*/Library/Application Support/Genieo/',
'/Users/*/Library/Application Support/com.genieoinnovation.Installer/',
'/Users/*/Library/Preferences/com.genieo.global.settings.plist.lockfile',
'/Users/*/Library/Preferences/com.geneio.settings.plist.lockfile',
'/Users/*/Library/Preferences/com.geneio.global.settings.plist',
'/Users/*/Library/Saved Application State/com.genieo.RemoveGenieoMac.savedState',
'/Users/*/Library/Preferences/com.genieo.settings.plist',
'/private/etc/launchd.conf',
'/usr/lib/libgenkit.dylib',
'/usr/lib/libgenkitsa.dylib',
'/usr/lib/libimckit.dylib',
'/usr/lib/libimckitsa.dylib',

#Vidx/MacVX
'/Applications/Vidx.app',
'/Library/Safari/Extensions/extension.safariextz',

#Best Youtube Downloader
'/Users/*/Library/LaunchAgents/com.moeppfdpoohhdcaefbfpmabjipnohiif.updater.plist',
'/Users/*/Library/Application Support/Google/Chrome/External Extensions/phpdijfdkggndfmgcfdhcimlflflnega.json',
'/Users/*/Library/LaunchAgents/Safari Security',
'/Users/*/Library/LaunchAgents/WebSocketServerApp',
'/Users/*/Library/LaunchAgents/com.webtools.update.agent.plist',
'/Users/*/Library/Application Support/webHelperApp/',
'/Users/*/Library/WebTools/',

#PremierOpinion
'/Applications/PremierOpinion',
'/Library/LaunchDaemons/PremierOpinion.plist',

}

found_malware = {match for filename in known_malware for match in
glob.glob(filename)}

settings_files = {
'/Users//Library/Application Support/Google/Chrome/Default/Preferences',
'/Users/
/Library/Application Support/Firefox/user.js',
'/Users/*/Library/Application Support/Firefox/prefs.js',

}

active_settings = {match for filename in settings_files for match in
glob.glob(filename)}

Look for "ProjectX" variants.

This adware seems to have a different name each time it pops up.

Apple's solution is too broad. We look at the files Apple suggests,

but then also search within to see if they are calling a known

binary file, "agent.app/Contents/MacOS/agent".

projectx_files = {
'/Library/LaunchAgents/com..agent.plist',
'/Library/LaunchDaemons/com.
.helper.plist',
'/Library/LaunchDaemons/com.*.daemon.plist',
}

projectx_candidates = {match for filename in projectx_files for match in
glob.glob(filename)}

agent_regex = re.compile('./Library/Application Support/(.)/Agent/agent.app/Contents/MacOS/agent')
for candidate in projectx_candidates:
with open(candidate, 'r') as candidate_file:
launchd_job = candidate_file.read()

if re.search(agent_regex, launchd_job):
    found_malware.add(candidate)
    # If we find a Launch[Agent|Daemon] that has ProgramArguments
    # which runs "agent", find the unique name for this instance.
    # We can then use it to find the Application Support folder.
    obfuscated_name = re.search(agent_regex, launchd_job).group(1)
    found_malware.add('/Library/Application Support/%s' % obfuscated_name)

Is this an EA or a script execution (Casper scripts always have 3

args, so we can't just use the first argument.

if len(sys.argv) == 1:
# Extension attribute (First arg is always script name).
result = ''
if found_malware:
result += 'True\n'
for item in enumerate(found_malware):
result += "%d: %s\n" % item
else:
result += 'False'

print('%s</result>' % result)

elif "--remove" in sys.argv:
# Removal script.
syslog.syslog(syslog.LOG_ALERT, "Looking for malware")
for item in found_malware:
try:
if os.path.isdir(item):
shutil.rmtree(item)
elif os.path.isfile(item):
os.remove(item)
syslog.syslog(syslog.LOG_ALERT, "Removed malware file: %s" % item)
except OSError as e:
syslog.syslog(syslog.LOG_ALERT,
"Failed to remove malware file: %s, %s" % (item, e))

syslog.syslog(syslog.LOG_ALERT, "Looking for settings files")                     
for item in active_settings:
    try:
        if os.path.isdir(item):
            shutil.rmtree(item)
        elif os.path.isfile(item):
            os.remove(item)
        syslog.syslog(syslog.LOG_ALERT, "Removed setting file file:  %s" % item)
    except OSError as e:
        syslog.syslog(syslog.LOG_ALERT,
                      "Failed to remove settings file:  %s, %s" % (item, e))

@sheagcraig
Copy link
Author

Just for the record I want to state that the above contributions include software not considered malware or adware, but just undesirable to admins in an enterprise environment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment