def _upload_file(local, remote): if os.path.exists(local): nf = NetlogFile(remote) with open(local, "rb") as f: for chunk in f: nf.sock.sendall(chunk) # dirty direct send, no reconnecting nf.close()
def run(self): """Run screenshotting. @return: operation status. """ img_counter = 0 img_last = None while self.do_run: time.sleep(SHOT_DELAY) try: filename = "screenshot%s.jpg" % str(img_counter) img_current = take_screenshot(filename) if img_last: if Screenshot().equal(img_last, img_current): continue file = open(img_current, 'r') tmpio = StringIO.StringIO(file.read()) # now upload to host from the StringIO nf = NetlogFile("shots/%s.jpg" % str(img_counter).rjust(4, "0")) for chunk in tmpio: nf.sock.sendall(chunk) nf.close() file.close() img_counter += 1 img_last = img_current except IOError as e: log.error("Cannot take screenshot: %s", e) continue return True
def _upload_file(local, remote): if path.exists(local): nf = NetlogFile(remote) with open(local, "rb") as f: for chunk in f: nf.sock.sendall(chunk) # dirty direct send, no reconnecting nf.close()
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) # Return was 0, authenticode certificate validated successfully out = out.decode(locale.getpreferredencoding(), errors="ignore") if not ret: output = 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 = " ".join("".join(err.split(":")[1:]).split()) self.json_data["error_desc"] = errmsg if "file format cannot be verified" in err: log.debug("File format not recognized.") elif "No signature found" not in err: log.debug("File has an invalid signature.") output = 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 = StringIO() upload.write(json.dumps(self.json_data)) upload.seek(0) nf = NetlogFile("aux/{0}.json".format(self.__class__.__name__)) for chunk in upload: nf.sock.sendall(chunk) nf.close() except Exception: import traceback log.exception(traceback.format_exc()) 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) # Return was 0, authenticode certificate validated successfully if not ret: output = 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 = " ".join("".join(err.split(":")[1:]).split()) self.json_data["error_desc"] = errmsg if "file format cannot be verified" in err: log.debug("File format not recognized.") elif "No signature found" not in err: log.debug("File has an invalid signature.") output = 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 = StringIO() upload.write(json.dumps(self.json_data)) upload.seek(0) nf = NetlogFile("aux/{0}.json".format(self.__class__.__name__)) for chunk in upload: nf.sock.sendall(chunk) nf.close() except Exception: import traceback log.exception(traceback.format_exc()) return True
def dump_memory(self): """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 min_addr = self.system_info.lpMinimumApplicationAddress max_addr = self.system_info.lpMaximumApplicationAddress mem = min_addr root = os.path.join(PATHS["memory"], str(int(time.time()))) if not os.path.exists(root): os.makedirs(root) # Now upload to host from the StringIO. nf = NetlogFile(os.path.join("memory", "%s.dmp" % str(self.pid))) process_handle = self.open_process() while mem < max_addr: mbi = MEMORY_BASIC_INFORMATION() count = c_ulong(0) if KERNEL32.VirtualQueryEx(process_handle, mem, byref(mbi), sizeof(mbi)) < sizeof(mbi): mem += page_size continue if mbi.State & MEM_COMMIT and \ mbi.Type & (MEM_IMAGE | MEM_MAPPED | MEM_PRIVATE): buf = create_string_buffer(mbi.RegionSize) if KERNEL32.ReadProcessMemory(process_handle, mem, buf, mbi.RegionSize, byref(count)): nf.sock.sendall(buf.raw) mem += mbi.RegionSize else: mem += page_size KERNEL32.CloseHandle(process_handle) nf.close() log.info("Memory dump of process with pid %d completed", self.pid) return True
def finish(self): log.info("starting to send data") data = self.m.get_logs() log.info("size of log: {}".format(len(data))) nc = NetlogFile("files/proxyLog.log") log.info("netlog initiated") nc.send(data, retry=True) log.info("netlog sent") return True
def dump_memory(self): """Dump process memory. @return: operation status. """ if self.pid == 0: 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 min_addr = self.system_info.lpMinimumApplicationAddress max_addr = self.system_info.lpMaximumApplicationAddress mem = min_addr root = os.path.join(PATHS["memory"], str(int(time()))) if not os.path.exists(root): os.makedirs(root) # now upload to host from the StringIO nf = NetlogFile("memory/%s.dmp" % str(self.pid)) while(mem < max_addr): mbi = MEMORY_BASIC_INFORMATION() count = c_ulong(0) if KERNEL32.VirtualQueryEx(self.h_process, mem, byref(mbi), sizeof(mbi)) < sizeof(mbi): mem += page_size continue if mbi.State == 0x1000 and mbi.Type == 0x20000: buf = create_string_buffer(mbi.RegionSize) if KERNEL32.ReadProcessMemory(self.h_process, mem, buf, mbi.RegionSize, byref(count)): nf.sock.sendall(buf.raw) mem += mbi.RegionSize else: mem += page_size nf.close() log.info("Memory dump of process with pid %d completed" % self.pid) 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
def _upload_file(local, remote): if os.path.exists(local): nf = NetlogFile(remote) with open(local, "rb") as f: for chunk in f: nf.sock.sendall( chunk) # dirty direct send, no reconnecting nf.close() else: log.info("No program.log found")
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(b"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.sock.sendall(usagedata) for counter_handle in counter_handles: PDH.PdhRemoveCounter(counter_handle) PDH.PdhCloseQuery(phquery) nf.close() return True
def upload(self, out_file, remote_file): filename = os.path.join(self.output_dir, out_file) while not os.path.exists(filename): time.sleep(2) file = open(filename, "r") tmpio = StringIO.StringIO(file.read()) nf = NetlogFile("logs/%s" % remote_file) for chunk in tmpio: nf.sock.sendall(chunk) nf.close() file.close()
def dump_memory(self): """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 bin_name = "" bit_str = "" file_path = os.path.join(PATHS["memory"], "{0}.dmp".format(self.pid)) if self.is_64bit(): orig_bin_name = LOADER64_NAME bit_str = "64-bit" else: orig_bin_name = LOADER32_NAME bit_str = "32-bit" bin_name = os.path.join(os.getcwd(), orig_bin_name) if os.path.exists(bin_name): ret = subprocess.call([bin_name, "dump", str(self.pid), file_path]) if ret == 1: log.info("Dumped %s process with pid %d", bit_str, self.pid) else: log.error("Unable to dump %s process with pid %d, error: %d", bit_str, self.pid, ret) return False else: log.error( "Please place the %s binary from cuckoomon into analyzer/windows/bin in order to analyze %s binaries.", os.path.basename(bin_name), bit_str) return False nf = NetlogFile(os.path.join("memory", "{0}.dmp".format(self.pid))) infd = open(file_path, "rb") buf = infd.read(1024 * 1024) try: while buf: nf.send(buf, retry=True) buf = infd.read(1024 * 1024) except: infd.close() nf.close() log.warning("Memory dump of process with pid %d failed", self.pid) return False infd.close() nf.close() log.info("Memory dump of process with pid %d completed", self.pid) return True
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): # i guess we don't need to unload at all #os.system("rmmod probelkm") # now upload the logfile nf = NetlogFile("logs/all.lkm") fd = open("/var/log/kern.log") for line in fd: if not "[probelkm]" in line: continue nf.sock.sendall(line) # dirty direct send, no reconnecting fd.close() nf.close()
def upload_memdump(self): """Upload process memory dump. @return: operation status. """ if not self.pid: log.warning( "No valid pid specified, memory dump cannot be uploaded") return False bin_name = "" bit_str = "" file_path = os.path.join(PATHS["memory"], "{0}.dmp".format(self.pid)) nf = NetlogFile(os.path.join("memory", "{0}.dmp".format(self.pid))) infd = open(file_path, "rb") buf = infd.read(1024 * 1024) try: while buf: nf.send(buf, retry=True) buf = infd.read(1024 * 1024) except: infd.close() nf.close() log.warning("Upload of memory dump for process %d failed", self.pid) return False infd.close() nf.close() log.info("Memory dump of process %d uploaded", self.pid) 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("\x00").split("\x00") counter_handles = [] for counter in counters: if "_Total" in counter: continue phcounter = PVOID() PDH.PdhAddCounterA(phquery, counter, None, byref(phcounter)) counter_handles.append(phcounter) nf = NetlogFile("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 = "%d %d\n" % (meminfo.dwMemoryLoad, round(bigfloat)) nf.sock.sendall(usagedata) for counter_handle in counter_handles: PDH.PdhRemoveCounter(counter_handle) PDH.PdhCloseQuery(phquery) nf.close() return True
def stop(self): try: self.proc.kill() except Exception as e: log.warning("Exception killing stap: %s", e) if os.path.exists("stap.log"): # now upload the logfile nf = NetlogFile("logs/all.stap") fd = open("stap.log", "rb") for chunk in fd: nf.sock.sendall(chunk) # dirty direct send, no reconnecting fd.close() nf.close() # in case we fell back to strace if os.path.exists("strace"): for fn in os.listdir("strace"): # we don't need the logs from the analyzer python process itself if fn == "straced.%u" % os.getpid(): continue fp = os.path.join("strace", fn) # now upload the logfile nf = NetlogFile("logs/%s" % fn) fd = open(fp, "rb") for chunk in fd: nf.sock.sendall( chunk) # dirty direct send, no reconnecting fd.close() nf.close()
def dump_memory(self): """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 bin_name = "" bit_str = "" file_path = os.path.join(PATHS["memory"], "{0}.dmp".format(self.pid)) if self.is_64bit(): bin_name = "bin/loader_x64.exe" bit_str = "64-bit" else: bin_name = "bin/loader.exe" bit_str = "32-bit" if os.path.exists(bin_name): ret = subprocess.call([bin_name, "dump", str(self.pid), file_path]) if ret == 1: log.info("Dumped %s process with pid %d", bit_str, self.pid) else: log.error("Unable to dump %s process with pid %d, error: %d", bit_str, self.pid, ret) return False else: log.error("Please place the %s binary from cuckoomon into analyzer/windows/bin in order to analyze %s binaries.", os.path.basename(bin_name), bit_str) return False nf = NetlogFile(os.path.join("memory", "{0}.dmp".format(self.pid))) infd = open(file_path, "rb") buf = infd.read(1024*1024) try: while buf: nf.send(buf, retry=False) buf = infd.read(1024*1024) nf.close() except: log.warning("Memory dump of process with pid %d failed", self.pid) return False log.info("Memory dump of process with pid %d completed", self.pid) return True
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("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 run(self): """Run screenshotting. @return: operation status. """ 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): continue img_counter += 1 #send a return keystroke for installers self.sendKey(0x24) try: # workaround as PIL can't write to the socket file object :( tmpio = StringIO.StringIO() img_current.save(tmpio, format="PNG") tmpio.seek(0) except: log.exception("Unable to write screenshot to disk.") # now upload to host from the StringIO nf = NetlogFile("shots/%s.png" % str(img_counter).rjust(4, "0")) for chunk in tmpio: nf.sock.sendall(chunk) nf.close() img_last = img_current return True
def dump_memory(self): """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 if self.is32bit(pid=self.pid): inject_exe = os.path.join("bin", "inject-x86.exe") else: inject_exe = os.path.join("bin", "inject-x64.exe") # Take the memory dump. dump_path = tempfile.mktemp() try: args = [ inject_exe, "--pid", "%s" % self.pid, "--dump", dump_path, ] subprocess.check_call(args) except subprocess.CalledProcessError: log.error("Failed to dump memory of %d-bit process with pid %d.", 32 if self.is32bit(pid=self.pid) else 64, self.pid) return # Calculate the next index. We keep in mind that one process may have # multiple process memory dumps in the future. idx = self.dumpmem[self.pid] = self.dumpmem.get(self.pid, 0) + 1 nf = NetlogFile(os.path.join("memory", "%s-%s.dmp" % (self.pid, idx))) # Send the dumped file. with open(dump_path, "rb") as f: nf.sock.sendall(f.read(1024 * 1024)) nf.close() os.unlink(dump_path) log.info("Memory dump of process with pid %d completed", self.pid) 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 finish(self): # in case we fell back to strace if os.path.exists("strace"): for fn in os.listdir("strace"): # we don't need the logs from the analyzer python process itself if fn == "straced.%u" % os.getpid(): continue fp = os.path.join("strace", fn) # now upload the logfile nf = NetlogFile("logs/%s" % fn) fd = open(fp, "rb") for chunk in fd: nf.sock.sendall( chunk) # dirty direct send, no reconnecting fd.close() nf.close()
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 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 stop(self): try: self.proc.kill() except Exception as e: log.warning("Exception killing stap: %s", e) if os.path.exists("stap.log"): # now upload the logfile nf = NetlogFile("logs/all.stap") fd = open("stap.log", "rb") for chunk in fd: nf.sock.sendall(chunk) # dirty direct send, no reconnecting fd.close() nf.close() # in case we fell back to strace if os.path.exists("strace"): for fn in os.listdir("strace"): # we don't need the logs from the analyzer python process itself if fn == "straced.%u" % os.getpid(): continue fp = os.path.join("strace", fn) # now upload the logfile nf = NetlogFile("logs/%s" % fn) fd = open(fp, "rb") for chunk in fd: nf.sock.sendall(chunk) # dirty direct send, no reconnecting fd.close() nf.close()
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 the screen shots. :return: bool """ img_count = 0 while self.capture: file_name = '/var/tmp/image{0}.jpg'.format(img_count) os.system('screencapture -x -t jpg {0}'.format(file_name)) img_count += 1 # Upload the images as we go here try: if not self.imgdiff(file_name): nf = NetlogFile('shots/{0}'.format(file_name)) nf.close() except: pass # Clean things up the temp dir so we don't fill the disk on long running processes os.remove(file_name) time.sleep(self.sleeptime) return True
def stop(self): all_running = [] proc = subprocess.Popen(self.cmd, shell=True, stdout=subprocess.PIPE) processes = proc.stdout.read().split("\r\r\n\r\r\n") for p in processes: p = p.strip() parts = p.split("\r\r\n") proc_dict = {} for kv_pair in parts: try: kv = kv_pair.split('=') proc_dict[kv[0]] = kv[1] all_running.append(proc_dict) except: continue proc.terminate() nf = NetlogFile("logs/running_processes.log") nf.sock.sendall(json.dumps(all_running)) nf.close()
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 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 finish(self): data = self.m.get_logs() nc = NetlogFile("files/proxyLog.log") nc.send(data, retry=True) return True
def send_file(name,data): """Send file to result server""" nf = NetlogFile(name) nf.sock.sendall(data) nf.close()
def start(self): if not self.enabled: return False 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 digital signature") file_path = os.path.join(os.environ["TEMP"] + os.sep, str(self.config.file_name)) cmd = f'{sign_path} verify /pa /v "{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(err.split(b":", 1)[1].split()) self.json_data["error_desc"] = errmsg.decode() 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/%s.json", self.__class__.__name__) upload = BytesIO() upload.write( json.dumps(self.json_data, ensure_ascii=False).encode()) 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
def send_file(name, data): """Send file to result server""" nf = NetlogFile(name) nf.sock.sendall(data) nf.close()