Example #1
0
    def execute(self, path, args=None, suspended=False, kernel_analysis=False):
        """Execute sample process.
        @param path: sample path.
        @param args: process args.
        @param suspended: is suspended.
        @return: operation status.
        """
        if not os.access(path, os.X_OK):
            log.error('Unable to access file at path "%s", execution aborted', path)
            return False

        startup_info = STARTUPINFO()
        startup_info.cb = sizeof(startup_info)
        # STARTF_USESHOWWINDOW
        startup_info.dwFlags = 1
        # SW_SHOWNORMAL
        startup_info.wShowWindow = 1
        process_info = PROCESS_INFORMATION()

        arguments = f'"{path}" '
        if args:
            arguments += args

        creation_flags = CREATE_NEW_CONSOLE
        if suspended:
            self.suspended = True
            creation_flags += CREATE_SUSPENDED

        created = KERNEL32.CreateProcessW(
            path, arguments, None, None, None, creation_flags, None, os.getenv("TEMP"), byref(startup_info), byref(process_info)
        )

        if created:
            self.pid = process_info.dwProcessId
            self.h_process = process_info.hProcess
            self.thread_id = process_info.dwThreadId
            self.h_thread = process_info.hThread
            log.info('Successfully executed process from path "%s" with arguments "%s" with pid %d', path, args or "", self.pid)
            if kernel_analysis:
                return self.kernel_analyze()
            return True
        else:
            log.error(
                'Failed to execute process from path "%s" with arguments "%s" (Error: %s)',
                path,
                args,
                get_error_string(KERNEL32.GetLastError()),
            )
            return False
Example #2
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
Example #3
0
    def execute(self, path, args=None, suspended=False, kernel_analysis=False):
        """Execute sample process.
        @param path: sample path.
        @param args: process args.
        @param suspended: is suspended.
        @return: operation status.
        """
        if not os.access(path, os.X_OK):
            log.error('Unable to access file at path "%s", execution aborted',
                      path)
            return False

        startup_info = STARTUPINFO()
        startup_info.cb = sizeof(startup_info)
        # STARTF_USESHOWWINDOW
        startup_info.dwFlags = 1
        # SW_SHOWNORMAL
        startup_info.wShowWindow = 1
        process_info = PROCESS_INFORMATION()

        arguments = f'"{path}" '
        if args:
            arguments += args

        creation_flags = CREATE_NEW_CONSOLE
        if suspended:
            self.suspended = True
            creation_flags += CREATE_SUSPENDED

        # Use the custom execution directory if provided, otherwise launch in the same location
        # where the sample resides (default %TEMP%)
        if "executiondir" in self.options.keys():
            execution_directory = self.options["executiondir"]
        elif "curdir" in self.options.keys():
            execution_directory = self.options["curdir"]
        else:
            execution_directory = os.getenv("TEMP")

        # Try to create the custom directories so that the execution path is deemed valid
        create_custom_folders(execution_directory)

        created = KERNEL32.CreateProcessW(path, arguments, None, None, None,
                                          creation_flags, None,
                                          execution_directory,
                                          byref(startup_info),
                                          byref(process_info))

        if created:
            self.pid = process_info.dwProcessId
            self.h_process = process_info.hProcess
            self.thread_id = process_info.dwThreadId
            self.h_thread = process_info.hThread
            log.info(
                'Successfully executed process from path "%s" with arguments "%s" with pid %d',
                path, args or "", self.pid)
            if kernel_analysis:
                return self.kernel_analyze()
            return True
        else:
            log.error(
                'Failed to execute process from path "%s" with arguments "%s" (Error: %s)',
                path,
                args,
                get_error_string(KERNEL32.GetLastError()),
            )
            return False
Example #4
0
def spCreateProcessW(application_name, command_line, process_attributes,
                     thread_attributes, inherit_handles, creation_flags,
                     environment, current_directory, startup_info):
    class STARTUPINFO(Structure):
        _fields_ = [
            ("cb", c_uint),
            ("reserved1", c_void_p),
            ("desktop", c_void_p),
            ("title", c_void_p),
            ("unused1", c_uint * 7),
            ("flags", c_uint),
            ("show_window", c_uint16),
            ("reserved2", c_uint16),
            ("reserved3", c_void_p),
            ("std_input", c_void_p),
            ("std_output", c_void_p),
            ("std_error", c_void_p),
        ]

    class PROCESS_INFORMATION(Structure):
        _fields_ = [
            ("process_handle", c_void_p),
            ("thread_handle", c_void_p),
            ("process_identifier", c_uint),
            ("thread_identifier", c_uint),
        ]

    class Handle(int):
        def Close(self):
            KERNEL32.CloseHandle(self)

    if environment:
        environment = "\x00".join(
            "%s=%s" % (k, v) for k, v in environment.items()
        ) + "\x00\x00"

    si = STARTUPINFO()
    si.cb = sizeof(STARTUPINFO)

    if startup_info:
        si.flags = startup_info.dwFlags
        si.show_window = startup_info.wShowWindow

    if si.flags & STARTF_USESTDHANDLES:
        si.std_input = cast(int(startup_info.hStdInput), c_void_p)
        si.std_output = cast(int(startup_info.hStdOutput), c_void_p)
        si.std_error = cast(int(startup_info.hStdError), c_void_p)

    pi = PROCESS_INFORMATION()

    result = KERNEL32.CreateProcessW(
        application_name, command_line, None, None, inherit_handles,
        creation_flags, environment, current_directory, byref(si), byref(pi)
    )
    if not result:
        # TODO We'll just assume this is correct for now.
        raise WindowsError(KERNEL32.GetLastError())

    return (
        Handle(pi.process_handle), Handle(pi.thread_handle),
        pi.process_identifier, pi.thread_identifier
    )