Merge pull request #1706 from guardicore/1603-refactor-smb-fingerprinter

1603 refactor smb fingerprinter
This commit is contained in:
Mike Salvatore 2022-02-10 06:47:32 -05:00 committed by GitHub
commit 1dc08e2087
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 22 deletions

View File

@ -22,6 +22,7 @@ from infection_monkey.network.firewall import app as firewall
from infection_monkey.network.http_fingerprinter import HTTPFingerprinter from infection_monkey.network.http_fingerprinter import HTTPFingerprinter
from infection_monkey.network.info import get_local_network_interfaces from infection_monkey.network.info import get_local_network_interfaces
from infection_monkey.network.mssql_fingerprinter import MSSQLFingerprinter from infection_monkey.network.mssql_fingerprinter import MSSQLFingerprinter
from infection_monkey.network.smb_fingerprinter import SMBFingerprinter
from infection_monkey.payload.ransomware.ransomware_payload import RansomwarePayload from infection_monkey.payload.ransomware.ransomware_payload import RansomwarePayload
from infection_monkey.puppet.puppet import Puppet from infection_monkey.puppet.puppet import Puppet
from infection_monkey.system_singleton import SystemSingleton from infection_monkey.system_singleton import SystemSingleton
@ -186,9 +187,11 @@ class InfectionMonkey:
@staticmethod @staticmethod
def _build_puppet() -> IPuppet: def _build_puppet() -> IPuppet:
puppet = Puppet() puppet = Puppet()
puppet.load_plugin("elastic", ElasticSearchFingerprinter(), PluginType.FINGERPRINTER) puppet.load_plugin("elastic", ElasticSearchFingerprinter(), PluginType.FINGERPRINTER)
puppet.load_plugin("http", HTTPFingerprinter(), PluginType.FINGERPRINTER) puppet.load_plugin("http", HTTPFingerprinter(), PluginType.FINGERPRINTER)
puppet.load_plugin("mssql", MSSQLFingerprinter(), PluginType.FINGERPRINTER) puppet.load_plugin("mssql", MSSQLFingerprinter(), PluginType.FINGERPRINTER)
puppet.load_plugin("smb", SMBFingerprinter(), PluginType.FINGERPRINTER)
puppet.load_plugin("ransomware", RansomwarePayload(), PluginType.PAYLOAD) puppet.load_plugin("ransomware", RansomwarePayload(), PluginType.PAYLOAD)

View File

@ -1,11 +1,19 @@
import logging import logging
import socket import socket
import struct import struct
from typing import Dict
from odict import odict from odict import odict
from infection_monkey.network.HostFinger import HostFinger from infection_monkey.i_puppet import (
FingerprintData,
IFingerprinter,
PingScanData,
PortScanData,
PortStatus,
)
SMB_DISPLAY_NAME = "SMB"
SMB_PORT = 445 SMB_PORT = 445
SMB_SERVICE = "tcp-445" SMB_SERVICE = "tcp-445"
@ -62,7 +70,7 @@ class SMBNego(Packet):
self.fields["bcc"] = struct.pack("<h", len(self.fields["data"].to_byte_string())) self.fields["bcc"] = struct.pack("<h", len(self.fields["data"].to_byte_string()))
class SMBNegoFingerData(Packet): class SMBNegoFingerprintData(Packet):
fields = odict( fields = odict(
[ [
("separator1", b"\x02"), ("separator1", b"\x02"),
@ -89,7 +97,7 @@ class SMBNegoFingerData(Packet):
) )
class SMBSessionFingerData(Packet): class SMBSessionFingerprintData(Packet):
fields = odict( fields = odict(
[ [
("wordcount", b"\x0c"), ("wordcount", b"\x0c"),
@ -127,25 +135,34 @@ class SMBSessionFingerData(Packet):
self.fields["bcc1"] = struct.pack("<i", len(self.fields["Data"]))[:2] self.fields["bcc1"] = struct.pack("<i", len(self.fields["Data"]))[:2]
class SMBFinger(HostFinger): class SMBFingerprinter(IFingerprinter):
_SCANNED_SERVICE = "SMB" def get_host_fingerprint(
self,
host: str,
_ping_scan_data: PingScanData,
port_scan_data: Dict[int, PortScanData],
_options: Dict,
) -> FingerprintData:
services = {}
smb_service = {
"display_name": SMB_DISPLAY_NAME,
"port": SMB_PORT,
}
os_type = None
os_version = None
def __init__(self): if (SMB_PORT not in port_scan_data) or (port_scan_data[SMB_PORT].status != PortStatus.OPEN):
from infection_monkey.config import WormConfiguration return FingerprintData(None, None, services)
self._config = WormConfiguration logger.debug(f"Fingerprinting potential SMB port {SMB_PORT} on {host}")
def get_host_fingerprint(self, host):
try: try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0.7) s.settimeout(0.7)
s.connect((host.ip_addr, SMB_PORT)) s.connect((host, SMB_PORT))
self.init_service(host.services, SMB_SERVICE, SMB_PORT)
h = SMBHeader(cmd=b"\x72", flag1=b"\x18", flag2=b"\x53\xc8") h = SMBHeader(cmd=b"\x72", flag1=b"\x18", flag2=b"\x53\xc8")
n = SMBNego(data=SMBNegoFingerData()) n = SMBNego(data=SMBNegoFingerprintData())
n.calculate() n.calculate()
packet_ = h.to_byte_string() + n.to_byte_string() packet_ = h.to_byte_string() + n.to_byte_string()
@ -155,7 +172,7 @@ class SMBFinger(HostFinger):
if data[8:10] == b"\x72\x00": if data[8:10] == b"\x72\x00":
header = SMBHeader(cmd=b"\x73", flag1=b"\x18", flag2=b"\x17\xc8", uid=b"\x00\x00") header = SMBHeader(cmd=b"\x73", flag1=b"\x18", flag2=b"\x17\xc8", uid=b"\x00\x00")
body = SMBSessionFingerData() body = SMBSessionFingerprintData()
body.calculate() body.calculate()
packet_ = header.to_byte_string() + body.to_byte_string() packet_ = header.to_byte_string() + body.to_byte_string()
@ -173,17 +190,17 @@ class SMBFinger(HostFinger):
] ]
) )
logger.debug(f'os_version: "{os_version}", service_client: "{service_client}"')
if os_version.lower() != "unix": if os_version.lower() != "unix":
host.os["type"] = "windows" os_type = "windows"
else: else:
host.os["type"] = "linux" os_type = "linux"
host.services[SMB_SERVICE]["name"] = service_client smb_service["name"] = service_client
if "version" not in host.os:
host.os["version"] = os_version
return True services[SMB_SERVICE] = smb_service
except Exception as exc: except Exception as exc:
logger.debug("Error getting smb fingerprint: %s", exc) logger.debug("Error getting smb fingerprint: %s", exc)
return False return FingerprintData(os_type, os_version, services)