Back
Type Name Operations
__pycache__ Open
account_review Open
autosuspend Open
check_software_mods Open
cms_tools Open
domainchecker Open
etc Open
extras Open
failsuspend Open
guds_modules Open
mailers Open
mitigatord Open
mysql Open
nlp_scripts Open
oldrads Open
ops Open
perl Open
python Open
suspended Open
temporary Open
README
account-review
alp.py
autossl_runner.sh
autosusprunner.sh
backup_scan.sh
blockip
check_apache
check_autossl
check_bandwidth
check_boxtrapper
check_cpu
check_crons
check_darkmailer.py
check_dcpumon
check_dns
check_domcount.sh
check_exim
check_hacks
check_imap
check_io
check_lve
check_mailchannels_dns
check_max_children
check_mem
check_misc
check_mysql
check_pacct
check_pop3
check_raid
check_server
check_size
check_software
check_spamd
check_traffic
check_user
check_zoneh
clean_exim.py
clean_moveuser
cms_counter.py
cms_creds
cms_dumpdb
cms_pw
cmspass.py
cpanel-api
cpumon
ctrl_alt_del
dcpumon.pl
disk_cleanup.py
dns-sync
docroot.py
du-tree
envinfo.py
exclude_rbl.py
exclude_sender
extract-vhost
find_warez
findbadscripts
fixwpcron.py
forensic.py
fraudhunter.py
generate_cpmove_tix
hostsfilemods
imap_io
killall911
lastcommcache.sh
legal_lock_down.sh
lil-cpanel
limit_bots
listacct
mail_sources.py
mailscan
mass_arp_fixer.py
mass_mysql_recover.py
megaclisas-status
modify-account
modsec_disable.py
move_generator.py
msp.pl
mysql_dstat
nlp
packandgo
pastebin
postmortem
procscrape
quarantine
quick_post
radsfunctions.sh
reap_fpm_orphans.sh
recent-cp
reclaim_suspensions
remote_dump
rescp.sh
reset_cpanel
reset_email
rotate_ip_addresses.py
rrdtooldisable.sh
rrdtoolenable.sh
sadatarunner.sh
send_customer_str
send_pp_email
server-load
setmaxemails
show-conns
software_report.py
sqltop
strmailer
suspend_domain
suspend_user
temp_apache_fix
unsuspend_user
unsusprunner.sh
update_spf
upgrade-check
vhost_data.py

File Transfer

Upload files to current directory

File Editor: check_darkmailer.py

#!/usr/lib/rads/venv/bin/python3 from argparse import ArgumentParser from dataclasses import dataclass from fnmatch import fnmatch from pathlib import Path import shlex import sys import time import platform from collections.abc import Generator import pwd import psutil import rads BAD_CMDS = [ 'httpd.pl', 'bash', 'exim', 'proc', './cache.sh', './xmr', 'xargsu', 'perxg', 'mdxfs', './backupm', './dirty', './apache2', '/usr/bin/host', '/usr/sbin/acpid', './cron.php', './milemined', './annizod', './fpm-worker-main', '[stealth]', ] OKAY_CMDS = [ 'usr/local/cpanel/bin/ftpput', '/usr/local/cpanel/3rdparty/bin/awstats.pl', 'mail.cgi', ] @dataclass class Proc: cmdline: list[str] pid: int create_time: float age_secs: float username: str ppid: int cmd_str: str def iter_procs() -> Generator[Proc]: """Iterate all system processes which match check_proc, as Proc objects""" now = time.time() for psutil_proc in psutil.process_iter(): try: proc_dict = psutil_proc.as_dict( attrs=['username', 'pid', 'ppid', 'create_time', 'cmdline'] ) except psutil.NoSuchProcess: continue if not proc_dict['cmdline']: continue yield Proc( age_secs=now - proc_dict['create_time'], cmd_str=shlex.join(proc_dict['cmdline']), **proc_dict, ) def check_proc(proc: Proc) -> bool: """Use some criteria to filter to only malicious processes""" if proc.ppid == 1 or proc.username == 'root' or proc.age_secs < 300: return False if proc.cmdline[0] not in BAD_CMDS or proc.cmdline[0] in OKAY_CMDS: return False try: home = Path(pwd.getpwnam(proc.username).pw_dir) except KeyError: return True ignore_file = home / ".imh" / ".check_darkmailer.ignore" try: for line in ignore_file.read_text().splitlines(): glob = line.strip() if glob and fnmatch(proc.cmd_str, glob): return False except OSError: pass return True def main(): """Locates possible running malicious scripts""" parser = ArgumentParser() parser.add_argument( "--make-ticket", action="store_true", help="This is used by the cron; it creates an STR ticket if any " "potentially malicious scripts are found", ) make_ticket: bool = parser.parse_args().make_ticket bad_procs = filter(check_proc, iter_procs()) if not bad_procs: return 0 proc_info = [] for proc in bad_procs: proc_info.append(f"{proc.pid} {proc.username} {proc.cmd_str}") print(*proc_info, sep='\n') if not make_ticket: return 2 body = f""" {platform.node()} found {len(bad_procs)} potentially malicious scripts. {__file__} found these processes by filtering to any non-root processes older than 5 minutes and not with a parent PID of 1, then checking their names for anything that looks like it might be malicious. If there's any false positives, you can mark them in the user's home dir in ~/.imh/.check_darkmailer.ignore - each line in the file is a glob. You can test that your glob works by running {__file__} again without --make-ticket and seeing if it still lists the process. Processes: {'\n'.join(proc_info)} """ try: rads.make_ticket( dest='str@imhadmin.net', subject="Darkmailer Processes", body=body, ) except rads.TicketError as exc: print(f"Failed to create STR ticket - {exc}", file=sys.stderr) return 3 return 2 if __name__ == "__main__": sys.exit(main())