Exemplo n.º 1
0
    def inject(self, dll=None, apc=False):
        """Cuckoo DLL injection.
        @param dll: Cuckoo DLL path.
        @param apc: APC use.
        """
        if not self.pid:
            log.warning("No valid pid specified, injection aborted")
            return False

        if not self.is_alive():
            log.warning(
                "The process with pid %s is not alive, "
                "injection aborted", self.pid)
            return False

        if not dll:
            dll = "cuckoomon.dll"

        dll = randomize_dll(os.path.join("dll", dll))

        if not dll or not os.path.exists(dll):
            log.warning(
                "No valid DLL specified to be injected in process "
                "with pid %d, injection aborted.", self.pid)
            return False

        arg = KERNEL32.VirtualAllocEx(self.h_process, None,
                                      len(dll) + 1, MEM_RESERVE | MEM_COMMIT,
                                      PAGE_READWRITE)

        if not arg:
            log.error(
                "VirtualAllocEx failed when injecting process with "
                "pid %d, injection aborted (Error: %s)", self.pid,
                get_error_string(KERNEL32.GetLastError()))
            return False

        bytes_written = c_int(0)
        if not KERNEL32.WriteProcessMemory(self.h_process, arg, dll + "\x00",
                                           len(dll) + 1, byref(bytes_written)):
            log.error(
                "WriteProcessMemory failed when injecting process with "
                "pid %d, injection aborted (Error: %s)", self.pid,
                get_error_string(KERNEL32.GetLastError()))
            return False

        kernel32_handle = KERNEL32.GetModuleHandleA("kernel32.dll")
        load_library = KERNEL32.GetProcAddress(kernel32_handle, "LoadLibraryA")

        config_path = os.path.join(os.getenv("TEMP"), "%s.ini" % self.pid)
        with open(config_path, "w") as config:
            cfg = Config("analysis.conf")
            cfgoptions = cfg.get_options()

            # The first time we come up with a random startup-time.
            if Process.first_process:
                # This adds 1 up to 30 times of 20 minutes to the startup
                # time of the process, therefore bypassing anti-vm checks
                # which check whether the VM has only been up for <10 minutes.
                Process.startup_time = random.randint(1, 30) * 20 * 60 * 1000

            config.write("host-ip={0}\n".format(cfg.ip))
            config.write("host-port={0}\n".format(cfg.port))
            config.write("pipe={0}\n".format(PIPE))
            config.write("results={0}\n".format(PATHS["root"]))
            config.write("analyzer={0}\n".format(os.getcwd()))
            config.write("first-process={0}\n".format(
                "1" if Process.first_process else "0"))
            config.write("startup-time={0}\n".format(Process.startup_time))
            config.write("shutdown-mutex={0}\n".format(SHUTDOWN_MUTEX))
            config.write("force-sleepskip={0}\n".format(
                cfgoptions.get("force-sleepskip", "0")))

            Process.first_process = False

        if apc or self.suspended:
            log.info("Using QueueUserAPC injection.")
            if not self.h_thread:
                log.info(
                    "No valid thread handle specified for injecting "
                    "process with pid %d, injection aborted.", self.pid)
                return False

            if not KERNEL32.QueueUserAPC(load_library, self.h_thread, arg):
                log.error(
                    "QueueUserAPC failed when injecting process with "
                    "pid %d (Error: %s)", self.pid,
                    get_error_string(KERNEL32.GetLastError()))
                return False
            log.info("Successfully injected process with pid %d." % self.pid)
        else:
            event_name = "CuckooEvent%d" % self.pid
            self.event_handle = KERNEL32.CreateEventA(None, False, False,
                                                      event_name)
            if not self.event_handle:
                log.warning("Unable to create notify event..")
                return False

            log.info("Using CreateRemoteThread injection.")
            new_thread_id = c_ulong(0)
            thread_handle = KERNEL32.CreateRemoteThread(
                self.h_process, None, 0, load_library, arg, 0,
                byref(new_thread_id))
            if not thread_handle:
                log.error(
                    "CreateRemoteThread failed when injecting process "
                    "with pid %d (Error: %s)", self.pid,
                    get_error_string(KERNEL32.GetLastError()))
                KERNEL32.CloseHandle(self.event_handle)
                self.event_handle = None
                return False
            else:
                KERNEL32.CloseHandle(thread_handle)

        return True
Exemplo n.º 2
0
    def run(self, waiting_time):

        # Open driver device
        self.hdevice = KERNEL32.CreateFileA(self.device_name,
                                            GENERIC_READ | GENERIC_WRITE, 0,
                                            None, OPEN_EXISTING, 0, None)
        if self.hdevice == INVALID_HANDLE_VALUE:
            self.log.error("CreateFileA failed with error : 0x%x" %
                           KERNEL32.GetLastError())
            quit()

        self.log.info("Driver device file opened, handle = %x" % self.hdevice)

        #todo : build command line
        self.process = Process(self.command_line, self.log)

        self.process.create_suspended()

        self.pre_run()

        self.log.info("Target process handle value is 0x%x" %
                      self.process.process_handle)

        self.thread_running = True
        thread = Thread(target=self.pipe_reader_thread, args=())

        #Create an unpack event which will be signaled when the
        self.hUnpackEvent = KERNEL32.CreateEventA(NULL, 0, 0, "DaEvent")
        self.UserlandNotidyEvent = KERNEL32.CreateEventA(
            NULL, 0, 0, "UserlandNotidyEvent")

        #Struct sent to the driver
        MyPidStruct = PID_STRUCT()
        MyPidStruct.do_log = self.kernel_log
        MyPidStruct.RWEPolicy = self.rwe_policy
        MyPidStruct.InitialNXState = self.initial_nx_state
        MyPidStruct.UserlandNotidyEvent = self.UserlandNotidyEvent
        MyPidStruct.TargetProcessHandle = self.process.process_handle

        #Initiate driver's state and communication mecanisms
        BytesReturned = DWORD(0)
        success = KERNEL32.DeviceIoControl(self.hdevice, IOCTL_SETUP_STUFF,
                                           ctypes.byref(MyPidStruct),
                                           ctypes.sizeof(MyPidStruct), NULL, 0,
                                           ctypes.byref(BytesReturned), 0)
        if not (success):
            self.log.error("DeviceIoControl failed")
            raise UnpackerException("DeviceIoControl failed")

        thread.start()

        #Resume main process thtread
        self.process.resume()
        self.log.info("Main thread resumed")

        #Wait for unpacking to terminate
        r = KERNEL32.WaitForSingleObject(self.hUnpackEvent,
                                         self.max_unpack_time)
        if (r == WAIT_ABANDONED):
            self.log.error("Wait abandoned, something went wrong")
            raise UnpackerException("Wait abandoned, something went wrong")

        if (r == WAIT_TIMEOUT):
            self.log.info("Wait timed out")
            self.log.info("Thread suspended")

        if (r == WAIT_OBJECT_0):
            self.log.info("Event signaled")

        BytesReturned = DWORD(0)
        success = KERNEL32.DeviceIoControl(self.hdevice, IOCTL_SUSPEND_TRACKED,
                                           NULL, 0, NULL, 0,
                                           ctypes.byref(BytesReturned), 0)
        if not (success):
            self.log.error("DeviceIoControl failed")
            raise UnpackerException("DeviceIoControl failed")

        self.thread_running = False

        result = self.post_treatment()

        BytesReturned = DWORD(0)
        success = KERNEL32.DeviceIoControl(self.hdevice,
                                           IOCTL_UNTRACK_AND_RESUME_PROCESSES,
                                           NULL, 0, NULL, 0,
                                           ctypes.byref(BytesReturned), 0)
        if not (success):
            self.log.error("DeviceIoControl failed")
            raise UnpackerException("DeviceIoControl failed")

        BytesReturned = DWORD(0)
        success = KERNEL32.DeviceIoControl(self.hdevice, IOCTL_CLEANUP, NULL,
                                           0, NULL, 0,
                                           ctypes.byref(BytesReturned), 0)
        if not (success):
            self.log.error("DeviceIoControl failed")
            raise UnpackerException("DeviceIoControl failed")

        KERNEL32.CloseHandle(self.hdevice)
        KERNEL32.CloseHandle(self.UserlandNotidyEvent)

        self.process.terminate()

        KERNEL32.ExitProcess(0)