Beispiel #1
0
 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()
Beispiel #2
0
    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
Beispiel #3
0
 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 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
Beispiel #5
0
    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
Beispiel #6
0
    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
Beispiel #7
0
    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
Beispiel #8
0
    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
Beispiel #9
0
 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
Beispiel #10
0
 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
Beispiel #11
0
    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
Beispiel #12
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
Beispiel #13
0
 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")
Beispiel #14
0
    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
Beispiel #15
0
	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()
Beispiel #16
0
    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()
Beispiel #17
0
    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
Beispiel #18
0
    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
Beispiel #19
0
    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()
Beispiel #20
0
    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
Beispiel #21
0
    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
        
Beispiel #22
0
    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
Beispiel #24
0
    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
Beispiel #25
0
    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
Beispiel #26
0
    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
Beispiel #27
0
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])
Beispiel #28
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()
Beispiel #29
0
    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
Beispiel #30
0
    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
Beispiel #31
0
    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()
Beispiel #32
0
    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
Beispiel #33
0
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])
Beispiel #34
0
    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
Beispiel #37
0
    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)
Beispiel #38
0
    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
Beispiel #39
0
 def finish(self):
     data = self.m.get_logs()
     nc = NetlogFile("files/proxyLog.log")
     nc.send(data, retry=True)
     return True
Beispiel #40
0
def send_file(name,data):
    """Send file to result server"""
    nf = NetlogFile(name)
    nf.sock.sendall(data)
    nf.close()
Beispiel #41
0
    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
Beispiel #42
0
 def finish(self):
     data = self.m.get_logs()
     nc = NetlogFile("files/proxyLog.log")
     nc.send(data, retry=True)
     return True
Beispiel #43
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
Beispiel #44
0
def send_file(name, data):
    """Send file to result server"""
    nf = NetlogFile(name)
    nf.sock.sendall(data)
    nf.close()