def check_startup_time(response): if common.is_linux(): boot_time = lib.get_boot_time() if boot_time: if len(boot_time) == 4: response["startup_time"] = { "name": [ Klanguage().to_ts(1808), Klanguage().to_ts(1809), Klanguage().to_ts(1810), Klanguage().to_ts(1811) ], "time": [0, boot_time[0], boot_time[1], boot_time[3]], "icon": [0, 1, 2, 3] } return if len(boot_time) == 3: response["startup_time"] = { "name": [ Klanguage().to_ts(1808), Klanguage().to_ts(1809), Klanguage().to_ts(1811) ], "time": [0, boot_time[0], boot_time[2]], "icon": [0, 1, 3] } return
def __init__(self): if common.is_linux(): envret = setenv() if envret == False: raise Exception( "Can not set important environment!Maybe use XWayland.") if common.is_x86_64(): misc_path = "lib/linux/x64/misc.so" else: misc_path = "lib/linux/x86/misc.so" self._lib = CDLL(os.path.join(common.get_work_dir(), misc_path)) elif common.is_windows(): self._lib = CDLL( os.path.join(common.get_work_dir(), "lib/windows/misc.dll")) else: raise Exception("Not support on macos") ret = self._lib.GlobalInit() if ret != 0: raise Exception("MiscGlobalInitFailed") self._buffer = create_string_buffer(4194304)
def run(payload, socket): if common.is_linux(): vuls = Kdatabase().get_obj("vuls") while True: if Kevent().is_terminate(): print("vulscan thread terminate") break now = time_op.now() settings = Kdatabase().get_obj('strategy') if settings: if now > vuls["lasttime"] + settings["vuls"]["period"]: with Kvuls().get_lock(): Kvuls().vulscan() vuls["lasttime"] = now if settings["vuls"]["auto_repair"]: if common.is_program_running( "apt-get") or common.is_program_running( "yum"): pass else: if lib.check_root(): for package in list(vuls["items"]): Kvuls().repair(package) Kdatabase().dump("vuls") time.sleep(5)
def runQuickScan(self): root_paths = [] if common.is_linux(): root_paths = [("/root", True), ('/bin', True), ('/sbin', True), ('/usr/bin', True), ('/usr/local/bin', True)] if common.is_darwin(): root_paths.append(('/users', True)) else: root_paths.append(('/home', True)) if common.is_windows(): # root_paths = [('D:\\test\\木马\\',True)] root = os.getenv('systemroot')[:1] root_paths = [(root + ':\\users', True)] # root_paths = [ (root+":\\Documents and Settings", True), # (root+":\\windows", False), # (root+":\\windows\\system32", True), # (root+":\\windows\\syswow64\\system32", True), # (root+":\\program files", True), # (root+":\\Program Files (x86)", True)] self.avoid_list.append((root + ':\\$Recycle.Bin').lower()) self.runVirusScan(root_paths)
def initAll(): global main_proc common.set_work_dir() dprint('[Init Info] work dir set') if common.is_linux(): start_python_main() waiting_proc_exit = False next_update_time = int(time.time()) + 30 while True: if not main_proc.is_alive(): dprint("[Init Info] marsnake terminated") break if not waiting_proc_exit and int(time.time()) > next_update_time: try: if check_and_update(): main_proc.terminate() waiting_proc_exit = True continue next_update_time = int( time.time()) + 60 * 60 * 3 # wait for 3 hour except Exception as e: dprint("[Init Error]", str(e)) time.sleep(10)
def check_kdump_config(response): if common.is_linux(): kdump_cmdline = "/proc/cmdline" crashkernel = "" if os.path.exists(kdump_cmdline): data = file_op.cat(kdump_cmdline, "r") if data: crashkernel, num = common.grep(data, r"crashkernel=(\S+)") #enable if crashkernel: kdump_conf = "/etc/kdump.conf" if os.path.exists(kdump_conf): data = file_op.cat(kdump_conf, "r") if data: lines = data.split("\n") values = [["Key", "Value"], ["Reserved memory", crashkernel]] keys = [ "Store the dump to a remote machine using the NFS protocol,", "Local directory in which the core dump is to be saved", "Write dump to storage devices", "Write the dump directly to a device", "Core collector to compress the data", "Action to perform in case dumping fails", "Store the dump to a remote machine using the SSH protocol", "SSH Key" ] patterns = [ re.compile(r"nfs\s(\S+)"), re.compile(r"path\s(\S+)"), re.compile(r"ext4\s(\S+)"), re.compile(r"raw\s(\S+)"), re.compile(r"core_collector\s(\S+).*"), re.compile(r"default\s(\S+)"), re.compile(r"ssh\s(\S+)"), re.compile(r"sshkey\s(\S+)") ] for line in lines: for i in range(len(patterns)): match = patterns[i].match(line) if match and len(match.groups()): values.append([keys[i], match.groups()[0]]) response["kernel"].append({ "name": "Kernel Dump Configuration", "value": len(values) - 1, "values": values })
def __init__(self, file_created_captured, file_modified_captured): if common.is_windows(): from . import fs_change_win as fs_change_proxy elif common.is_linux(): from . import fs_change_linux as fs_change_proxy else: raise "No support os " + __NAME__ self.name = "Filesystem monitor" self.proxy = fs_change_proxy self.file_created_captured = file_created_captured self.file_modified_captured = file_modified_captured
def __init__(self, usb_plugged, usb_unplugged): if common.is_windows(): from . import usb_detect_win as usb_detect_proxy elif common.is_linux(): from . import usb_detect_linux as usb_detect_proxy else: raise "No support os " + __NAME__ self.name = "USB detector" self.proxy = usb_detect_proxy self.usb_plugged = usb_plugged self.usb_unplugged = usb_unplugged
def run(payload, socket): if common.is_linux(): data = { "kernel": [], "authentication": [], "feature": [], } audit = Kdatabase().get_obj('audit') while True: if Kevent().is_terminate(): print("security audit thread terminate") break # reset data data['kernel'] = [] data['authentication'] = [] data['feature'] = [] data['statistic'] = {"critical": 0, "warning": 0} now = time_op.now() if now > audit["lasttime"] + constant.AUDIT_SCAN_PERIOD: #check_upgradable_packages(data) audit_implement.kernel_available_version(data) audit_implement.enum_kernel_modules(data) audit_implement.check_magickey_configuration(data) audit_implement.check_need_reboot(data) audit_implement.check_coredump_config(data) #check_kdump_config(data) #kernel_default_limits(data) audit_implement.security_info(data) audit_implement.get_useradd_list(data) audit_implement.logged_user(data) audit_implement.check_sudoers_file(data) audit_implement.login_defs_policy(data) audit['feature'] = data['feature'] audit['authentication'] = data['authentication'] audit['kernel'] = data['kernel'] audit['statistic'] = data['statistic'] audit["lasttime"] = now Kdatabase().dump('audit') time.sleep(5)
def load_jsons(self): apps_path = os.path.join(self.json_path, "apps.json") if not os.path.exists(apps_path): Klogger().debug("apps.json does not exist") raise Exception try: with open(apps_path, "r") as f: raw_apps_list = json.load(f) except Exception as e: Klogger().debug("read apps.json fails with %s" % (str(e))) raise for each in raw_apps_list: if (not 'id' in each or not 'label' in each or not 'description' in each or not 'icon' in each): Klogger().debug("Corrupted item in apps.json") continue if 'os' in each: if each['os'] == "windows": if not common.is_windows(): continue elif each['os'] == "linux": if not common.is_linux(): continue else: Klogger().debug("Unknown os in apps.json, id %s" % (each['id'])) continue item = { "label": each['label'], "description": each['description'], "icon": each['icon'] } if 'running' in each: item['running'] = each['running'] self.apps_list[each['id']] = item for pathname in self.json_files: try: item = clean_item(os.path.join(self.json_path, pathname)) except Exception as e: Klogger().warn('error reading item: %s %s', pathname, e) continue self.kinds[item.id] = item
def check_coredump_config(response): if common.is_linux(): dumpable = "/proc/sys/fs/suid_dumpable" config = {"0": "Default", "1": "Debug", "2": "Protected"} if os.path.exists(dumpable): data = file_op.cat(dumpable, "r") if data and data in config: response["kernel"].append({ "name": "Core dump mode", "value": config[data] })
def __init__(self, ssh_login_failed, ssh_login_success, remote_ip_detect, backdoor_detect): self.name = "Period" if common.is_linux(): self.ssh_lasttime_scan = time_op.now() self.backdoor_lasttime_scan = time_op.now() self.ssh_login_failed = ssh_login_failed self.ssh_login_success = ssh_login_success self.backdoor_detect = backdoor_detect self.ip_lasttime_scan = time_op.now() self.remote_ip_detect = remote_ip_detect self.ip_detected = []
def runDeepScan(self): root_paths = [] if common.is_linux() or common.is_darwin(): root_paths.append(("/", True)) self.avoid_list = ['/proc', '/dev', '/sys'] if common.is_windows(): for item in psutil.disk_partitions(): device, mountpoint, fstype, opts = item if fstype: root_paths.append((mountpoint, True)) self.avoid_list.append( os.path.join(mountpoint, '$Recycle.Bin').lower()) self.runVirusScan(root_paths)
def parse_apache2_conf(apconf_path): web_paths = [] if common.is_linux() and os.path.exists(apconf_path): for root, dirs, files in os.walk(apconf_path): for file in files: with open(os.path.join(root, file), "r") as f: data_all = f.read() #DocumentRoot "/var/www/html" match = re.search(r'DocumentRoot "(\S+)"', data_all) if match and len(match.groups()): web_paths.append(match.groups()[0]) return web_paths
def get_arp_caches(response): values = [] interfaces = psutil.net_if_addrs() for name, addrs in interfaces.items(): for addr in addrs: if addr[0] == 2 and addr[1] != '127.0.0.1': #cidr = sum([bin(int(x)).count("1") for x in addr[2].split(".")]) #netmask = (2 ** cidr - 1) << (32 - cidr) netmask = struct.unpack(">I", socket.inet_aton(addr[2]))[0] num = 0xFFFFFFFF - netmask ip = struct.unpack(">I", socket.inet_aton(addr[1]))[0] start_ip = ip & netmask for i in range(num): target = start_ip + i if target == ip: continue arp_force(target) if common.is_linux(): with open('/proc/net/arp') as arpt: for line in arpt.readlines(): if "IP address" in line or "Flags" in line: continue (ip, hw, flags, mac, mask, dev) = line.split() if flags == hex(2): values.append([ip, hw, flags, mac, mask, dev]) values = sorted( values, key=lambda t: struct.unpack(">I", socket.inet_aton(t[0]))[0]) values.insert( 0, ["IP address", "HW type", "Flags", "HW address", "Mask", "Device"]) response["network"].append({ "name": "ARP Table", "value": len(values) - 1, "values": values })
def do(self): while (True): now = time_op.now() if common.is_linux(): if now >= self.ssh_lasttime_scan + macro.PERIOD_SSH_SCAN: self.ssh_detect() self.ssh_lasttime_scan = now if now >= self.backdoor_lasttime_scan + macro.PERIOD_BACKDOOR_SCAN: self.malicious_backdoor_detect() self.backdoor_lasttime_scan = now if now >= self.ip_lasttime_scan + macro.PERIOD_IP_SCAN: self.malicious_ip_detect() self.ip_lasttime_scan = now time.sleep(10)
def on_file_modified_captured(self, pathname): if os.path.exists(pathname) and common.is_linux(): import magic with magic.Magic() as m: kind = m.id_filename(pathname) if kind: pattern = re.compile(r"^(ELF|PE)\S+") m = pattern.search(kind) if m is None: return else: return result = KCybertek().detect_file_sha256(pathname) if result: KUEBA_event().on_malware_detect(pathname, result)
def parse_nginx_conf(ngconf_path): web_paths = [] try: import nginxparser except Exception: pass else: if common.is_linux() and os.path.exists(ngconf_path): for root, dirs, files in os.walk(ngconf_path): for f in files: confs = nginxparser.load(open(os.path.join(root, f))) for conf in confs: for setting in conf[1]: if setting[0] == 'root': web_paths.append(setting[1]) return web_paths
def new_terminal(self, session_id, socket): command = "cmd" if common.is_linux(): command = "bash" if self.pty: self.terminate() Klogger().info( "Terminate old terminal for session {}".format(session_id)) term = terminal(shell_command=[command]).new_one() self.pty = { "terminal": term, "future": self.executor.submit(terminal_reading, term, socket, session_id) } Klogger().info("Create new terminal for session {}".format(session_id))
def op_service(name, op, response): if common.is_linux(): if common.check_programs_installed("systemctl"): #data, success, retcode = common.exec_command(['systemctl', 'is-enabled', name]) if op == 0: data, success, retcode = common.exec_command(['systemctl', 'enable', name, "--no-ask-password"]) if success: response["status"] = "enabled" else: response["error"] = "{} code : {}".format(data, retcode) else: data, success, retcode = common.exec_command(['systemctl', 'disable', name, "--no-ask-password"]) if success: response["status"] = "disabled" else: response["error"] = "{} code : {}".format(data, retcode) else: response["error"] = Klanguage().to_ts(4003)
def do(self, target_risk_id): if common.is_linux(): self.login_defs_policy(target_risk_id) self.check_sudoers_file(target_risk_id)
from core.cleaner import Kcleaner from core.vuls import Kvuls from core import security_audit_implement from utils import common, import_helper #import pcapy if common.is_linux(): import module.basic.overview if common.is_windows(): import module.basic.overview_win import wmi import win32timezone import win32file import login if common.is_darwin(): import module.basic.overview_mac import module.basic.heartbeat import module.basic.set_language import module.basic.get_info import module.basic.system_status import module.status.resource import module.hardening.vulscan import module.hardening.boot_services import module.terminal.new_pty import module.terminal.write_pty import module.terminal.resize_pty import module.terminal.kill_pty import module.vnc.init_vnc
def enum_process_by_users(): process_by_user = {} # use monitor_second directly may be dangerous since there is no lock monitor_second = Kdatabase().get_monitor_second().copy() for proc in psutil.process_iter(): try: if common.is_kernel_thread(proc): continue pid = proc.pid if pid in monitor_second["procs"]: saved_proc = monitor_second["procs"][pid] username = saved_proc["username"] name = saved_proc["name"] cpu = saved_proc["data"][0] memory = saved_proc["data"][1] threads = saved_proc["thread"] fds = saved_proc["fd"] delta = int(time.time()) - saved_proc["beginat"] delta = delta if delta > 0 else 1 io_read = saved_proc["io_rb"] io_write = saved_proc["io_wb"] status = saved_proc["status"] with proc.oneshot(): try: memory = proc.memory_percent() except: pass try: threads = proc.num_threads() if common.is_linux(): fds = proc.num_fds() elif common.is_windows(): fds = proc.num_handles() except: pass try: if "start_record" in monitor_second and monitor_second["start_record"]: _delta = int(time.time()) - int(monitor_second["start_record"].timestamp()) if _delta <= 0: _delta = 1 _io = proc.io_counters() _io_read = _io[2] _io_write = _io[3] delta = _delta io_read = _io_read - saved_proc["io_rb"] io_write = _io_write - saved_proc["io_wb"] except: pass try: status = proc.status() except: pass else: username = "******" name = "unknown" cpu = 0.0 memory = 0.0 threads = 0 fds = 0 delta = 1 io_read = 0.0 io_write = 0.0 status = "unknown" with proc.oneshot(): try: username = proc.username() status = proc.status() except: continue try: cmdline = proc.cmdline() exe = proc.exe() if exe: cmdline[0] = exe name = " ".join(cmdline[:3]) except: try: name = proc.name() except: continue try: memory = proc.memory_percent() except: pass try: threads = proc.num_threads() if common.is_linux(): fds = proc.num_fds() elif common.is_windows(): fds = proc.num_handles() except: pass try: _delta = int(time.time()) - int(proc.create_time()) if _delta <= 0: _delta = 1 _io = proc.io_counters() _io_read = _io[2] _io_write = _io[3] delta = _delta io_read = _io_read io_write = _io_write except: pass if not username in process_by_user: process_by_user[username] = { "username": username, "cpu": 0.0, "memory": 0.0, "fds": 0, "threads": 0, "disk_io": { "read": 0.0, "write": 0.0 }, "process": [] } process_by_user[username]["cpu"] += cpu process_by_user[username]["memory"] += memory process_by_user[username]["fds"] += fds process_by_user[username]["threads"] += threads process_by_user[username]["disk_io"]["read"] += io_read / delta process_by_user[username]["disk_io"]["write"] += io_write / delta process_by_user[username]["process"].append({ "pid": pid, "name": name, "cpu": round(cpu, 2), "memory": round(memory, 2), "threads": threads, "fds": fds, "disk_io": { "read": round((io_read / delta), 2), "write": round((io_write / delta), 2) }, "status": status }) except Exception as e: pass for each in process_by_user.values(): each["cpu"] = round(each["cpu"], 2) each["memory"] = round(each["memory"], 2) each["disk_io"]["read"] = round(each["disk_io"]["read"], 2) each["disk_io"]["write"] = round(each["disk_io"]["write"], 2) return process_by_user
def record_account(self): fingerprint = Kdatabase().get_obj("fingerprint") if common.is_linux(): import pwd pwall_users = pwd.getpwall()
def list_process_by_users(): process_by_users = enum_process_by_users() if common.is_linux(): result = [] useradd_users = lib.find_useradd_users() import pwd pwall_users = [ x[0] for x in pwd.getpwall() ] users = [ x for x in useradd_users if x in pwall_users ] if "root" in process_by_users: users.insert(0, "root") for user in users: if user in process_by_users: result.append(process_by_users[user]) del process_by_users[user] if not process_by_users: return result non_useradd_users = { "username": "******", "cpu": 0.0, "memory": 0.0, "fds": 0, "threads": 0, "disk_io": { "read": 0.0, "write": 0.0 }, "process": [] } for each in process_by_users.values(): non_useradd_users["cpu"] += each["cpu"] non_useradd_users["memory"] += each["memory"] non_useradd_users["fds"] += each["fds"] non_useradd_users["threads"] += each["threads"] non_useradd_users["disk_io"]["read"] += each["disk_io"]["read"] non_useradd_users["disk_io"]["write"] += each["disk_io"]["write"] non_useradd_users["process"] += each["process"] non_useradd_users["cpu"] = round(non_useradd_users["cpu"], 2) non_useradd_users["memory"] = round(non_useradd_users["memory"], 2) non_useradd_users["disk_io"]["read"] = round(non_useradd_users["disk_io"]["read"], 2) non_useradd_users["disk_io"]["write"] = round(non_useradd_users["disk_io"]["write"], 2) result.append(non_useradd_users) return result elif common.is_windows(): for each in process_by_users.values(): if '\\' in each["username"]: each["username"] = each["username"].split("\\")[1] return list(process_by_users.values()) else: return list(process_by_users.values())
def do(self, target_risk_id): if common.is_linux(): self.security_info(target_risk_id)
def run(payload, socket): monitor = Kdatabase().get_obj("monitor") monitor_second = Kdatabase().get_monitor_second() monitor_warnings = { "cpu": { "start_time": 0, "end_time": 0, "percent": 0.0, "percent_count": 0, "db": None }, "memory": { "start_time": 0, "end_time": 0, "percent": 0.0, "percent_count": 0, "db": None } } counters_ts = 0 while True: if Kevent().is_terminate(): print("resource thread terminate") break if not counters_ts: psutil.cpu_percent() disk_counters = psutil.disk_io_counters() net_counters = psutil.net_io_counters() counters_ts = datetime.now() time.sleep(1) continue #update counters now = datetime.now() interval = (now - counters_ts).total_seconds() counters_ts = now if interval > 15.0: Kdatabase().reset_monitor_second() monitor_second = Kdatabase().get_monitor_second() counters_ts = 0 continue #calculate net = psutil.net_io_counters() tx_bytes = (net.bytes_sent - net_counters.bytes_sent) / interval rx_bytes = (net.bytes_recv - net_counters.bytes_recv) / interval net_counters = net disk = psutil.disk_io_counters() dru = (disk.read_bytes - disk_counters.read_bytes) / interval dwu = (disk.write_bytes - disk_counters.write_bytes) / interval disk_counters = disk monitor_second["cpu"].append(psutil.cpu_percent()) monitor_second["memory"].append(psutil.virtual_memory()[2]) monitor_second["net_io"]["tx"].append(tx_bytes) monitor_second["net_io"]["rx"].append(rx_bytes) monitor_second["disk_io"]["read"].append(dru) monitor_second["disk_io"]["write"].append(dwu) if not "start_record" in monitor_second or not monitor_second["start_record"]: monitor_second["start_record"] = now for proc in psutil.process_iter(): try: proc.cpu_percent() except: pass if now > monitor_second["start_record"] + timedelta(seconds = RECORD_INTERVAL): procs = {} for proc in psutil.process_iter(): try: if common.is_kernel_thread(proc): continue pid = proc.pid username = "******" status = "unknown" beginat = int(time.time()) name = "unknown" proc_read_bytes = 0 proc_write_bytes = 0 cpu_percent = 0.0 memory_percent = 0.0 thread_num = 0 fds_num = 0 with proc.oneshot(): try: username = proc.username() status = proc.status() beginat = int(proc.create_time()) except: continue try: cmdline = proc.cmdline() exe = proc.exe() if exe: cmdline[0] = exe name = " ".join(cmdline[:3]) except: try: name = proc.name() except: continue try: io = proc.io_counters() proc_read_bytes = io[2] proc_write_bytes = io[3] except: pass try: cpu_percent = proc.cpu_percent() memory_percent = proc.memory_percent() except: pass try: thread_num = proc.num_threads() if common.is_linux(): fds_num = proc.num_fds() elif common.is_windows(): fds_num = proc.num_handles() except: pass procs[pid] = { "name" : name, "username" : username, "io_rb": proc_read_bytes, "io_wb": proc_write_bytes, "beginat" : beginat, "status" : status, "fd" : fds_num, "thread" : thread_num, "data" : (cpu_percent, memory_percent) } except Exception as e: #print("pid : {} name : {} error : {}".format(pid, name, str(e))) pass upgrade_proc_status(monitor_second, monitor, procs, monitor_warnings) monitor_second["start_record"] = monitor_second["start_record"] + timedelta(seconds = RECORD_INTERVAL) if len(monitor_second["cpu"]) > 120: pop_status(monitor_second) if interval >= 1: sleep = 1 - (interval - 1) if sleep < 0: sleep = 1 else: sleep = 1 time.sleep(sleep)
def cpu_status(response): virtualization = "None" cpu_mhz = 0 num_threads = 0 num_process = 0 num_fds = 0 if os.path.exists("/proc/cpuinfo"): with open("/proc/cpuinfo") as f: data = f.readlines() for line in data: _tmp = line.split(":") if len(_tmp) != 2: continue item, value = (_tmp[0].strip(), _tmp[1].strip()) if item == "cpu MHz": try: cpu_mhz = int(float(value)) except: pass elif item == "flags": if "vmx" in value: virtualization = "Intel VT-x" if "svm" in value: virtualization = "AMD-V" for proc in psutil.process_iter(): try: num_threads += proc.num_threads() if common.is_linux(): num_fds += proc.num_fds() elif common.is_windows(): num_fds += proc.num_handles() except Exception as e: pass num_process += 1 #cache = cpu_cache() freq = psutil.cpu_freq() freq = [cpu_mhz, 0, cpu_mhz] if (not freq or len(freq) < 3) else freq response["cpu"].append([Klanguage().to_ts(1505), "{}%".format(psutil.cpu_percent(interval = 0.2))]) response["cpu"].append([Klanguage().to_ts(1511), num_process]) response["cpu"].append([Klanguage().to_ts(1508), psutil.cpu_count(logical = False)]) response["cpu"].append([Klanguage().to_ts(1514), "{} Mhz".format(freq[0])]) response["cpu"].append([Klanguage().to_ts(1506), virtualization]) response["cpu"].append([Klanguage().to_ts(1509), num_threads]) response["cpu"].append([Klanguage().to_ts(1512), psutil.cpu_count(logical = True)]) response["cpu"].append([Klanguage().to_ts(1515), "{} Mhz".format(freq[1])]) response["cpu"].append([Klanguage().to_ts(1507), sys.byteorder]) response["cpu"].append([Klanguage().to_ts(1510), num_fds]) response["cpu"].append([Klanguage().to_ts(1513), str(datetime.now() - datetime.fromtimestamp(psutil.boot_time())).split(".")[0]]) response["cpu"].append([Klanguage().to_ts(1516), "{} Mhz".format(freq[2])])