Exemplo n.º 1
0
    def invoke(self, ctlcode, value, outlength=0x1000):
        device_handle = KERNEL32.CreateFileA(
            "\\\\.\\%s" % self.pipepath, GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE, None, OPEN_EXISTING, 0,
            None) % 2**32

        if device_handle == 0xffffffff:
            # Only report an error if the error is not "name not found",
            # indicating that no kernel analysis is currently taking place.
            if KERNEL32.GetLastError() != 2:
                log.warning("Error opening handle to driver (%s): %d!",
                            driver_name, KERNEL32.GetLastError())
            return False

        out = ctypes.create_string_buffer(outlength)
        length = ctypes.c_uint()

        ret = KERNEL32.DeviceIoControl(device_handle, ctlcode, value,
                                       len(value), out, ctypes.sizeof(out),
                                       ctypes.byref(length), None)
        KERNEL32.CloseHandle(device_handle)

        if not ret:
            log.warning("Error performing ioctl (0x%08x): %d!", ctlcode,
                        KERNEL32.GetLastError())
            return False

        return out.raw[:length.value]
Exemplo n.º 2
0
 def add_tracked_pid(self, pid):
     #Initiate driver's state and communication mecanisms
     BytesReturned = DWORD(0)
     pid = DWORD(pid)
     success = KERNEL32.DeviceIoControl(self.hdevice, IOCTL_ADD_TRACKED,
                                        ctypes.byref(pid),
                                        ctypes.sizeof(pid), NULL, 0,
                                        ctypes.byref(BytesReturned), 0)
     if not (success):
         self.log.error("DeviceIoControl failed")
         raise UnpackerException("DeviceIoControl failed")
Exemplo n.º 3
0
    def kernel_analyze(self):
        """zer0m0n kernel analysis
        """
        log.info("Starting kernel analysis")
        log.info("Installing driver")
        if is_os_64bit():
            sys_file = os.path.join(os.getcwd(), "dll", "zer0m0n_x64.sys")
        else:
            sys_file = os.path.join(os.getcwd(), "dll", "zer0m0n.sys")
        exe_file = os.path.join(os.getcwd(), "dll", "logs_dispatcher.exe")
        if not sys_file or not exe_file or not os.path.exists(
                sys_file) or not os.path.exists(exe_file):
            log.warning(
                "No valid zer0m0n files to be used for process with pid %d, injection aborted",
                self.pid)
            return False

        exe_name = service_name = driver_name = random_string(6)

        inf_data = ('[Version]\r\n'
                        'Signature = "$Windows NT$"\r\n'
                        'Class = "ActivityMonitor"\r\n'
                        'ClassGuid = {{b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2}}\r\n'
                        'Provider = %Prov%\r\n'
                        'DriverVer = 22/01/2014,1.0.0.0\r\n'
                        'CatalogFile = %DriverName%.cat\r\n'
                    '[DestinationDirs]\r\n'
                        'DefaultDestDir = 12\r\n'
                        'MiniFilter.DriverFiles = 12\r\n'
                    '[DefaultInstall]\r\n'
                        'OptionDesc = %ServiceDescription%\r\n'
                        'CopyFiles = MiniFilter.DriverFiles\r\n'
                    '[DefaultInstall.Services]\r\n' \
                        'AddService = %ServiceName%,,MiniFilter.Service\r\n'
                    '[DefaultUninstall]\r\n'
                        'DelFiles = MiniFilter.DriverFiles\r\n'
                    '[DefaultUninstall.Services]\r\n'
                        'DelService = %ServiceName%,0x200\r\n'
                    '[MiniFilter.Service]\r\n'
                        'DisplayName = %ServiceName%\r\n'
                        'Description = %ServiceDescription%\r\n'
                        'ServiceBinary = %12%\\%DriverName%.sys\r\n'
                        'Dependencies = "FltMgr"\r\n'
                        'ServiceType = 2\r\n'
                        'StartType = 3\r\n'
                        'ErrorControl = 1\r\n'
                        'LoadOrderGroup = "FSFilter Activity Monitor"\r\n'
                        'AddReg = MiniFilter.AddRegistry\r\n'
                    '[MiniFilter.AddRegistry]\r\n'
                        'HKR,,"DebugFlags",0x00010001 ,0x0\r\n'
                        'HKR,"Instances","DefaultInstance",0x00000000,%DefaultInstance%\r\n'
                        'HKR,"Instances\\"%Instance1.Name%,"Altitude",0x00000000,%Instance1.Altitude%\r\n'
                        'HKR,"Instances\\"%Instance1.Name%,"Flags",0x00010001,%Instance1.Flags%\r\n'
                    '[MiniFilter.DriverFiles]\r\n'
                        '%DriverName%.sys\r\n'
                    '[SourceDisksFiles]\r\n'
                        '{driver_name}.sys = 1,,\r\n'
                    '[SourceDisksNames]\r\n'
                        '1 = %DiskId1%,,,\r\n'
                    '[Strings]\r\n'
                        'Prov = "{random_string8}"\r\n'
                        'ServiceDescription = "{random_string12}"\r\n'
                        'ServiceName = "{service_name}"\r\n'
                        'DriverName = "{driver_name}"\r\n'
                        'DiskId1 = "{service_name} Device Installation Disk"\r\n'
                        'DefaultInstance = "{service_name} Instance"\r\n'
                        'Instance1.Name = "{service_name} Instance"\r\n'
                        'Instance1.Altitude = "370050"\r\n'
                        'Instance1.Flags = 0x0'
                    ).format(
                        service_name=service_name, driver_name=driver_name, random_string8=random_string(8), random_string12=random_string(12)
                    )

        new_inf = os.path.join(os.getcwd(), "dll",
                               "{0}.inf".format(service_name))
        new_sys = os.path.join(os.getcwd(), "dll",
                               "{0}.sys".format(driver_name))
        copy(sys_file, new_sys)
        new_exe = os.path.join(os.getcwd(), "dll", "{0}.exe".format(exe_name))
        copy(exe_file, new_exe)
        log.info("[-] Driver name : " + new_sys)
        log.info("[-] Inf name : " + new_inf)
        log.info("[-] Application name : " + new_exe)
        log.info("[-] Service : " + service_name)

        fh = open(new_inf, "w")
        fh.write(inf_data)
        fh.close()

        os_is_64bit = is_os_64bit()
        if os_is_64bit:
            wow64 = c_ulong(0)
            KERNEL32.Wow64DisableWow64FsRedirection(byref(wow64))

        os.system(
            'cmd /c "rundll32 setupapi.dll, InstallHinfSection DefaultInstall 132 '
            + new_inf + '"')
        os.system("net start " + service_name)

        si = STARTUPINFO()
        si.cb = sizeof(si)
        pi = PROCESS_INFORMATION()
        cr = CREATE_NEW_CONSOLE

        ldp = KERNEL32.CreateProcessW(new_exe, None, None, None, None, cr,
                                      None, os.getenv("TEMP"), byref(si),
                                      byref(pi))
        if not ldp:
            if os_is_64bit:
                KERNEL32.Wow64RevertWow64FsRedirection(wow64)
            log.error("Failed starting " + exe_name + ".exe.")
            return False

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

            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))

        log.info("Sending startup information")
        hFile = KERNEL32.CreateFileW(PATH_KERNEL_DRIVER,
                                     GENERIC_READ | GENERIC_WRITE, 0, None,
                                     OPEN_EXISTING, 0, None)
        if os_is_64bit:
            KERNEL32.Wow64RevertWow64FsRedirection(wow64)
        if hFile:
            p = Process(pid=os.getpid())
            ppid = p.get_parent_pid()
            pid_vboxservice = 0
            pid_vboxtray = 0

            # get pid of VBoxService.exe and VBoxTray.exe
            proc_info = PROCESSENTRY32()
            proc_info.dwSize = sizeof(PROCESSENTRY32)

            snapshot = KERNEL32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
            flag = KERNEL32.Process32First(snapshot, byref(proc_info))
            while flag:
                if proc_info.sz_exeFile == "VBoxService.exe":
                    log.info("VBoxService.exe found !")
                    pid_vboxservice = proc_info.th32ProcessID
                    flag = 0
                elif proc_info.sz_exeFile == "VBoxTray.exe":
                    pid_vboxtray = proc_info.th32ProcessID
                    log.info("VBoxTray.exe found !")
                    flag = 0
                flag = KERNEL32.Process32Next(snapshot, byref(proc_info))
            bytes_returned = c_ulong(0)
            msg = str(self.pid) + "_" + str(ppid) + "_" + str(
                os.getpid()) + "_" + str(pi.dwProcessId) + "_" + str(
                    pid_vboxservice) + "_" + str(pid_vboxtray) + '\0'
            KERNEL32.DeviceIoControl(hFile, IOCTL_PID, msg, len(msg), None, 0,
                                     byref(bytes_returned), None)
            msg = os.getcwd() + '\0'
            KERNEL32.DeviceIoControl(hFile,
                                     IOCTL_CUCKOO_PATH, str(msg, 'utf-8'),
                                     len(str(msg, 'utf-8')), None, 0,
                                     byref(bytes_returned), None)
        else:
            log.warning("Failed to access kernel driver")

        return True
Exemplo n.º 4
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)
Exemplo n.º 5
0
    def pipe_reader_thread(self):

        evt_header = EVENT_HEADER()
        nbRead = DWORD(0)

        while (self.thread_running):

            valid_object = True

            #Wait for the driver to signal an event is ready for retrieval
            r = KERNEL32.WaitForSingleObject(self.UserlandNotidyEvent,
                                             INFINITE)
            if (r == WAIT_OBJECT_0):

                #An event has arrived, request it to the driver
                ReceiveBuffer = ctypes.create_string_buffer(1024)
                BytesReturned = DWORD(0)
                success = KERNEL32.DeviceIoControl(
                    self.hdevice, IOCTL_RETRIEVE_EXCEPTION, NULL, 0,
                    ctypes.byref(ReceiveBuffer), ctypes.sizeof(ReceiveBuffer),
                    ctypes.byref(BytesReturned), 0)
                if not (success):
                    self.log.error("DeviceIoControl failed")
                    raise UnpackerException("DeviceIoControl failed")

                header_size = ctypes.sizeof(EVENT_HEADER)

                #Ensure there is a header
                if (BytesReturned.value < header_size):
                    self.log.error(
                        "Did not receive enough data from driver (%d bytes)" %
                        BytesReturned.value)
                    continue

                #Copy the data in a EVENT_HEADER object
                ctypes.memmove(ctypes.addressof(evt_header),
                               ReceiveBuffer[0:header_size], header_size)

                #Ensure it is a known event
                if not (Events.has_key(evt_header.event_type)):
                    self.log.error("Received unknown event with type : %d" %
                                   evt_header.event_type)
                    continue

                #Ensure the object fits in the buffer
                n_remaining_bytes = BytesReturned.value - header_size

                event_class = Events[evt_header.event_type]

                if (n_remaining_bytes != ctypes.sizeof(event_class)):
                    self.log.error(
                        "Wrong event size. Received %d bytes, expected %d bytes"
                        % (n_remaining_bytes, ctypes.sizeof(event_class)))
                    continue

                event_obj = event_class()

                # "cast" the buffer in the appropriate event class
                ctypes.memmove(ctypes.addressof(event_obj),
                               ReceiveBuffer[header_size:],
                               ctypes.sizeof(event_class))

                #call the user defined event handler
                result = self.event_handler(evt_header.event_type, event_obj)
                if (result == 0):
                    self.stop()
                    return