def start(self): if not self.do_run: return try: self.executable.append(self.file_path) if isinstance(self.pre_script_args_list, list): for args in self.pre_script_args_list: self.executable.append(args) else: self.executable.append(self.pre_script_args_list) log.info("Pre_script command: %s", " ".join(self.executable)) p = subprocess.check_output(self.executable, timeout=self.timeout, stderr=subprocess.STDOUT) nf = NetlogFile() nf.init("logs/pre_script.log") nf.sock.send(p) nf.close() log.info( "Successfully ran pre_script, saved output to logs/pre_script.logs" ) return True except subprocess.CalledProcessError as e: log.error("Error, return code: %s", e.returncode) log.error("Error, Process stdout: %s", e.output) except Exception as e: log.error("Error running pre_script due to error: %s", e) return False
def start(self): if not self.do_run: return try: nf = NetlogFile() nf.init("logs/during_script.log") self.executable.append(self.file_path) if isinstance(self.during_script_args_list, list): for args in self.during_script_args_list: self.executable.append(args) else: self.executable.append(self.during_script_args_list) log.info("During_script command: %s", " ".join(self.executable)) popen = subprocess.Popen(self.executable, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) for stdout_line in iter(popen.stdout.readline, ""): nf.sock.send(stdout_line.encode()) popen.stdout.close() nf.close() return_code = popen.wait() log.info( "Running during_script, saved output to logs/during_script.logs" ) if return_code: log.error("Process stderr: %s", popen.stderr) raise subprocess.CalledProcessError(return_code, str(self.executable)) except Exception as e: log.error("Error running during_script due to error: %s", e) return False return True
def test_netlogfile_init(p): nf = NetlogFile() nf.init(u"dump-\u202e.exe") nf.sock = None nf.init(u"dump-\u202e.exe", u"file-\u202e.exe") a, b = p.return_value.sendall.call_args_list assert a[0][0] == str(a[0][0]) assert b[0][0] == str(b[0][0])
def dump_memory_block(self, addr, length): """Dump process memory. @return: operation status. """ if not self.pid: log.warning("No valid pid specified, memory dump aborted") return False if not self.is_alive(): log.warning("The process with pid %d is not alive, memory " "dump aborted", self.pid) return False self.get_system_info() page_size = self.system_info.dwPageSize if length < page_size: length = page_size # Now upload to host from the StringIO. idx = self.dumpmem[self.pid] = self.dumpmem.get(self.pid, 0) + 1 file_name = os.path.join("memory", "block-%s-%s-%s.dmp" % (self.pid, hex(addr), idx)) process_handle = self.open_process() mbi = MEMORY_BASIC_INFORMATION() if KERNEL32.VirtualQueryEx(process_handle, addr, byref(mbi), sizeof(mbi)) == 0: log.warning("Couldn't obtain MEM_BASIC_INFO for pid %d address %s", self.pid, hex(addr)) return False # override request with the full mem region attributes addr = mbi.BaseAddress length = mbi.RegionSize count = c_ulong(0) try: buf = create_string_buffer(length) if KERNEL32.ReadProcessMemory(process_handle, addr, buf, length, byref(count)): header = struct.pack("QIIII", addr, length, mbi.State, mbi.Type, mbi.Protect) nf = NetlogFile() nf.init(file_name) nf.sock.sendall(header) nf.sock.sendall(buf.raw) nf.close() else: log.warning("ReadProcessMemory failed on process_handle %r addr %s length %s", process_handle, hex(addr), hex(length)) except: log.exception("ReadProcessMemory exception on process_handle %r addr %s length %s", process_handle, hex(addr), hex(length)) KERNEL32.CloseHandle(process_handle) log.info("Memory block dump of process with pid %d, addr %s, length %s completed", self.pid, hex(addr), hex(length)) return True
def run(self): """Run capturing of usage info. @return: operation status. """ meminfo = MEMORYSTATUSEX() meminfo.dwLength = sizeof(MEMORYSTATUSEX) phquery = PVOID() PDH.PdhOpenQuery(None, None, byref(phquery)) buflen = DWORD() buflen.value = 0 PDH.PdhExpandWildCardPathA(None, "\\Processor(*)\\% Processor Time", None, byref(buflen), 0) buf = create_string_buffer(buflen.value + 1) PDH.PdhExpandWildCardPathA(None, "\\Processor(*)\\% Processor Time", buf, byref(buflen), 0) counters = buf.raw.rstrip(b"\x00").split(b"\x00") counter_handles = [] for counter in counters: if b"_Total" in counter: continue phcounter = PVOID() PDH.PdhAddCounterA(phquery, counter, None, byref(phcounter)) counter_handles.append(phcounter) nf = NetlogFile() nf.init("aux/usage.log") PDH.PdhCollectQueryData(phquery) while self.do_run: time.sleep(2) PDH.PdhCollectQueryData(phquery) usage = PDH_FMT_COUNTERVALUE() bigfloat = 0.0 for counter_handle in counter_handles: PDH.PdhGetFormattedCounterValue(counter_handle, PDH_FMT_DOUBLE, None, byref(usage)) if usage.doubleValue > bigfloat: bigfloat = usage.doubleValue KERNEL32.GlobalMemoryStatusEx(byref(meminfo)) usagedata = b"%d %d\n" % (meminfo.dwMemoryLoad, round(bigfloat)) nf.send(usagedata) for counter_handle in counter_handles: PDH.PdhRemoveCounter(counter_handle) PDH.PdhCloseQuery(phquery) nf.close() return True
def run(self): """Run screenshotting. @return: operation status. """ if "screenshots" in self.options: self.do_run = int(self.options["screenshots"]) scr = Screenshot() # TODO We should also send the action "pillow" so that the Web # Interface can adequately inform the user about this missing library. if not scr.have_pil(): log.info( "Python Image Library (either PIL or Pillow) is not " "installed, screenshots are disabled." ) return False img_counter = 0 img_last = None while self.do_run: time.sleep(SHOT_DELAY) try: img_current = scr.take() except IOError as e: log.error("Cannot take screenshot: %s", e) continue if img_last and scr.equal(img_last, img_current, SKIP_AREA): continue img_counter += 1 # workaround as PIL can't write to the socket file object :( tmpio = StringIO.StringIO() img_current.save(tmpio, format="JPEG") tmpio.seek(0) # now upload to host from the StringIO nf = NetlogFile() nf.init("shots/%04d.jpg" % img_counter) for chunk in tmpio: nf.sock.sendall(chunk) nf.close() img_last = img_current return True
def stop(self): """Stop screenrecording""" # Stop the video self.src.stop() # TODO: taking video based on events try: with open(self.src.file, "rb") as f: nf = NetlogFile() nf.init("screenrecord/%s" % self.src.fname) nf.sock.sendall(f.read()) nf.close() except Exception as e: log.debug("Screenrecord bug: %s", e)
def run(self): """Run screenshotting. @return: operation status. """ if "screenshots" in self.options: shot_delay = int(self.options["screenshots"]) if shot_delay == 0: self.do_run = False else: shot_delay = 1 if not Screenshot().have_pil(): log.warning("Python Image Library is not installed, " "screenshots are disabled") return False img_counter = 0 img_last = None while self.do_run: time.sleep(shot_delay) try: img_current = Screenshot().take() except IOError as e: log.error("Cannot take screenshot: %s", e) continue if img_last: if Screenshot().equal(img_last, img_current, SKIP_AREA): continue img_counter += 1 # workaround as PIL can't write to the socket file object :( tmpio = StringIO.StringIO() img_current.save(tmpio, format="JPEG") tmpio.seek(0) # now upload to host from the StringIO nf = NetlogFile() nf.init("shots/%s.jpg" % str(img_counter).rjust(4, "0")) for chunk in tmpio: nf.sock.sendall(chunk) nf.close() img_last = img_current return True
def stop(self): log.info("Collecting EMET events...") c = wmi.WMI(privileges=['Security']) for event in c._raw_query('SELECT * FROM Win32_NTLogEvent'): if event.SourceName == "EMET": #https://msdn.microsoft.com/en-us/library/aa394226(v=vs.85).aspx maybe add more values? dadada.append([event.SourceName, event.Category, event.Type, event.ComputerName, event.User, event.Message]) bleekscheet = "\n".join(str(x) for x in dadada) nf = NetlogFile() nf.init("logs/emet_events.log") nf.send(bleekscheet) nf.close() return True
def run(self): """Run screenshotting. @return: operation status. """ if not self.enabled: return False if not Screenshot().have_pil(): log.warning( "Python Image Library is not installed, screenshots are disabled" ) return False img_counter = 0 img_last = None while self.do_run: time.sleep(SHOT_DELAY) try: img_current = Screenshot().take() except IOError as e: log.error("Cannot take screenshot: %s", e) continue if img_last: if Screenshot().equal(img_last, img_current, SKIP_AREA): continue img_counter += 1 # workaround as PIL can't write to the socket file object :( tmpio = BytesIO() img_current.save(tmpio, format="JPEG") tmpio.seek(0) # now upload to host from the StringIO nf = NetlogFile() nf.init(f"shots/{str(img_counter).rjust(4, '0')}.jpg") for chunk in tmpio: nf.sock.send(chunk) nf.close() img_last = img_current return True
def start(self): if not self.enabled: return True try: if self.config.category != "file": log.debug("Skipping authenticode validation, analysis is not " "a file.") return True sign_path = os.path.join(os.getcwd(), "bin", "signtool.exe") if not os.path.exists(sign_path): log.info("Skipping authenticode validation, signtool.exe was " "not found in bin/") return True log.debug("Checking for a digitial signature.") file_path = os.path.join(os.environ["TEMP"] + os.sep, str(self.config.file_name)) cmd = '{0} verify /pa /v "{1}"'.format(sign_path, file_path) ret, out, err = util.cmd_wrapper(cmd) out = out.decode(locale.getpreferredencoding(), errors="ignore") # Return was 0, authenticode certificate validated successfully if not ret: _ = self.parse_digisig(out) self.jsonify("Certificate Chain", self.cert_build) self.jsonify("Timestamp Chain", self.time_build) self.json_data["valid"] = True log.debug("File has a valid signature.") # Non-zero return, it didn't validate or exist else: self.json_data["error"] = True errmsg = b" ".join(b"".join(err.split(b":")[1:]).split()) self.json_data["error_desc"] = errmsg.decode("utf-8") if b"file format cannot be verified" in err: log.debug("File format not recognized.") elif b"No signature found" not in err: log.debug("File has an invalid signature.") _ = self.parse_digisig(out) self.jsonify("Certificate Chain", self.cert_build) self.jsonify("Timestamp Chain", self.time_build) else: log.debug("File is not signed.") if self.json_data: log.info("Uploading signature results to aux/{0}.json".format( self.__class__.__name__)) upload = BytesIO() upload.write(json.dumps(self.json_data, ensure_ascii=False).encode("utf-8")) upload.seek(0) nf = NetlogFile() nf.init("aux/DigiSig.json") for chunk in upload: nf.sock.send(chunk) nf.close() except Exception as e: print(e) import traceback log.exception(traceback.format_exc()) return True
def dump_memory_block(self, addr, length): """Dump process memory. @return: operation status. """ if not self.pid: log.warning("No valid pid specified, memory dump aborted") return False if not self.is_alive(): log.warning( "The process with pid %d is not alive, memory " "dump aborted", self.pid) return False self.get_system_info() page_size = self.system_info.dwPageSize if length < page_size: length = page_size # Now upload to host from the StringIO. idx = self.dumpmem[self.pid] = self.dumpmem.get(self.pid, 0) + 1 file_name = os.path.join( "memory", "block-%s-%s-%s.dmp" % (self.pid, hex(addr), idx)) process_handle = self.open_process() mbi = MEMORY_BASIC_INFORMATION() if KERNEL32.VirtualQueryEx(process_handle, addr, byref(mbi), sizeof(mbi)) == 0: log.warning("Couldn't obtain MEM_BASIC_INFO for pid %d address %s", self.pid, hex(addr)) return False # override request with the full mem region attributes addr = mbi.BaseAddress length = mbi.RegionSize count = c_ulong(0) try: buf = create_string_buffer(length) if KERNEL32.ReadProcessMemory(process_handle, addr, buf, length, byref(count)): header = struct.pack("QIIII", addr, length, mbi.State, mbi.Type, mbi.Protect) nf = NetlogFile() nf.init(file_name) nf.sock.sendall(header) nf.sock.sendall(buf.raw) nf.close() else: log.warning( "ReadProcessMemory failed on process_handle %r addr %s length %s", process_handle, hex(addr), hex(length)) except: log.exception( "ReadProcessMemory exception on process_handle %r addr %s length %s", process_handle, hex(addr), hex(length)) KERNEL32.CloseHandle(process_handle) log.info( "Memory block dump of process with pid %d, addr %s, length %s completed", self.pid, hex(addr), hex(length)) return True