Exemplo n.º 1
0
    def run_shellcode(self, sc_addr, offset=0):
        """
        Begin emulating position independent code (i.e. shellcode) to prepare for emulation
        """

        target = None
        for sc_path, _sc_addr, size in self.pic_buffers:
            if _sc_addr == sc_addr:
                target = _sc_addr
                break

        if not target:
            raise Win32EmuError("Invalid shellcode address")

        stack_commit = 0x4000

        self.stack_base, stack_addr = self.alloc_stack(stack_commit)
        self.set_func_args(self.stack_base, self.return_hook, 0x7000)

        run = Run()
        run.type = "shellcode"
        run.start_addr = sc_addr + offset
        run.instr_cnt = 0
        args = [
            self.mem_map(1024, tag="emu.shellcode_arg_%d" % (i), base=0x41420000 + i)
            for i in range(4)
        ]
        run.args = args

        self.reg_write(_arch.X86_REG_ECX, 1024)

        self.add_run(run)

        # Create an empty process object for the shellcode if none is
        # supplied
        container = self.init_container_process()
        if container:
            self.processes.append(container)
            self.curr_process = container
        else:
            p = objman.Process(self)
            self.processes.append(p)
            self.curr_process = p

        mm = self.get_address_map(sc_addr)
        if mm:
            mm.set_process(self.curr_process)

        t = objman.Thread(self, stack_base=self.stack_base, stack_commit=stack_commit)
        self.om.objects.update({t.address: t})
        self.curr_process.threads.append(t)

        self.curr_thread = t

        peb = self.alloc_peb(self.curr_process)

        # Set the TEB
        self.init_teb(t, peb)

        self.start()
Exemplo n.º 2
0
    def init_processes(self, processes):
        for proc in processes:
            p = objman.Process(self)
            self.add_object(p)
            p.name = proc.get('name', '')
            p.pid = proc.get('pid')

            if p.name.lower() == 'system':
                p.pid = 4
                p.path = 'System'

            if not p.pid:
                p.pid = self.om.new_id()
            base = proc.get('base_addr')

            if isinstance(base, str):
                base = int(base, 16)
            p.base = base
            if not p.path:
                p.path = proc.get('path')
            p.image = ntpath.basename(p.path)

            # Create an initial thread for each process
            t = objman.Thread(self)
            self.add_object(t)
            t.process = p
            p.threads.append(t)
            self.processes.append(p)

        # The SYSTEM process should be the starting context
        sp = [p for p in self.processes if p.name.lower() == 'system']
        if sp:
            sp = sp[0]
            self.set_current_process(sp)
Exemplo n.º 3
0
    def init_container_process(self):
        """
        Create a process to be used to host shellcode or DLLs
        """
        for p in self.config_processes:
            if p.get('is_main_exe'):
                name = p.get('name', '')
                emu_path = p.get('path', '')
                base = p.get('base_addr', 0)
                if isinstance(base, str):
                    base = int(base, 0)
                cmd_line = p.get('command_line', '')

                proc = objman.Process(self, name=name,
                                      path=emu_path, base=base, cmdline=cmd_line)
                return proc
        return None
Exemplo n.º 4
0
    def init_container_process(self):
        """
        Create a process to be used to host shellcode or DLLs
        """
        for p in self.config_processes:
            if p.get("is_main_exe"):
                name = p.get("name", "")
                emu_path = p.get("path", "")
                base = p.get("base_addr", 0)
                if isinstance(base, str):
                    base = int(base, 0)
                cmd_line = p.get("command_line", "")

                proc = objman.Process(
                    self, name=name, path=emu_path, base=base, cmdline=cmd_line
                )
                return proc
        return None
Exemplo n.º 5
0
    def init_processes(self, processes):
        """
        Initialize configured processes set in the emulator config
        """
        for proc in processes:
            p = objman.Process(self)
            self.add_object(p)

            p.name = proc.get('name', '')
            new_pid = proc.get('pid')
            if new_pid:
                p.pid = new_pid

            base = proc.get('base_addr')

            if isinstance(base, str):
                base = int(base, 16)
            p.base = base
            p.path = proc.get('path')
            p.session = proc.get('session', 0)
            p.image = ntpath.basename(p.path)

            self.processes.append(p)
Exemplo n.º 6
0
    def run_module(self, module, all_entrypoints=False):
        """
        Begin emulating a previously loaded module

        Arguments:
            module: Module to emulate
        """

        if not module:
            self.stop()
            raise Win32EmuError('Module not found')

        # Check if any TLS callbacks exist, these run before the module's entry point
        tls = module.get_tls_callbacks()
        for i, cb_addr in enumerate(tls):
            base = module.get_base()
            if base < cb_addr < base + module.get_image_size():
                run = Run()
                run.start_addr = cb_addr
                run.type = 'tls_callback_%d' % (i)
                run.args = [base, DLL_PROCESS_ATTACH, 0]
                self.add_run(run)

        # Queue up the module's main entry point
        ep = module.base + module.ep

        run = Run()
        run.start_addr = ep

        main_exe = None
        if not module.is_exe():
            run.args = [module.base, DLL_PROCESS_ATTACH, 0]
            run.type = 'dll_entry.DLL_PROCESS_ATTACH'
            container = self.init_container_process()
            if container:
                self.processes.append(container)
                self.curr_process = container
        else:
            run.type = 'module_entry'
            main_exe = module
            run.args = [
                self.mem_map(8, tag='emu.module_arg_%d' % (i))
                for i in range(4)
            ]

        if main_exe:
            self.user_modules = [main_exe] + self.user_modules

        self.add_run(run)

        if all_entrypoints:
            # Only emulate a subset of all the exported functions
            # There are some modules (such as the windows kernel) with
            # thousands of exports
            exports = [
                k for k in module.get_exports()[:MAX_EXPORTS_TO_EMULATE]
            ]

            if exports:
                args = [
                    self.mem_map(8,
                                 tag='emu.export_arg_%d' % (i),
                                 base=0x41420000) for i in range(4)
                ]  # noqa
                for exp in exports:
                    if exp.name in ('DllMain', 'ServiceMain'):
                        continue
                    run = Run()
                    if exp.name:
                        fn = exp.name
                    else:
                        fn = 'no_name'

                    run.type = 'export.%s' % (fn)
                    run.start_addr = exp.address
                    # Here we set dummy args to pass into the export function
                    run.args = args
                    # Store these runs and only queue them before the unload
                    # routine this is because some exports may not be ready to
                    # be called yet
                    self.add_run(run)

        # Create an empty process object for the module if none is
        # supplied
        if len(self.processes) == 0:
            p = objman.Process(self,
                               path=module.get_emu_path(),
                               base=module.base,
                               pe=module,
                               cmdline=self.command_line)
            self.curr_process = p
            self.om.objects.update({p.address: p})
            mm = self.get_address_map(module.base)
            if mm:
                mm.process = self.curr_process

        t = objman.Thread(self,
                          stack_base=self.stack_base,
                          stack_commit=module.stack_commit)

        self.om.objects.update({t.address: t})
        self.curr_process.threads.append(t)
        self.curr_thread = t

        peb = self.alloc_peb(self.curr_process)

        # Set the TEB
        self.init_teb(t, peb)

        # Begin emulation
        self.start()
Exemplo n.º 7
0
    def run_module(self, module, all_entrypoints=False, emulate_children=False, entrypoints=None):
        """
        Begin emulating a previously loaded module

        Arguments:
            module: Module to emulate
        """
        if entrypoints is None:
            entrypoints = []

        self.prepare_module_for_emulation(module, all_entrypoints, entrypoints)

        # Create an empty process object for the module if none is
        # supplied, only do this for the main module
        if len(self.processes) == 0:
            p = objman.Process(
                self,
                path=module.get_emu_path(),
                base=module.base,
                pe=module,
                cmdline=self.command_line,
            )
            self.curr_process = p
            self.om.objects.update({p.address: p})
            mm = self.get_address_map(module.base)
            if mm:
                mm.process = self.curr_process

        t = objman.Thread(
            self, stack_base=self.stack_base, stack_commit=module.stack_commit
        )

        self.om.objects.update({t.address: t})
        self.curr_process.threads.append(t)
        self.curr_thread = t

        peb = self.alloc_peb(self.curr_process)

        # Set the TEB
        self.init_teb(t, peb)

        # Begin emulation of main module
        self.start()

        if not emulate_children or len(self.child_processes) == 0:
            return

        # Emulate any child processes
        while len(self.child_processes) > 0:
            child = self.child_processes.pop(0)

            child.pe = self.load_module(data=child.pe_data, first_time_setup=False)
            self.prepare_module_for_emulation(child.pe, all_entrypoints, entrypoints)

            self.command_line = child.cmdline

            self.curr_process = child
            self.curr_process.base = child.pe.base
            self.curr_thread = child.threads[0]

            self.om.objects.update({self.curr_thread.address: self.curr_thread})

            # PEB and TEB will be initialized when the next run happens

            self.start()

        return