Esempio n. 1
0
    def run(self, arg):
        if not idaapi.get_root_filename():
            rs_log('please load a file/idb before')
            return

        global SyncForm
        if not SyncForm:
            SyncForm = SyncForm_t()
            SyncForm.Show()
            rs_log("plugin loaded")
Esempio n. 2
0
    def cb_broker_finished(self):
        rs_log("broker finished")
        self.uninit_hotkeys()
        if self.broker:
            self.broker.worker.stop()
            self.cb_sync.stateChanged.disconnect(self.cb_change_state)
            self.cb_sync.toggle()
            self.cb_sync.stateChanged.connect(self.cb_change_state)

        self.btn.setText("Start")
Esempio n. 3
0
 def cb_change_state(self, state):
     if state == QtCore.Qt.Checked:
         rs_log("sync enabled")
         # Restart broker
         self.hotkeys_ctx = []
         self.init_broker()
     else:
         if self.broker:
             self.smooth_kill()
         rs_log("sync disabled\n")
Esempio n. 4
0
    def translate_notice(self):
        if not self.dbg_dialect:
            rs_log("idb isn't synced yet, can't translate")
            return

        ea = idaapi.get_screen_ea()
        mod = self.name.split('.')[0].strip()
        cmd = self.dbg_dialect['prefix'] + "translate 0x%x 0x%x %s" % (self.base, ea, mod)
        self.notice_broker("cmd", "\"cmd\":\"%s\"" % cmd)
        rs_debug("translate address 0x%x" % ea)
Esempio n. 5
0
    def pdb_name_warning(self, name):
        pdbpath = DbgDirHlpr.read_rsds_pdb()
        if not pdbpath:
            return

        normpath = os.path.normpath(pdbpath.replace("\\", "\\\\"))
        pdb_root, pdb_ext = os.path.splitext(os.path.basename(normpath))
        mod_root, mod_ext = os.path.splitext(name)

        if pdb_root.strip() != mod_root.strip():
            rs_log("hint: pdb name ('%s') differs from registered module name ('%s')" % (pdb_root+mod_ext, name))
Esempio n. 6
0
    def hbp_notice(self, oneshot=False):
        if not self.is_active:
            rs_log("idb isn't enabled, hbp can't be set")
            return

        ea = idaapi.get_screen_ea()
        offset = self.rebase_remote(ea)
        cmd = "%s0x%x" % (self.dbg_dialect['hbp1' if oneshot else 'hbp'], offset)

        self.notice_broker("cmd", "\"cmd\":\"%s\"" % cmd)
        rs_log(">> set %s" % cmd)
Esempio n. 7
0
    def init_single_hotkey(self, key, fnCb, conflict=None):
        # 'mute' existing action shortcut if present
        if conflict:
            ida_kernwin.update_action_shortcut(conflict, None)

        ctx = idaapi.add_hotkey(key, fnCb)
        if ctx is None:
            rs_log("failed to register hotkey %s" % key)
            del ctx
        else:
            self.hotkeys_ctx.append((ctx, key, conflict))
Esempio n. 8
0
    def append_cmt(self, ea, cmt, rptble=False):
        if len(cmt) > 1024:
            rs_log("warning, comment needs to be splitted (from 0x%x)" % ea)
            nh = idaapi.next_head(ea, ida_idaapi.BADADDR)
            if nh == ida_idaapi.BADADDR:
                rs_log('[x] failed to find next instruction candidate')
                return

            self.append_cmt(nh, cmt[1024:], rptble)
            cmt = cmt[:1024]

        idaapi.append_cmt(ea, cmt, rptble)
Esempio n. 9
0
    def req_rcmt(self, hash):
        msg, offset, base = hash['msg'], hash['offset'], hash['base']
        offset, msg = self.addr_switch(offset, msg)
        if not offset:
            return

        ea = self.rebase(base, offset)
        if not ea:
            return

        idaapi.set_cmt(ea, str(''), False)
        rs_log("reset comment at 0x%x" % ea)
Esempio n. 10
0
    def req_cmt(self, hash):
        msg, offset, base = hash['msg'], hash['offset'], hash['base']
        offset, msg = self.addr_switch(offset, msg)
        if not offset:
            return

        ea = self.rebase(base, offset)
        if not ea:
            return

        self.append_cmt(ea, str(msg))
        rs_log("comment added at 0x%x" % ea)
Esempio n. 11
0
    def handle_name_aliasing(self):
        name = idaapi.get_root_filename()
        rs_log("default idb name: %s" % name)

        # check in conf for name aliasing
        os.environ['IDB_PATH'] = os.path.realpath(IDB_PATH)
        for loc in ('IDB_PATH', 'USERPROFILE', 'HOME'):
            if loc in os.environ:
                try:
                    confpath = os.path.join(os.path.realpath(os.environ[loc]),
                                            '.sync')
                    if os.path.exists(confpath):
                        rs_log("found config file: %s" % confpath)
                        config = ConfigParser()
                        config.read(confpath)

                        if config.has_option('ALIASES', name):
                            alias = config.get('ALIASES', name)
                            if alias != "":
                                name = alias
                                rs_log("overwrite idb name with %s" % name)

                        break
                except Exception as e:
                    rs_log('failed to load configuration file')

        self.pdb_name_warning(name)
        return name
Esempio n. 12
0
    def export_bp_notice(self):
        if not self.dbg_dialect:
            rs_log("idb isn't synced yet, can't export bp")
            return

        mod = self.name.split('.')[0].strip()
        nbp = ida_dbg.get_bpt_qty()

        for i in range(nbp):
            ea = idc.get_bpt_ea(i)
            attrs = [idc.BPTATTR_TYPE, idc.BPTATTR_COND, idc.BPTATTR_FLAGS]
            btype, cond, flags = [idc.get_bpt_attr(ea, x) for x in attrs]

            if cond:
                rs_log("bp %d: conditional bp not supported" % i)
            else:
                if ((btype in [idc.BPT_EXEC, idc.BPT_SOFT])
                        and ((flags & idc.BPT_ENABLED) != 0)):

                    offset = ea - self.base
                    bp = self.dbg_dialect['hbp' if
                                          (btype == idc.BPT_EXEC) else 'bp']
                    cmd = "%s%s+0x%x" % (bp, mod, offset)
                    self.notice_broker("cmd", "\"cmd\":\"%s\"" % cmd)
                    rs_log("bp %d: %s" % (i, cmd))

        rs_log('export done')
Esempio n. 13
0
    def uninit_hotkeys(self):
        if not self.hotkeys_ctx:
            return

        # delete registered context and restore original action
        for ctx, key, conflict in self.hotkeys_ctx:
            if idaapi.del_hotkey(ctx):
                del ctx
            else:
                rs_log("failed to delete hotkey %s" % key)

            if conflict:
                ida_kernwin.update_action_shortcut(conflict, key)

        self.hotkeys_ctx = []
Esempio n. 14
0
    def init_single_hotkey(self, key, fnCb, conflict=None):
        if conflict:
            if self.cmd_hooks.minver74sp1():
                # 'hook' existing action shortcut when possible
                self.cmd_hooks.add_hook(conflict, fnCb)
                return
            else:
                # 'mute' existing action shortcut
                ida_kernwin.update_action_shortcut(conflict, None)

        ctx = idaapi.add_hotkey(key, fnCb)
        if ctx is None:
            rs_log("failed to register hotkey %s" % key)
            del ctx
        else:
            self.hotkeys_ctx.append((ctx, key, conflict))
Esempio n. 15
0
    def req_lbl(self, hash):
        msg, offset, base = hash['msg'], hash['offset'], hash['base']
        offset, msg = self.addr_switch(offset, msg)
        if not offset:
            return

        ea = self.rebase(base, offset)
        if not ea:
            return

        flags = False
        if str(msg).startswith('@@'):
            flags = idaapi.SN_LOCAL

        idaapi.set_name(ea, str(msg), flags)
        rs_log("label added at 0x%x" % ea)
Esempio n. 16
0
    def bp_notice(self, oneshot=False):
        if not self.is_active:
            rs_log("idb isn't enabled, bp can't be set")
            return

        ea = idaapi.get_screen_ea()
        offset = self.rebase_remote(ea)
        if offset is not None:
            cmd = "%s0x%x" % (self.dbg_dialect['bp1' if oneshot else 'bp'],
                              offset)

            if (oneshot and 'oneshot_post' in self.dbg_dialect):
                cmd += self.dbg_dialect['oneshot_post']

            self.notice_broker("cmd", "\"cmd\":\"%s\"" % cmd)
            rs_log(">> set %s" % cmd)
Esempio n. 17
0
    def req_raddr(self, hash):
        raddr, rbase, offset, base = hash['raddr'], hash['rbase'], hash['offset'], hash['base']
        ea = self.rebase(base, offset)
        if not ea:
            return

        if self.base_remote != rbase:
            rs_log('could not rebase this address, 0x%x != 0x0, not in module')
            return

        addr = self.rebase(rbase, raddr)
        if not addr:
            return

        self.append_cmt(ea, "0x%x (rebased from 0x%x)" % (addr, raddr))
        rs_log("comment added at 0x%x" % ea)
Esempio n. 18
0
    def req_broker(self, hash):
        subtype = hash['subtype']

        if (subtype == 'msg'):
            # simple message announcement
            rs_log("<< broker << %s" % hash['msg'])

        elif (subtype == 'notice'):
            # notice from broker
            self.broker_port = int(hash['port'])
            rs_debug("<< broker << binding on port %d" % self.broker_port)

            for attempt in range(rsconfig.CONNECT_BROKER_MAX_ATTEMPT):
                try:
                    host = socket.gethostbyname('localhost')
                    self.broker_sock = socket.socket(socket.AF_INET,
                                                     socket.SOCK_STREAM)
                    self.broker_sock.settimeout(2)
                    self.broker_sock.connect((host, self.broker_port))
                    break
                except socket.error:
                    rs_log('failed to connect to broker')
                    rs_log(sys.exc_info())
                    if self.broker_sock:
                        self.broker_sock.close()
                    self.broker_sock = None
                    time.sleep(0.1)
                    if (attempt == (rsconfig.CONNECT_BROKER_MAX_ATTEMPT - 1)):
                        self.announcement(
                            "[sync] failed to connect to broker (attempt %d)" %
                            attempt)
                        raise RuntimeError

            # request broker to validate its beacon
            time.sleep(0.4)
            self.beacon_notice()

        # enable/disable idb, if disable it drops most sync requests
        elif (subtype == 'enable_idb'):
            self.is_active = True
            rs_log('idb is enabled')

        elif (subtype == 'disable_idb'):
            self.is_active = False
            self.base_remote = None
            self.cb_restore_last_line()
            rs_log('idb is disabled')
Esempio n. 19
0
    def req_fcmt(self, hash):
        msg, offset, base = hash['msg'], hash['offset'], hash['base']
        offset, msg = self.addr_switch(offset, msg)
        if not offset:
            return

        ea = self.rebase(base, offset)
        if not ea:
            return

        func = idaapi.get_func(ea)
        if not func:
            rs_log("could not find func for 0x%x" % ea)
            return

        idaapi.set_func_cmt(func, str(msg), False)
        rs_log("function comment added at 0x%x" % ea)
Esempio n. 20
0
    def rebase(self, base, offset):
        if base is not None:
            # check for non-compliant debugger client
            if base > offset:
                rs_log('unsafe addr: 0x%x > 0x%x' % (base, offset))
                return None

            # update base address of remote module
            if self.base_remote != base:
                self.base_remote = base

            offset = self.rebase_local(offset)

        if not self.is_safe(offset):
            rs_log('unsafe addr: 0x%x not in valid segment' % (offset))
            return None

        return offset
Esempio n. 21
0
    def uninit_hotkeys(self):
        # disable ida_kernwin.UI_Hooks
        if self.cmd_hooks.minver74sp1():
            self.cmd_hooks.unhook()

        if not self.hotkeys_ctx:
            return

        # delete registered context and restore original action
        for ctx, key, conflict in self.hotkeys_ctx:
            if idaapi.del_hotkey(ctx):
                del ctx
            else:
                rs_log("failed to delete hotkey %s" % key)

            if conflict and not self.cmd_hooks.minver74sp1():
                ida_kernwin.update_action_shortcut(conflict, key)

        self.hotkeys_ctx = []
Esempio n. 22
0
    def export_bp_notice(self):
        if not self.dbg_dialect:
            rs_log("idb isn't synced yet, can't export bp")
            return

        is_windbg = (self.dbg_dialect == 'windbg')

        # Windbg supports relative address, ie. mod+0xCAFE
        # for non relative address the remote base address is needed
        if (not is_windbg) and (not self.base_remote):
            rs_log("idb isn't enabled, can't export bp")
            return

        mod = self.name.split('.')[0].strip()
        nbp = ida_dbg.get_bpt_qty()

        for i in range(nbp):
            ea = idc.get_bpt_ea(i)
            attrs = [idc.BPTATTR_TYPE, idc.BPTATTR_COND, idc.BPTATTR_FLAGS]
            btype, cond, flags = [idc.get_bpt_attr(ea, x) for x in attrs]

            if cond:
                rs_log("bp %d: conditional bp not supported" % i)
            else:
                if ((btype in [idc.BPT_EXEC, idc.BPT_SOFT])
                        and ((flags & idc.BPT_ENABLED) != 0)):

                    bp = self.dbg_dialect['hbp' if
                                          (btype == idc.BPT_EXEC) else 'bp']

                    if is_windbg:
                        offset = ea - self.base
                        cmd = "%s%s+0x%x" % (bp, mod, offset)
                    else:
                        offset = self.rebase_remote(ea)
                        cmd = "%s0x%x" % (bp, offset)

                    self.notice_broker("cmd", "\"cmd\":\"%s\"" % cmd)
                    rs_log("bp %d: %s" % (i, cmd))

        rs_log('export done')
Esempio n. 23
0
    def addr_switch(self, offset, msg):
        if (not msg) or (msg == ''):
            return [offset, msg]

        try:
            args = self.parser.parse_args(msg.split())
        except argparse.ArgumentError:
            rs_log('failed to parse command')
            return [None, msg]

        # no address switch supplied
        if not args.address:
            return [offset, msg]

        try:
            addr = int(''.join(args.address), 16)
        except (TypeError, ValueError):
            rs_log('failed to parse address, should be hex')
            return [None, msg]

        # make sure the address points to a valid instruction/data
        head = idaapi.get_item_head(addr)
        if head != addr:
            rs_log("ambiguous address, did you mean 0x%x ?" % head)
            return [None, msg]

        return [addr, ' '.join(args.msg)]
Esempio n. 24
0
    def init_broker(self):
        rs_debug("init_broker")
        modname = self.input.text()
        if modname == "":
            modname = self.handle_name_aliasing()
            self.input.setText(modname)

        cmdline = "\"%s\" -u \"%s\" --idb \"%s\"" % (PYTHON_PATH, BROKER_PATH,
                                                     modname)
        rs_log("cmdline: %s" % cmdline)

        try:
            self.broker = Broker(self.parser)
            self.broker.started.connect(self.cb_broker_started)
            self.broker.finished.connect(self.cb_broker_finished)
            self.broker.start(cmdline)
        except Exception as e:
            rs_log("[-] failed to start broker: %s\n%s" %
                   (str(e), traceback.format_exc()))
            return

        self.broker.worker.name = modname
Esempio n. 25
0
    def handle_name_aliasing(self):
        name = idaapi.get_root_filename()
        rs_log("default idb name: %s" % name)

        try:
            conf = load_configuration(name)
            if conf.path:
                rs_log("found config file: %s" % repr(conf))
            if conf.alias:
                name = conf.alias
                rs_log("overwrite idb name with %s" % name)
        except Exception as e:
            rs_log('failed to load configuration file')

        self.pdb_name_warning(name)
        return name
Esempio n. 26
0
    def init_broker(self):
        rs_debug("init_broker")
        modname = self.input.text()
        cmdline = "\"%s\" -u \"%s\" --idb \"%s\"" % (PYTHON_PATH, BROKER_PATH,
                                                     modname)
        rs_log("cmdline: %s" % cmdline)

        self.broker = Broker(self.parser)
        env = QProcessEnvironment.systemEnvironment()
        env.insert("IDB_PATH", IDB_PATH)
        env.insert("PYTHON_PATH", PYTHON_PATH)

        try:
            self.broker.started.connect(self.cb_broker_started)
            self.broker.finished.connect(self.cb_broker_finished)
            self.broker.setProcessEnvironment(env)
            self.broker.start(cmdline)
        except Exception as e:
            rs_log("[-] failed to start broker: %s\n%s" %
                   (str(e), traceback.format_exc()))
            return

        self.init_hotkeys()
        self.broker.worker.name = modname
Esempio n. 27
0
    def read_rsds_codeview():
        guid = None
        penode = idaapi.netnode()
        penode.create(idautils.peutils_t.PE_NODE)
        fpos = penode.altval(idautils.peutils_t.PE_ALT_DBG_FPOS)

        if (fpos == 0):
            rs_log('No debug directory')
            return guid

        input_file = ida_nalt.get_input_file_path()
        if not os.path.exists(input_file):
            rs_log('input file not available')
        else:
            with open(input_file, 'rb') as fd:
                fd.seek(fpos)
                raw = fd.read(0x1C)
                """
                typedef struct _IMAGE_DEBUG_DIRECTORY {
                  DWORD Characteristics;
                  DWORD TimeDateStamp;
                  WORD  MajorVersion;
                  WORD  MinorVersion;
                  DWORD Type;
                  DWORD SizeOfData;
                  DWORD AddressOfRawData;
                  DWORD PointerToRawData;
                } IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY;
                """
                dbgdir = struct.unpack('LLHHLLLL', raw)
                #  2, IMAGE_DEBUG_TYPE_CODEVIEW
                if not (dbgdir[4] == 2):
                    rs_log('not CODEVIEW data')
                else:
                    fd.seek(dbgdir[7])
                    if not (fd.read(4).decode('ascii') == 'RSDS'):
                        rs_log("unsupported CODEVIEW information format (%s)" %
                               sig)
                    else:
                        d1, d2, d3 = struct.unpack('LHH', fd.read(0x8))
                        d4 = struct.unpack('>H', fd.read(0x2))[0]
                        d5 = binascii.hexlify(fd.read(0x6)).upper()
                        guid = "%08X-%04X-%04X-%04X-%s" % (d1, d2, d3, d4, d5)

        return guid
Esempio n. 28
0
    def req_rrln(self, hash):
        sym, rbase, offset, base = hash['sym'], hash['rbase'], hash['offset'], hash['base']

        rs_log("%s -  0x%x - 0x%x - 0x%x" % (sym, rbase, offset, base))

        addr = idc.get_name_ea_simple(sym)
        if addr:
            self.notice_broker("cmd", "\"cmd\":\"%s\"" % addr)
            rs_log("resolved address: %s" % addr)
        else:
            rs_log("could not resolve address for symbol %s" % sym)
Esempio n. 29
0
    def req_rrln(self, hash):
        sym = hash['sym']
        rs_log("rrln> symbol \"%s\"" % sym)

        addr = idc.get_name_ea_simple(str(sym))
        if addr:
            raddr = self.rebase_remote(addr)
            self.notice_broker("cmd", "\"cmd\":\"%s\"" % raddr)
            rs_log("rrln> remote: 0x%x, local: 0x%x)" % (raddr, addr))
        else:
            rs_log("rrln> symbol not found \"%s\"" % sym)
Esempio n. 30
0
    def req_bps_set(self, hash):
        blob = hash['msg']
        rs_log('[-] save .bpcmds')
        node = idaapi.netnode(rsconfig.NETNODE_INDEX)
        if not node:
            rs_log('[-] failed to open netnode store')
            self.notice_broker('cmd', "\"cmd\":\"    -> failed to save .bpcmds")
            return

        new = node.create(rsconfig.NETNODE_STORE)
        if new == 0:
            rs_log('    -> creating new netnode store')

        out = node.setblob(rs_encode(blob), 0, chr(1))
        self.notice_broker("cmd", "\"cmd\":\"    -> .bpcmds saved\"")
        return