forked from p15670423/monkey
Refactored process list collector
This commit is contained in:
parent
04b7370575
commit
2286571a72
|
@ -1,3 +1,4 @@
|
|||
AWS_COLLECTOR = "AwsCollector"
|
||||
HOSTNAME_COLLECTOR = "HostnameCollector"
|
||||
ENVIRONMENT_COLLECTOR = "EnvironmentCollector"
|
||||
PROCESS_LIST_COLLECTOR = "ProcessListCollector"
|
||||
|
|
|
@ -62,44 +62,12 @@ class InfoCollector(object):
|
|||
|
||||
def get_info(self):
|
||||
# Collect all hardcoded
|
||||
self.get_process_list()
|
||||
self.get_network_info()
|
||||
self.get_azure_info()
|
||||
|
||||
# Collect all plugins
|
||||
SystemInfoCollectorsHandler().execute_all_configured()
|
||||
|
||||
def get_process_list(self):
|
||||
"""
|
||||
Adds process information from the host to the system information.
|
||||
Currently lists process name, ID, parent ID, command line
|
||||
and the full image path of each process.
|
||||
:return: None. Updates class information
|
||||
"""
|
||||
LOG.debug("Reading process list")
|
||||
processes = {}
|
||||
for process in psutil.process_iter():
|
||||
try:
|
||||
processes[process.pid] = {"name": process.name(),
|
||||
"pid": process.pid,
|
||||
"ppid": process.ppid(),
|
||||
"cmdline": " ".join(process.cmdline()),
|
||||
"full_image_path": process.exe(),
|
||||
}
|
||||
except (psutil.AccessDenied, WindowsError):
|
||||
# we may be running as non root
|
||||
# and some processes are impossible to acquire in Windows/Linux
|
||||
# in this case we'll just add what we can
|
||||
processes[process.pid] = {"name": "null",
|
||||
"pid": process.pid,
|
||||
"ppid": process.ppid(),
|
||||
"cmdline": "ACCESS DENIED",
|
||||
"full_image_path": "null",
|
||||
}
|
||||
continue
|
||||
|
||||
self.info['process_list'] = processes
|
||||
|
||||
def get_network_info(self):
|
||||
"""
|
||||
Adds network information from the host to the system information.
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import logging
|
||||
import psutil
|
||||
|
||||
from common.data.system_info_collectors_names import PROCESS_LIST_COLLECTOR
|
||||
from infection_monkey.system_info.system_info_collector import SystemInfoCollector
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Linux doesn't have WindowsError
|
||||
try:
|
||||
WindowsError
|
||||
except NameError:
|
||||
# noinspection PyShadowingBuiltins
|
||||
WindowsError = psutil.AccessDenied
|
||||
|
||||
|
||||
class ProcessListCollector(SystemInfoCollector):
|
||||
def __init__(self):
|
||||
super(ProcessListCollector, self).__init__(name=PROCESS_LIST_COLLECTOR)
|
||||
|
||||
def collect(self) -> dict:
|
||||
"""
|
||||
Adds process information from the host to the system information.
|
||||
Currently lists process name, ID, parent ID, command line
|
||||
and the full image path of each process.
|
||||
"""
|
||||
logger.debug("Reading process list")
|
||||
processes = {}
|
||||
for process in psutil.process_iter():
|
||||
try:
|
||||
processes[process.pid] = {
|
||||
"name": process.name(),
|
||||
"pid": process.pid,
|
||||
"ppid": process.ppid(),
|
||||
"cmdline": " ".join(process.cmdline()),
|
||||
"full_image_path": process.exe(),
|
||||
}
|
||||
except (psutil.AccessDenied, WindowsError):
|
||||
# we may be running as non root and some processes are impossible to acquire in Windows/Linux.
|
||||
# In this case we'll just add what we know.
|
||||
processes[process.pid] = {
|
||||
"name": "null",
|
||||
"pid": process.pid,
|
||||
"ppid": process.ppid(),
|
||||
"cmdline": "ACCESS DENIED",
|
||||
"full_image_path": "null",
|
||||
}
|
||||
continue
|
||||
|
||||
return {'process_list': processes}
|
|
@ -1,3 +1,5 @@
|
|||
from common.data.system_info_collectors_names import *
|
||||
|
||||
WARNING_SIGN = " \u26A0"
|
||||
|
||||
SCHEMA = {
|
||||
|
@ -106,7 +108,7 @@ SCHEMA = {
|
|||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"EnvironmentCollector"
|
||||
ENVIRONMENT_COLLECTOR
|
||||
],
|
||||
"title": "Collect which environment this machine is on (on prem/cloud)",
|
||||
"attack_techniques": []
|
||||
|
@ -114,7 +116,7 @@ SCHEMA = {
|
|||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"AwsCollector"
|
||||
AWS_COLLECTOR
|
||||
],
|
||||
"title": "If on AWS, collect more information about the instance",
|
||||
"attack_techniques": []
|
||||
|
@ -122,11 +124,19 @@ SCHEMA = {
|
|||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"HostnameCollector"
|
||||
HOSTNAME_COLLECTOR
|
||||
],
|
||||
"title": "Collect the machine's hostname",
|
||||
"attack_techniques": []
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
PROCESS_LIST_COLLECTOR
|
||||
],
|
||||
"title": "Collect running processes on the machine",
|
||||
"attack_techniques": []
|
||||
},
|
||||
],
|
||||
},
|
||||
"post_breach_acts": {
|
||||
|
@ -471,9 +481,10 @@ SCHEMA = {
|
|||
"$ref": "#/definitions/system_info_collectors_classes"
|
||||
},
|
||||
"default": [
|
||||
"EnvironmentCollector",
|
||||
"AwsCollector",
|
||||
"HostnameCollector"
|
||||
ENVIRONMENT_COLLECTOR,
|
||||
AWS_COLLECTOR,
|
||||
HOSTNAME_COLLECTOR,
|
||||
PROCESS_LIST_COLLECTOR
|
||||
],
|
||||
"description": "Determines which system information collectors will collect information."
|
||||
},
|
||||
|
|
|
@ -6,7 +6,6 @@ from monkey_island.cc.services.config import ConfigService
|
|||
from monkey_island.cc.services.node import NodeService
|
||||
from monkey_island.cc.services.telemetry.processing.system_info_collectors.system_info_telemetry_dispatcher import \
|
||||
SystemInfoTelemetryDispatcher
|
||||
from monkey_island.cc.services.telemetry.zero_trust_tests.antivirus_existence import test_antivirus_existence
|
||||
from monkey_island.cc.services.wmi_handler import WMIHandler
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -18,8 +17,7 @@ def process_system_info_telemetry(telemetry_json):
|
|||
process_ssh_info,
|
||||
process_credential_info,
|
||||
process_mimikatz_and_wmi_info,
|
||||
test_antivirus_existence,
|
||||
dispatcher.dispatch_to_relevant_collectors
|
||||
dispatcher.dispatch_collector_results_to_relevant_processors
|
||||
]
|
||||
|
||||
# Calling safe_process_telemetry so if one of the stages fail, we log and move on instead of failing the rest of
|
||||
|
|
|
@ -5,6 +5,7 @@ from common.data.system_info_collectors_names import *
|
|||
from monkey_island.cc.services.telemetry.processing.system_info_collectors.aws import process_aws_telemetry
|
||||
from monkey_island.cc.services.telemetry.processing.system_info_collectors.environment import process_environment_telemetry
|
||||
from monkey_island.cc.services.telemetry.processing.system_info_collectors.hostname import process_hostname_telemetry
|
||||
from monkey_island.cc.services.telemetry.zero_trust_tests.antivirus_existence import test_antivirus_existence
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -12,6 +13,7 @@ SYSTEM_INFO_COLLECTOR_TO_TELEMETRY_PROCESSORS = {
|
|||
AWS_COLLECTOR: [process_aws_telemetry],
|
||||
ENVIRONMENT_COLLECTOR: [process_environment_telemetry],
|
||||
HOSTNAME_COLLECTOR: [process_hostname_telemetry],
|
||||
PROCESS_LIST_COLLECTOR: [test_antivirus_existence]
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,9 +34,9 @@ class SystemInfoTelemetryDispatcher(object):
|
|||
:param telemetry_json: Telemetry sent from the Monkey
|
||||
"""
|
||||
if "collectors" in telemetry_json["data"]:
|
||||
self.dispatch_each_result_to_relevant_processors(telemetry_json)
|
||||
self.dispatch_single_result_to_relevant_processor(telemetry_json)
|
||||
|
||||
def dispatch_each_result_to_relevant_processors(self, telemetry_json):
|
||||
def dispatch_single_result_to_relevant_processor(self, telemetry_json):
|
||||
relevant_monkey_guid = telemetry_json['monkey_guid']
|
||||
|
||||
for collector_name, collector_results in telemetry_json["data"]["collectors"].items():
|
||||
|
|
|
@ -7,16 +7,16 @@ from monkey_island.cc.models.zero_trust.event import Event
|
|||
from monkey_island.cc.services.telemetry.zero_trust_tests.known_anti_viruses import ANTI_VIRUS_KNOWN_PROCESS_NAMES
|
||||
|
||||
|
||||
def test_antivirus_existence(telemetry_json):
|
||||
current_monkey = Monkey.get_single_monkey_by_guid(telemetry_json['monkey_guid'])
|
||||
if 'process_list' in telemetry_json['data']:
|
||||
def test_antivirus_existence(process_list_json, monkey_guid):
|
||||
current_monkey = Monkey.get_single_monkey_by_guid(monkey_guid)
|
||||
|
||||
process_list_event = Event.create_event(
|
||||
title="Process list",
|
||||
message="Monkey on {} scanned the process list".format(current_monkey.hostname),
|
||||
event_type=zero_trust_consts.EVENT_TYPE_MONKEY_LOCAL)
|
||||
events = [process_list_event]
|
||||
|
||||
av_processes = filter_av_processes(telemetry_json)
|
||||
av_processes = filter_av_processes(process_list_json["process_list"])
|
||||
|
||||
for process in av_processes:
|
||||
events.append(Event.create_event(
|
||||
|
@ -35,8 +35,8 @@ def test_antivirus_existence(telemetry_json):
|
|||
)
|
||||
|
||||
|
||||
def filter_av_processes(telemetry_json):
|
||||
all_processes = list(telemetry_json['data']['process_list'].items())
|
||||
def filter_av_processes(process_list):
|
||||
all_processes = list(process_list.items())
|
||||
av_processes = []
|
||||
for process in all_processes:
|
||||
process_name = process[1]['name']
|
||||
|
|
Loading…
Reference in New Issue