forked from p15670423/monkey
add support for simple fingerprinting by: ping, smb, ssh and open ports
This commit is contained in:
parent
bea2d5e3d4
commit
7697f5fce9
|
@ -3,19 +3,84 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import ntpath
|
import ntpath
|
||||||
from network.range import ClassCRange, RelativeRange, FixedRange
|
from network.range import ClassCRange, RelativeRange, FixedRange
|
||||||
from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter
|
from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter
|
||||||
from network import TcpScanner, PingScanner
|
from network import TcpScanner, PingScanner, SMBFinger, SSHFinger
|
||||||
|
from abc import ABCMeta
|
||||||
|
import uuid
|
||||||
|
import types
|
||||||
__author__ = 'itamar'
|
__author__ = 'itamar'
|
||||||
|
|
||||||
class WormConfiguration(object):
|
GUID = str(uuid.getnode())
|
||||||
|
|
||||||
|
EXTERNAL_CONFIG_FILE = os.path.join(os.path.dirname(sys.argv[0]), 'monkey.bin')
|
||||||
|
|
||||||
|
def _cast_by_example(value, example):
|
||||||
|
example_type = type(example)
|
||||||
|
if example_type is str:
|
||||||
|
return str(os.path.expandvars(value))
|
||||||
|
elif example_type is tuple and len(example) != 0:
|
||||||
|
return tuple([_cast_by_example(x, example[0]) for x in value])
|
||||||
|
elif example_type is list and len(example) != 0:
|
||||||
|
return [_cast_by_example(x, example[0]) for x in value]
|
||||||
|
elif example_type is type(value):
|
||||||
|
return value
|
||||||
|
elif example_type is bool:
|
||||||
|
return value.lower() == 'true'
|
||||||
|
elif example_type is int:
|
||||||
|
return int(value)
|
||||||
|
elif example_type is float:
|
||||||
|
return float(value)
|
||||||
|
elif example_type is types.ClassType or example_type is ABCMeta:
|
||||||
|
return globals()[value]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
class Configuration(object):
|
||||||
|
|
||||||
|
def from_dict(self, data):
|
||||||
|
for key,value in data.items():
|
||||||
|
if key.startswith('_'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
default_value = getattr(Configuration, key)
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
setattr(self, key, _cast_by_example(value, default_value))
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
result = {}
|
||||||
|
for key in dir(Configuration):
|
||||||
|
if key.startswith('_'):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
value = getattr(self, key)
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
val_type = type(value)
|
||||||
|
|
||||||
|
if val_type is types.FunctionType or val_type is types.MethodType:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if val_type is types.ClassType or val_type is ABCMeta:
|
||||||
|
value = value.__name__
|
||||||
|
elif val_type is tuple or val_type is list:
|
||||||
|
if len(value) != 0 and type(value[0]) is types.ClassType or type(value[0]) is ABCMeta:
|
||||||
|
value = val_type([x.__name__ for x in value])
|
||||||
|
|
||||||
|
result[key] = value
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
### logging config
|
### logging config
|
||||||
###########################
|
###########################
|
||||||
|
|
||||||
use_file_logging = True
|
use_file_logging = True
|
||||||
dropper_log_path = os.path.expandvars("%temp%\~df1562.tmp")
|
dropper_log_path = os.path.expandvars("%temp%\~df1562.tmp") if sys.platform == "win32" else '/tmp/user-1562'
|
||||||
monkey_log_path = os.path.expandvars("%temp%\~df1563.tmp")
|
monkey_log_path = os.path.expandvars("%temp%\~df1563.tmp") if sys.platform == "win32" else '/tmp/user-1563'
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
### dropper config
|
### dropper config
|
||||||
|
@ -23,8 +88,9 @@ class WormConfiguration(object):
|
||||||
|
|
||||||
dropper_try_move_first = sys.argv[0].endswith(".exe")
|
dropper_try_move_first = sys.argv[0].endswith(".exe")
|
||||||
dropper_set_date = True
|
dropper_set_date = True
|
||||||
dropper_date_reference_path = r"\windows\system32\kernel32.dll"
|
dropper_date_reference_path = r"\windows\system32\kernel32.dll" if sys.platform == "win32" else '/bin/sh'
|
||||||
dropper_target_path = ntpath.join(r"C:\Windows", ntpath.split(sys.argv[0])[-1])
|
dropper_target_path = r"C:\Windows\monkey.exe"
|
||||||
|
dropper_target_path_linux = '/bin/monkey'
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
### monkey config
|
### monkey config
|
||||||
|
@ -39,7 +105,8 @@ class WormConfiguration(object):
|
||||||
max_iterations = 2
|
max_iterations = 2
|
||||||
|
|
||||||
scanner_class = TcpScanner
|
scanner_class = TcpScanner
|
||||||
exploiter_classes = (RdpExploiter, )
|
finger_classes = (PingScanner, SSHFinger, SMBFinger)
|
||||||
|
exploiter_classes = (SSHExploiter, SmbExploiter, WmiExploiter, RdpExploiter, Ms08_067_Exploiter)
|
||||||
|
|
||||||
# how many victims to look for in a single scan iteration
|
# how many victims to look for in a single scan iteration
|
||||||
victims_max_find = 14
|
victims_max_find = 14
|
||||||
|
@ -47,7 +114,11 @@ class WormConfiguration(object):
|
||||||
# how many victims to exploit before stopping
|
# how many victims to exploit before stopping
|
||||||
victims_max_exploit = 7
|
victims_max_exploit = 7
|
||||||
|
|
||||||
command_server = "russian-mail-brides.com"
|
current_server = ""
|
||||||
|
|
||||||
|
command_servers = ["russian-mail-brides.com:5000"]
|
||||||
|
|
||||||
|
serialize_config = True
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
### scanners config
|
### scanners config
|
||||||
|
@ -55,14 +126,15 @@ class WormConfiguration(object):
|
||||||
|
|
||||||
|
|
||||||
#range_class = RelativeRange
|
#range_class = RelativeRange
|
||||||
#range_size = 8
|
range_size = 8
|
||||||
range_class = FixedRange
|
range_class = ClassCRange
|
||||||
range_fixed = ("10.15.1.94", )
|
range_fixed = ("10.0.0.1")
|
||||||
|
|
||||||
# TCP Scanner
|
# TCP Scanner
|
||||||
tcp_target_ports = [445, 135]
|
tcp_target_ports = [22, 445, 135]
|
||||||
tcp_scan_timeout = 1000 # 1000 Milliseconds
|
tcp_scan_timeout = 1000 # 1000 Milliseconds
|
||||||
tcp_scan_interval = 200
|
tcp_scan_interval = 200
|
||||||
|
tcp_scan_get_banner = True
|
||||||
|
|
||||||
# Ping Scanner
|
# Ping Scanner
|
||||||
ping_scan_timeout = 1000
|
ping_scan_timeout = 1000
|
||||||
|
@ -80,3 +152,11 @@ class WormConfiguration(object):
|
||||||
# psexec exploiter
|
# psexec exploiter
|
||||||
psexec_user = "Administrator"
|
psexec_user = "Administrator"
|
||||||
psexec_passwords = ["Password1!", "1234", "password", "password", "12345678"]
|
psexec_passwords = ["Password1!", "1234", "password", "password", "12345678"]
|
||||||
|
|
||||||
|
#ssh exploiter
|
||||||
|
ssh_user = "root"
|
||||||
|
ssh_passwords = ["root", "toor", "1234", "12345678"]
|
||||||
|
|
||||||
|
alive = True
|
||||||
|
|
||||||
|
WormConfiguration = Configuration()
|
|
@ -1,10 +1,15 @@
|
||||||
|
|
||||||
__author__ = 'itamar'
|
__author__ = 'itamar'
|
||||||
|
|
||||||
class VictimHost(object):
|
class VictimHost(object):
|
||||||
def __init__(self, ip_addr):
|
def __init__(self, ip_addr):
|
||||||
self.ip_addr = ip_addr
|
self.ip_addr = ip_addr
|
||||||
self.cred = {}
|
self.cred = {}
|
||||||
|
self.os = {}
|
||||||
|
self.services = {}
|
||||||
|
self.monkey_exe = None
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.ip_addr)
|
return hash(self.ip_addr)
|
||||||
|
@ -28,4 +33,4 @@ class VictimHost(object):
|
||||||
self.cred[username.lower()] = password
|
self.cred[username.lower()] = password
|
||||||
|
|
||||||
def get_credentials(self, username):
|
def get_credentials(self, username):
|
||||||
return self.cred.get(username.lower(), None)
|
return self.cred.get(username.lower(), None)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
from abc import ABCMeta, abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
|
import socket
|
||||||
|
|
||||||
__author__ = 'itamar'
|
__author__ = 'itamar'
|
||||||
|
|
||||||
|
@ -10,6 +11,16 @@ class HostScanner(object):
|
||||||
def is_host_alive(self, host):
|
def is_host_alive(self, host):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
class HostFinger(object):
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_host_fingerprint(self, host):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
from ping_scanner import PingScanner
|
from ping_scanner import PingScanner
|
||||||
from tcp_scanner import TcpScanner
|
from tcp_scanner import TcpScanner
|
||||||
|
from smbfinger import SMBFinger
|
||||||
|
from sshfinger import SSHFinger
|
||||||
|
from info import local_ips
|
|
@ -1,26 +1,67 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
from network import HostScanner
|
import logging
|
||||||
|
from network import HostScanner, HostFinger
|
||||||
from model.host import VictimHost
|
from model.host import VictimHost
|
||||||
|
import re
|
||||||
|
|
||||||
__author__ = 'itamar'
|
__author__ = 'itamar'
|
||||||
|
|
||||||
PING_COUNT_FLAG = "-n" if "win32" == sys.platform else "-c"
|
PING_COUNT_FLAG = "-n" if "win32" == sys.platform else "-c"
|
||||||
PING_TIMEOUT_FLAG = "-w" if "win32" == sys.platform else "-W"
|
PING_TIMEOUT_FLAG = "-w" if "win32" == sys.platform else "-W"
|
||||||
|
TTL_REGEX_STR = '(?<=TTL\=)[0-9]+'
|
||||||
|
LINUX_TTL = 64
|
||||||
|
WINDOWS_TTL = 128
|
||||||
|
|
||||||
class PingScanner(HostScanner):
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class PingScanner(HostScanner, HostFinger):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._config = __import__('config').WormConfiguration
|
self._config = __import__('config').WormConfiguration
|
||||||
self._devnull = open(os.devnull, "w")
|
self._devnull = open(os.devnull, "w")
|
||||||
|
self._ttl_regex = re.compile(TTL_REGEX_STR, re.IGNORECASE)
|
||||||
|
|
||||||
def is_host_alive(self, host):
|
def is_host_alive(self, host):
|
||||||
assert isinstance(host, VictimHost)
|
assert isinstance(host, VictimHost)
|
||||||
|
|
||||||
|
timeout = self._config.ping_scan_timeout
|
||||||
|
if not "win32" == sys.platform:
|
||||||
|
timeout = timeout / 1000
|
||||||
|
|
||||||
return 0 == subprocess.call(["ping",
|
return 0 == subprocess.call(["ping",
|
||||||
PING_COUNT_FLAG, "1",
|
PING_COUNT_FLAG, "1",
|
||||||
PING_TIMEOUT_FLAG, str(self._config.ping_scan_timeout),
|
PING_TIMEOUT_FLAG, str(timeout),
|
||||||
host.ip_addr],
|
host.ip_addr],
|
||||||
stdout=self._devnull,
|
stdout=self._devnull,
|
||||||
stderr=self._devnull)
|
stderr=self._devnull)
|
||||||
|
|
||||||
|
def get_host_fingerprint(self, host):
|
||||||
|
assert isinstance(host, VictimHost)
|
||||||
|
|
||||||
|
timeout = self._config.ping_scan_timeout
|
||||||
|
if not "win32" == sys.platform:
|
||||||
|
timeout = timeout / 1000
|
||||||
|
|
||||||
|
sub_proc = subprocess.Popen(["ping",
|
||||||
|
PING_COUNT_FLAG,
|
||||||
|
"1",
|
||||||
|
PING_TIMEOUT_FLAG,
|
||||||
|
str(timeout), host.ip_addr],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
output = " ".join(sub_proc.communicate())
|
||||||
|
regex_result = self._ttl_regex.search(output)
|
||||||
|
if regex_result:
|
||||||
|
try:
|
||||||
|
ttl = int(regex_result.group(0))
|
||||||
|
if LINUX_TTL == ttl:
|
||||||
|
host.os['type'] = 'linux'
|
||||||
|
elif WINDOWS_TTL == ttl:
|
||||||
|
host.os['type'] = 'windows'
|
||||||
|
return True
|
||||||
|
except Exception, exc:
|
||||||
|
LOG.debug("Error parsing ping fingerprint: %s", exc)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import string
|
||||||
|
import logging
|
||||||
|
from network import HostFinger
|
||||||
|
from model.host import VictimHost
|
||||||
|
from odict import odict
|
||||||
|
import select
|
||||||
|
|
||||||
|
SMB_PORT = 445
|
||||||
|
SMB_SERVICE = 'tcp-445'
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class Packet():
|
||||||
|
fields = odict([
|
||||||
|
("data", ""),
|
||||||
|
])
|
||||||
|
def __init__(self, **kw):
|
||||||
|
self.fields = odict(self.__class__.fields)
|
||||||
|
for k,v in kw.items():
|
||||||
|
if callable(v):
|
||||||
|
self.fields[k] = v(self.fields[k])
|
||||||
|
else:
|
||||||
|
self.fields[k] = v
|
||||||
|
def __str__(self):
|
||||||
|
return "".join(map(str, self.fields.values()))
|
||||||
|
|
||||||
|
##### SMB Packets #####
|
||||||
|
class SMBHeader(Packet):
|
||||||
|
fields = odict([
|
||||||
|
("proto", "\xff\x53\x4d\x42"),
|
||||||
|
("cmd", "\x72"),
|
||||||
|
("errorcode", "\x00\x00\x00\x00"),
|
||||||
|
("flag1", "\x00"),
|
||||||
|
("flag2", "\x00\x00"),
|
||||||
|
("pidhigh", "\x00\x00"),
|
||||||
|
("signature", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("reserved", "\x00\x00"),
|
||||||
|
("tid", "\x00\x00"),
|
||||||
|
("pid", "\x00\x00"),
|
||||||
|
("uid", "\x00\x00"),
|
||||||
|
("mid", "\x00\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
class SMBNego(Packet):
|
||||||
|
fields = odict([
|
||||||
|
("wordcount", "\x00"),
|
||||||
|
("bcc", "\x62\x00"),
|
||||||
|
("data", "")
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
self.fields["bcc"] = struct.pack("<h",len(str(self.fields["data"])))
|
||||||
|
|
||||||
|
class SMBNegoFingerData(Packet):
|
||||||
|
fields = odict([
|
||||||
|
("separator1","\x02" ),
|
||||||
|
("dialect1", "\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00"),
|
||||||
|
("separator2","\x02"),
|
||||||
|
("dialect2", "\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00"),
|
||||||
|
("separator3","\x02"),
|
||||||
|
("dialect3", "\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00"),
|
||||||
|
("separator4","\x02"),
|
||||||
|
("dialect4", "\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00"),
|
||||||
|
("separator5","\x02"),
|
||||||
|
("dialect5", "\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00"),
|
||||||
|
("separator6","\x02"),
|
||||||
|
("dialect6", "\x4e\x54\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
class SMBSessionFingerData(Packet):
|
||||||
|
fields = odict([
|
||||||
|
("wordcount", "\x0c"),
|
||||||
|
("AndXCommand", "\xff"),
|
||||||
|
("reserved","\x00" ),
|
||||||
|
("andxoffset", "\x00\x00"),
|
||||||
|
("maxbuff","\x04\x11"),
|
||||||
|
("maxmpx", "\x32\x00"),
|
||||||
|
("vcnum","\x00\x00"),
|
||||||
|
("sessionkey", "\x00\x00\x00\x00"),
|
||||||
|
("securitybloblength","\x4a\x00"),
|
||||||
|
("reserved2","\x00\x00\x00\x00"),
|
||||||
|
("capabilities", "\xd4\x00\x00\xa0"),
|
||||||
|
("bcc1",""),
|
||||||
|
("Data","\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x01\x28\x0a\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x33\x00\x20\x00\x32\x00\x36\x00\x30\x00\x30\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00\x35\x00\x2e\x00\x31\x00\x00\x00\x00\x00"),
|
||||||
|
|
||||||
|
])
|
||||||
|
def calculate(self):
|
||||||
|
self.fields["bcc1"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
|
||||||
|
|
||||||
|
class SMBFinger(HostFinger):
|
||||||
|
def __init__(self):
|
||||||
|
self._config = __import__('config').WormConfiguration
|
||||||
|
|
||||||
|
def get_host_fingerprint(self, host):
|
||||||
|
assert isinstance(host, VictimHost)
|
||||||
|
|
||||||
|
try:
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.settimeout(0.7)
|
||||||
|
s.connect((host.ip_addr, SMB_PORT))
|
||||||
|
|
||||||
|
host.services[SMB_SERVICE] = {}
|
||||||
|
|
||||||
|
h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8")
|
||||||
|
n = SMBNego(data = SMBNegoFingerData())
|
||||||
|
n.calculate()
|
||||||
|
|
||||||
|
Packet = str(h)+str(n)
|
||||||
|
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||||
|
s.send(Buffer)
|
||||||
|
data = s.recv(2048)
|
||||||
|
|
||||||
|
if data[8:10] == "\x72\x00":
|
||||||
|
Header = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
|
||||||
|
Body = SMBSessionFingerData()
|
||||||
|
Body.calculate()
|
||||||
|
|
||||||
|
Packet = str(Header)+str(Body)
|
||||||
|
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
||||||
|
|
||||||
|
s.send(Buffer)
|
||||||
|
data = s.recv(2048)
|
||||||
|
|
||||||
|
if data[8:10] == "\x73\x16":
|
||||||
|
length = struct.unpack('<H',data[43:45])[0]
|
||||||
|
pack = tuple(data[47+length:].split('\x00\x00\x00'))[:2]
|
||||||
|
os_version, service_client = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]])
|
||||||
|
|
||||||
|
if os_version.lower() != 'unix':
|
||||||
|
host.os['type'] = 'windows'
|
||||||
|
else:
|
||||||
|
host.os['type'] = 'linux'
|
||||||
|
|
||||||
|
host.services[SMB_SERVICE]['name'] = service_client
|
||||||
|
if not host.os.has_key('version'):
|
||||||
|
host.os['version'] = os_version
|
||||||
|
else:
|
||||||
|
host.services[SMB_SERVICE]['os-version'] = os_version
|
||||||
|
|
||||||
|
return True
|
||||||
|
except Exception, exc:
|
||||||
|
LOG.debug("Error getting smb fingerprint: %s", exc)
|
||||||
|
|
||||||
|
return False
|
|
@ -0,0 +1,57 @@
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import string
|
||||||
|
import logging
|
||||||
|
from network import HostFinger
|
||||||
|
import socket
|
||||||
|
import select
|
||||||
|
from network.tools import check_port_tcp
|
||||||
|
from model.host import VictimHost
|
||||||
|
|
||||||
|
SSH_PORT = 22
|
||||||
|
SSH_SERVICE = 'tcp-22'
|
||||||
|
SSH_REGEX = 'SSH-\d\.\d-OpenSSH'
|
||||||
|
TIMEOUT = 30
|
||||||
|
BANNER_READ = 1024
|
||||||
|
LINUX_DIST_SSH = ['ubuntu', 'debian']
|
||||||
|
|
||||||
|
class SSHFinger(HostFinger):
|
||||||
|
def __init__(self):
|
||||||
|
self._config = __import__('config').WormConfiguration
|
||||||
|
self._banner_regex = re.compile(SSH_REGEX, re.IGNORECASE)
|
||||||
|
|
||||||
|
def _banner_match(self, host, banner):
|
||||||
|
host.services[SSH_SERVICE]['name'] = 'ssh'
|
||||||
|
for dist in LINUX_DIST_SSH:
|
||||||
|
if banner.lower().find(dist) != -1:
|
||||||
|
host.os['type'] = 'linux'
|
||||||
|
os_version = banner.split(' ').pop().strip()
|
||||||
|
if not host.os.has_key('version'):
|
||||||
|
host.os['version'] = os_version
|
||||||
|
else:
|
||||||
|
host.services[SSH_SERVICE]['os-version'] = os_version
|
||||||
|
break
|
||||||
|
|
||||||
|
def get_host_fingerprint(self, host):
|
||||||
|
assert isinstance(host, VictimHost)
|
||||||
|
|
||||||
|
for service in host.services.values():
|
||||||
|
banner = service.get('banner', '')
|
||||||
|
if self._banner_regex.search(banner):
|
||||||
|
self._banner_match(host, banner)
|
||||||
|
return
|
||||||
|
|
||||||
|
is_open, banner = check_port_tcp(host.ip_addr, SSH_PORT, TIMEOUT, True)
|
||||||
|
|
||||||
|
if is_open:
|
||||||
|
host.services[SSH_SERVICE] = {}
|
||||||
|
|
||||||
|
if banner:
|
||||||
|
host.services[SSH_SERVICE]['banner'] = banner
|
||||||
|
if self._banner_regex.search(banner):
|
||||||
|
self._banner_match(host, banner)
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
|
@ -1,29 +1,43 @@
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import socket
|
import socket
|
||||||
from network import HostScanner
|
from network import HostScanner, HostFinger
|
||||||
from model.host import VictimHost
|
from model.host import VictimHost
|
||||||
|
from network.tools import check_port_tcp
|
||||||
|
import select
|
||||||
|
|
||||||
__author__ = 'itamar'
|
__author__ = 'itamar'
|
||||||
|
|
||||||
class TcpScanner(HostScanner):
|
BANNER_READ = 1024
|
||||||
def __init__(self, target_port=None):
|
|
||||||
|
class TcpScanner(HostScanner, HostFinger):
|
||||||
|
def __init__(self):
|
||||||
self._config = __import__('config').WormConfiguration
|
self._config = __import__('config').WormConfiguration
|
||||||
|
|
||||||
def is_host_alive(self, host):
|
def is_host_alive(self, host):
|
||||||
|
return self.get_host_fingerprint(host, True)
|
||||||
|
|
||||||
|
def get_host_fingerprint(self, host, only_one_port=False):
|
||||||
assert isinstance(host, VictimHost)
|
assert isinstance(host, VictimHost)
|
||||||
|
|
||||||
for target_port in self._config.tcp_target_ports:
|
count = 0
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
||||||
sock.settimeout(self._config.tcp_scan_timeout / 1000.0)
|
|
||||||
|
|
||||||
try:
|
for target_port in self._config.tcp_target_ports:
|
||||||
sock.connect((host.ip_addr, target_port))
|
|
||||||
sock.close()
|
is_open, banner = check_port_tcp(host.ip_addr,
|
||||||
return True
|
target_port,
|
||||||
except socket.error:
|
self._config.tcp_scan_interval / 1000.0,
|
||||||
|
self._config.tcp_scan_get_banner)
|
||||||
|
|
||||||
|
if is_open:
|
||||||
|
count+=1
|
||||||
|
service = 'tcp-' + str(target_port)
|
||||||
|
host.services[service] = {}
|
||||||
|
if banner:
|
||||||
|
host.services[service]['banner'] = banner
|
||||||
|
if only_one_port:
|
||||||
|
break
|
||||||
|
else:
|
||||||
time.sleep(self._config.tcp_scan_interval / 1000.0)
|
time.sleep(self._config.tcp_scan_interval / 1000.0)
|
||||||
|
|
||||||
continue
|
return count != 0
|
||||||
|
|
||||||
return False
|
|
Loading…
Reference in New Issue