(self)
setting unicorn registers
setting unicorn registers
setting unicorn registers
def set_regs(self):
        ''' setting unicorn registers '''
        uc = self.uc

        self._symbolic_offsets = set()

        if self.state.arch.qemu_name == 'x86_64':
            fs = self.state.solver.eval(self.state.regs.fs)
            gs = self.state.solver.eval(self.state.regs.gs)
            self.write_msr(fs, 0xC0000100)
            self.write_msr(gs, 0xC0000101)
        elif self.state.arch.qemu_name == 'i386':
            fs = self.state.solver.eval(self.state.regs.fs) << 16
            gs = self.state.solver.eval(self.state.regs.gs) << 16
            self.setup_gdt(fs, gs)
        elif self.state.arch.qemu_name == 'mips':
            # ulr
            ulr = self.state.regs._ulr
            uc.reg_write(self._uc_const.UC_MIPS_REG_CP0_USERLOCAL, self.state.solver.eval(ulr))

        self.setup_flags()
        for r, c in self._uc_regs.items():
            if r in self.state.arch.reg_blacklist:
                continue
            v = self._process_value(getattr(self.state.regs, r), 'reg')
            if v is None:
                raise SimValueError('setting a symbolic register')
            # l.debug('setting $%s = %#x', r, self.state.solver.eval(v))
            uc.reg_write(c, self.state.solver.eval(v))

            start, size = self.state.arch.registers[r]
            if v.symbolic:
                symbolic_reg_offsets = set(range(start, start + size))
                # Process subregisters in decreasing order of their size so that smaller subregisters' taint status
                # isn't clobbered by larger subregisters
                subregs = sorted(self.state.arch.get_register_by_name(r).subregisters, key=lambda x: x[-1], reverse=True)
                for subreg in subregs:
                    if not getattr(self.state.regs, subreg[0]).symbolic:
                        for subreg_offset in range(start + subreg[1], start + subreg[1] + subreg[2]):
                            symbolic_reg_offsets.discard(subreg_offset)

                self._symbolic_offsets.update(symbolic_reg_offsets)

        # TODO: Support ARM hardfloat synchronization

        if self.state.arch.name in ('X86', 'AMD64'):
            # sync the fp clerical data
            c3210 = self.state.solver.eval(self.state.regs.fc3210)
            top = self.state.solver.eval(self.state.regs.ftop[2:0])
            rm = self.state.solver.eval(self.state.regs.fpround[1:0])
            control = 0x037F | (rm << 10)
            status = (top << 11) | c3210
            uc.reg_write(unicorn.x86_const.UC_X86_REG_FPCW, control)
            uc.reg_write(unicorn.x86_const.UC_X86_REG_FPSW, status)

            for rn in ('fc3210', 'ftop', 'fpround'):
                start, size = self.state.arch.registers[rn]
                self._symbolic_offsets.difference_update(range(start, start + size))

            # we gotta convert the 64-bit doubles values to 80-bit extended precision!
            uc_offset = unicorn.x86_const.UC_X86_REG_FP0
            vex_offset = self.state.arch.registers['fpu_regs'][0]
            vex_tag_offset = self.state.arch.registers['fpu_tags'][0]
            tag_word = 0
            for _ in range(8):
                tag = self.state.solver.eval(self.state.registers.load(vex_tag_offset, size=1))
                tag_word <<= 2
                if tag == 0:
                    tag_word |= 3       # unicorn doesn't care about any value other than 3 for setting
                else:
                    val = self._process_value(self.state.registers.load(vex_offset, size=8), 'reg')
                    if val is None:
                        raise SimValueError('setting a symbolic fp register')
                    if val.symbolic:
                        self._symbolic_offsets.difference_update(b for b,vb in enumerate(val.chop(8), start) if vb.symbolic)
                    val = self.state.solver.eval(val)

                    sign = bool(val & 0x8000000000000000)
                    exponent = (val & 0x7FF0000000000000) >> 52
                    mantissa =  val & 0x000FFFFFFFFFFFFF
                    if exponent not in (0, 0x7FF): # normal value
                        exponent = exponent - 1023 + 16383
                        mantissa <<= 11
                        mantissa |= 0x8000000000000000  # set integer part bit, implicit to double
                    elif exponent == 0:     # zero or subnormal value
                        mantissa = 0
                    elif exponent == 0x7FF:    # nan or infinity
                        exponent = 0x7FFF
                        if mantissa != 0:
                            mantissa = 0x8000000000000000
                        else:
                            mantissa = 0xFFFFFFFFFFFFFFFF

                    if sign:
                        exponent |= 0x8000

                    uc.reg_write(uc_offset, (exponent, mantissa))

                uc_offset += 1
                vex_offset += 8
                vex_tag_offset += 1

            uc.reg_write(unicorn.x86_const.UC_X86_REG_FPTAG, tag_word)
def set_regs ( self ) : uc = self . uc self . _symbolic_offsets = set ( ) if self . state . arch . qemu_name == 'x86_64' : fs = self . state . solver . eval ( self . state . regs . fs ) gs = self . state . solver . eval ( self . state . regs . gs ) self . write_msr ( fs , 0xC0000100 ) self . write_msr ( gs , 0xC0000101 ) elif self . state . arch . qemu_name == 'i386' : fs = self . state . solver . eval ( self . state . regs . fs ) << 16 gs = self . state . solver . eval ( self . state . regs . gs ) << 16 self . setup_gdt ( fs , gs ) elif self . state . arch . qemu_name == 'mips' : # ulr ulr = self . state . regs . _ulr uc . reg_write ( self . _uc_const . UC_MIPS_REG_CP0_USERLOCAL , self . state . solver . eval ( ulr ) ) self . setup_flags ( ) for r , c in self . _uc_regs . items ( ) : if r in self . state . arch . reg_blacklist : continue v = self . _process_value ( getattr ( self . state . regs , r ) , 'reg' ) if v is None : raise SimValueError ( 'setting a symbolic register' ) # l.debug('setting $%s = %#x', r, self.state.solver.eval(v)) uc . reg_write ( c , self . state . solver . eval ( v ) ) start , size = self . state . arch . registers [ r ] if v . symbolic : symbolic_reg_offsets = set ( range ( start , start + size ) ) # Process subregisters in decreasing order of their size so that smaller subregisters' taint status # isn't clobbered by larger subregisters subregs = sorted ( self . state . arch . get_register_by_name ( r ) . subregisters , key = lambda x : x [ - 1 ] , reverse = True ) for subreg in subregs : if not getattr ( self . state . regs , subreg [ 0 ] ) . symbolic : for subreg_offset in range ( start + subreg [ 1 ] , start + subreg [ 1 ] + subreg [ 2 ] ) : symbolic_reg_offsets . discard ( subreg_offset ) self . _symbolic_offsets . update ( symbolic_reg_offsets ) # TODO: Support ARM hardfloat synchronization if self . state . arch . name in ( 'X86' , 'AMD64' ) : # sync the fp clerical data c3210 = self . state . solver . eval ( self . state . regs . fc3210 ) top = self . state . solver . eval ( self . state . regs . ftop [ 2 : 0 ] ) rm = self . state . solver . eval ( self . state . regs . fpround [ 1 : 0 ] ) control = 0x037F | ( rm << 10 ) status = ( top << 11 ) | c3210 uc . reg_write ( unicorn . x86_const . UC_X86_REG_FPCW , control ) uc . reg_write ( unicorn . x86_const . UC_X86_REG_FPSW , status ) for rn in ( 'fc3210' , 'ftop' , 'fpround' ) : start , size = self . state . arch . registers [ rn ] self . _symbolic_offsets . difference_update ( range ( start , start + size ) ) # we gotta convert the 64-bit doubles values to 80-bit extended precision! uc_offset = unicorn . x86_const . UC_X86_REG_FP0 vex_offset = self . state . arch . registers [ 'fpu_regs' ] [ 0 ] vex_tag_offset = self . state . arch . registers [ 'fpu_tags' ] [ 0 ] tag_word = 0 for _ in range ( 8 ) : tag = self . state . solver . eval ( self . state . registers . load ( vex_tag_offset , size = 1 ) ) tag_word <<= 2 if tag == 0 : tag_word |= 3 # unicorn doesn't care about any value other than 3 for setting else : val = self . _process_value ( self . state . registers . load ( vex_offset , size = 8 ) , 'reg' ) if val is None : raise SimValueError ( 'setting a symbolic fp register' ) if val . symbolic : self . _symbolic_offsets . difference_update ( b for b , vb in enumerate ( val . chop ( 8 ) , start ) if vb . symbolic ) val = self . state . solver . eval ( val ) sign = bool ( val & 0x8000000000000000 ) exponent = ( val & 0x7FF0000000000000 ) >> 52 mantissa = val & 0x000FFFFFFFFFFFFF if exponent not in ( 0 , 0x7FF ) : # normal value exponent = exponent - 1023 + 16383 mantissa <<= 11 mantissa |= 0x8000000000000000 # set integer part bit, implicit to double elif exponent == 0 : # zero or subnormal value mantissa = 0 elif exponent == 0x7FF : # nan or infinity exponent = 0x7FFF if mantissa != 0 : mantissa = 0x8000000000000000 else : mantissa = 0xFFFFFFFFFFFFFFFF if sign : exponent |= 0x8000 uc . reg_write ( uc_offset , ( exponent , mantissa ) ) uc_offset += 1 vex_offset += 8 vex_tag_offset += 1 uc . reg_write ( unicorn . x86_const . UC_X86_REG_FPTAG , tag_word )