Exemplo n.º 1
0
def analyze(vw):
    """
    """
    # Go through the relocations and create locations for them
    for segva,segsize,segname,segfname in vw.getSegments():

        # FIXME should we do this by something other than name?
        if segname != ".reloc":
            continue

        offset, bytes = vw.getByteDef(segva)

        while offset < segsize:
            # error cehck to make sure we are providing four bytes
            # to the parse routine
            if len(bytes[offset+4:offset+8]) != 4:
                break

            basepage = e_bits.parsebytes(bytes, offset, 4)

            vaoff = segva + offset
            vw.makeNumber(vaoff, 4)
            vw.makeName(vaoff, "reloc_chunk_%.8x" % vaoff)

            recsize = e_bits.parsebytes(bytes, offset+4, 4)
            vw.makeNumber(segva+offset+4, 4)

            ioff = offset + 8
            while ioff < offset+recsize:
                vw.makeNumber(segva + ioff, 2)
                ioff += 2

            offset += recsize
            if recsize == 0:
                break
Exemplo n.º 2
0
def analyze(vw):
    """
    """
    # Go through the relocations and create locations for them
    for segva, segsize, segname, segfname in vw.getSegments():
        reloc_va = vw.getFileMeta(segfname, "reloc_va")
        # Found binaries with multiple sections named .reloc where one was iat another
        # was actual reloc
        if reloc_va != segva:
            continue

        offset, bytes = vw.getByteDef(segva)
        while offset < segsize:
            # error check to make sure we are providing four bytes
            # to the parse routine
            if len(bytes[offset + 4:offset + 8]) != 4:
                break

            basepage = e_bits.parsebytes(bytes, offset, 4)

            vaoff = segva + offset
            vw.makeNumber(vaoff, 4)
            vw.makeName(vaoff, "reloc_chunk_%.8x" % vaoff)

            recsize = e_bits.parsebytes(bytes, offset + 4, 4)
            vw.makeNumber(segva + offset + 4, 4)

            ioff = offset + 8
            while ioff < offset + recsize:
                vw.makeNumber(segva + ioff, 2)
                ioff += 2

            offset += recsize
            if recsize == 0:
                break
Exemplo n.º 3
0
    def _buildOper(self, bytes, offset, immoff, otype, oinfo):

        if otype == OPTYPE_Reg:
            return z80RegOper(oinfo)

        elif otype == OPTYPE_RegMem:
            return z80RegMem(oinfo)

        elif otype == OPTYPE_const:
            return z80ConstOper(oinfo)

        elif otype == OPTYPE_imm8:
            imm = e_bits.parsebytes(bytes, offset+immoff, 1)
            return z80ImmOper(imm)

        elif otype == OPTYPE_imm16:
            imm = e_bits.parsebytes(bytes, offset+immoff, 2)
            return z80ImmOper(imm)

        elif otype == OPTYPE_RegAlt:
            print 'REG ALT!'
            return z80RegOper(oinfo)

        elif otype == OPTYPE_Ind:
            print 'OPTYPE IND'

        elif otype == OPTYPE_RegMemDisp:
            disp = e_bits.parsebytes(bytes, offset+immoff, 1, sign=True)
            return z80RegMem(oinfo, disp)

        else:
            raise Exception('Unknown z80 operand type: %d' % otype)
Exemplo n.º 4
0
    def parse_sib(self, bytez, offset, mod, prefixes=0):
        """
        Return a tuple of (size, scale, index, base, imm)
        """
        byte = ord(bytez[offset])
        scale = (byte >> 6) & 0x3
        index = (byte >> 3) & 0x7
        base  = byte & 0x7
        imm = None

        size = 1

        # Special SIB case with no index reg
        if index == 4:
            index = None

        # Special SIB case with possible immediate
        if base == 5:
            if mod == 0: # [ imm32 + index * scale ]
                base = None
                imm = e_bits.parsebytes(bytez, offset+size, 4, sign=False)
                size += 4
            # FIXME is there special stuff needed here?
            elif mod == 1:
                pass
                #raise "OMG MOD 1"
            elif mod == 2:
                pass
                #raise "OMG MOD 2"

        return (size, scale, index, base, imm)
Exemplo n.º 5
0
    def ameth_l(self, bytez, offset, tsize, prefixes, operflags):
        osize = 1
        imm = e_bits.parsebytes(bytez, offset, 1)
        vvvv = (imm >> 4)
        offset = self.ROFFSETSIMD
        if not (prefixes & PREFIX_VEX_L):
            vvvv |= e_i386.RMETA_LOW128

        oper = i386RegOper(offset + vvvv, tsize)
        return osize, oper
Exemplo n.º 6
0
 def readMemValue(self, addr, size):
     """
     Returns the value of the bytes at the "addr" address, given the size (currently, power of 2 only)
     """
     bytes = self.readMemory(addr, size)
     if bytes == None:
         return None
     if len(bytes) != size:
         raise Exception("Read Gave Wrong Length At 0x%.8x (va: 0x%.8x wanted %d got %d)" % (self.getProgramCounter(),addr, size, len(bytes)))
     
     return e_bits.parsebytes(bytes, 0, size, False, self.getEndian())
Exemplo n.º 7
0
    def extended_parse_modrm(self, bytes, offset, opersize, regbase=0):
        """
        Return a tuple of (size, Operand)
        """
        size = 1
        # FIXME this would be best to not parse_modrm twice.  tweak it.
        mod,reg,rm = self.parse_modrm(ord(bytes[offset]))
        if mod == 0 and rm == 5:
            imm = e_bits.parsebytes(bytes, offset + size, 4, sign=True)
            size += 4
            return(size, Amd64RipRelOper(imm, 4))

        return e_i386.i386Disasm.extended_parse_modrm(self, bytes, offset, opersize, regbase)
Exemplo n.º 8
0
    def readMemValue(self, addr, size):
        '''
        Read a number from memory of the given size.
        '''
        #FIXME: use getBytesDef (and implement a dummy wrapper in VTrace for getBytesDef)
        bytes = self.readMemory(addr, size)
        if bytes == None:
            return None

        #FIXME change this (and all uses of it) to passing in format...
        if len(bytes) != size:
            raise Exception("Read Gave Wrong Length At 0x%.8x (va: 0x%.8x wanted %d got %d)" % (self.getProgramCounter(),addr, size, len(bytes)))

        return e_bits.parsebytes(bytes, 0, size, False, self.getEndian())
Exemplo n.º 9
0
    def addAnalysisResults(self, vw, emu):
        """
        Do any post-run annotation that the base analysis emulator knows
        how to do...
        """
        # Add emulation anomalies
        for row in self.getAnomalies():
            va, msg = row
            vw.setVaSetRow("Emulation Anomalies", row)
            vw.setComment(va, 'Emu Anomaly: %s' % (msg,), check=True)

        # Go through the evaluated dereference operands and add operand refs
        deltadone = {}
        for va, idx, val, tsize, spdelta, discrete in self.operrefs:

            if spdelta:

                vw.addFref(self.fva, va, idx, spdelta)

                if deltadone.get(spdelta):
                    continue

                deltadone[spdelta] = True
                if spdelta <= 0:  # add function locals
                    vw.setFunctionLocal(self.fva, spdelta, LSYM_NAME, ('int', 'local%d' % abs(spdelta)))

                continue

            # Only infer things about the workspace based on discrete operands
            if vw.isValidPointer(val) and discrete:

                vw.addXref(va, val, REF_DATA)
                if vw.getLocation(val) is not None:
                    continue

                offset, bytes = vw.getByteDef(val)
                pval = e_bits.parsebytes(bytes, offset, tsize)
                if vw.psize == tsize and vw.isValidPointer(pval):
                    vw.makePointer(val, tova=pval)
                else:
                    vw.makeNumber(val, tsize)

        for va, callname, argv in self.callcomments:
            reprargs = [emu.reprVivValue(val) for val in argv]
            self.vw.setComment(va, '%s(%s)' % (callname, ','.join(reprargs)))
Exemplo n.º 10
0
 def ameth_a(self, bytez, offset, tsize, prefixes, operflags):
     imm = e_bits.parsebytes(bytez, offset, tsize)
     # seg = e_bits.parsebytes(bytez, offset+tsize, 2)
     # THIS BEING GHETTORIGGED ONLY EFFECTS callf jmpf - unghettorigged by atlas
     # FIXME: envi.intel.ameth_a skipping seg prefix %d" % seg)
     return (tsize, i386ImmOper(imm, tsize))
Exemplo n.º 11
0
 def ameth_o(self, bytez, offset, tsize, prefixes, operflags):
     # NOTE: displacement *stays* 32 bit even with REX
     # (but 16 bit should probably be supported)
     imm = e_bits.parsebytes(bytez, offset, self.ptrsize, sign=False)
     return (self.ptrsize, i386ImmMemOper(imm, tsize))
Exemplo n.º 12
0
 def ameth_j(self, bytez, offset, tsize, prefixes, operflags):
     imm = e_bits.parsebytes(bytez, offset, tsize, sign=True)
     return (tsize, i386PcRelOper(imm, tsize))
Exemplo n.º 13
0
 def ameth_i(self, bytez, offset, tsize, prefixes, operflags):
     imm = e_bits.parsebytes(bytez, offset, tsize)
     return (tsize, i386ImmOper(imm, tsize))
Exemplo n.º 14
0
 def ameth_a(self, bytez, offset, tsize, prefixes, operflags):
     imm = e_bits.parsebytes(bytez, offset, tsize)
     #seg = e_bits.parsebytes(bytez, offset+tsize, 2)
     # THIS BEING GHETTORIGGED ONLY EFFECTS callf jmpf - unghettorigged by atlas
     #print "FIXME: envi.intel.ameth_a skipping seg prefix %d" % seg
     return (tsize, i386ImmOper(imm, tsize))
Exemplo n.º 15
0
 def ameth_j(self, bytez, offset, tsize, prefixes, operflags):
     imm = e_bits.parsebytes(bytez, offset, tsize, sign=True)
     return (tsize, i386PcRelOper(imm, tsize))
Exemplo n.º 16
0
    def extended_parse_modrm(self, bytez, offset, opersize, regbase=0, prefixes=0):
        """
        Return a tuple of (size, Operand)
        """

        mod,reg,rm = self.parse_modrm(ord(bytez[offset]))

        size = 1

        #print "EXTENDED MOD REG RM",mod,reg,rm

        if mod == 3: # Easy one, just a reg
            # FIXME only use self.byteRegOffset in 32 bit mode, NOT 64 bit...
            if opersize == 1: rm = self.byteRegOffset(rm, prefixes=prefixes)
            elif opersize == 2: rm += RMETA_LOW16
            #print "OPERSIZE",opersize,rm
            return (size, i386RegOper(rm+regbase, opersize))

        elif mod == 0:
            # means we are [reg] unless rm == 4 (SIB) or rm == 5 ([imm32])
            if rm == 5:
                imm = e_bits.parsebytes(bytez, offset + size, 4)
                size += 4
                # NOTE: in 64 bit mode, *this* is where we differ, (This case is RIP relative)
                return(size, i386ImmMemOper(imm, opersize))

            elif rm == 4:
                sibsize, scale, index, base, imm = self.parse_sib(bytez, offset+size, mod, prefixes=prefixes)
                size += sibsize
                if base != None: base += regbase    # Adjust for different register addressing modes
                if index != None: index += regbase    # Adjust for different register addressing modes
                oper = i386SibOper(opersize, reg=base, imm=imm, index=index, scale=scale_lookup[scale])
                return (size, oper)

            else:
                return(size, i386RegMemOper(regbase+rm, opersize))

        elif mod == 1:
            # mod 1 means we are [ reg + disp8 ] (unless rm == 4 which means sib + disp8)
            if rm == 4:
                sibsize, scale, index, base, imm = self.parse_sib(bytez, offset+size, mod, prefixes=prefixes)
                size += sibsize
                disp = e_bits.parsebytes(bytez, offset+size, 1, sign=True)
                size += 1
                if base != None: base += regbase    # Adjust for different register addressing modes
                if index != None: index += regbase    # Adjust for different register addressing modes
                oper = i386SibOper(opersize, reg=base, index=index, scale=scale_lookup[scale], disp=disp)
                return (size,oper)
            else:
                x = e_bits.signed(ord(bytez[offset+size]), 1)
                size += 1
                return(size, i386RegMemOper(regbase+rm, opersize, disp=x))

        elif mod == 2:
            # Means we are [ reg + disp32 ] (unless rm == 4  which means SIB + disp32)
            if rm == 4:
                sibsize, scale, index, base, imm = self.parse_sib(bytez,offset+size,mod, prefixes=prefixes)
                size += sibsize
                disp = e_bits.parsebytes(bytez, offset + size, 4, sign=True)
                size += 4
                if base != None: base += regbase    # Adjust for different register addressing modes
                if index != None: index += regbase    # Adjust for different register addressing modes
                oper = i386SibOper(opersize, reg=base, imm=imm, index=index, scale=scale_lookup[scale], disp=disp)
                return (size, oper)

            else:
                # NOTE: Immediate displacements in SIB are still 4 bytes in 64 bit mode
                disp = e_bits.parsebytes(bytez, offset+size, 4, sign=True)
                size += 4
                return(size, i386RegMemOper(regbase+rm, opersize, disp=disp))

        else:
            raise Exception("How does mod == %d" % mod)
Exemplo n.º 17
0
 def ameth_i(self, bytes, offset, tsize, prefixes):
     # FIXME sign extend here if opflags has OP_SIGNED
     imm = e_bits.parsebytes(bytes, offset, tsize)
     return (tsize, i386ImmOper(imm, tsize))
Exemplo n.º 18
0
 def ameth_a(self, bytes, offset, tsize, prefixes):
     imm = e_bits.parsebytes(bytes, offset, tsize)
     seg = e_bits.parsebytes(bytes, offset+tsize, 2)
     # THIS BEING GHETTORIGGED ONLY EFFECTS callf jmpf
     #print "FIXME: envi.intel.ameth_a skipping seg prefix %d" % seg
     return (tsize+2, i386ImmOper(imm, tsize))
Exemplo n.º 19
0
 def ameth_i(self, bytez, offset, tsize, prefixes, operflags):
     imm = e_bits.parsebytes(bytez, offset, tsize)
     return (tsize, i386ImmOper(imm, tsize))
Exemplo n.º 20
0
 def ameth_o(self, bytez, offset, tsize, prefixes, operflags):
     # NOTE: displacement *stays* 32 bit even with REX
     # (but 16 bit should probably be supported)
     imm = e_bits.parsebytes(bytez, offset, self.ptrsize, sign=False)
     return (self.ptrsize, i386ImmMemOper(imm, tsize))
Exemplo n.º 21
0
    def shortend_parse_modrm(self,
                             bytez,
                             offset,
                             opersize,
                             regbase=0,
                             prefixes=0):
        '''
        This is to handle the 16 version of oper addressing. ~1/2 of the table is
        completely different from the 32 bit version
        '''
        mod, reg, rm = self.parse_modrm(bytez[offset])
        size = 1
        opers = addr16_modes[rm]
        # SIB oper for the 16 bit addressing stuff because it actually fits
        if mod == 0:
            if len(opers) == 2:
                return (size,
                        i386SibOper(opersize,
                                    reg=opers[0],
                                    imm=None,
                                    index=opers[1],
                                    scale=1))
            elif len(opers) == 1:
                return (size, i386RegMemOper(opers[0], opersize))
            else:
                imm = e_bits.parsebytes(bytez, offset + size, 2)
                size += 2
                return (size, i386ImmMemOper(imm, opersize))

        elif mod == 1:
            imm = e_bits.parsebytes(bytez, offset + size, 1)
            size += 1
            if len(opers) == 2:
                return (size,
                        i386SibOper(opersize,
                                    reg=opers[0],
                                    disp=imm,
                                    index=opers[1],
                                    scale=1))
            elif len(opers) == 1:
                return (size, i386RegMemOper(opers[0], opersize, disp=imm))
            else:
                return i386ImmMemOper(imm, opersize)
        elif mod == 2:
            imm = e_bits.parsebytes(bytez, offset + size, 2)
            size += 2
            if len(opers) == 2:
                return i386SibOper(opersize,
                                   reg=opers[0],
                                   disp=imm,
                                   index=opers[1],
                                   scale=1)
            elif len(opers) == 1:
                return (size, i386RegMemOper(opers[0], opersize, disp=imm))
            else:
                return (size, i386ImmMemOper(imm, opersize))
        elif mod == 3:
            if opersize == 1:
                rm = self.byteRegOffset(rm, prefixes=prefixes)
            elif opersize == 2:
                rm += RMETA_LOW16
            return (size, i386RegOper(rm + regbase, opersize))
        else:
            raise Exception("(16bit) How does mod == %d" % mod)
Exemplo n.º 22
0
    def extended_parse_modrm(self,
                             bytez,
                             offset,
                             opersize,
                             regbase=0,
                             prefixes=0):
        """
        Return a tuple of (size, Operand)
        """
        if prefixes & PREFIX_ADDR_SIZE:
            if opersize == 4 and self.ptrsize == 4:
                return self.shortend_parse_modrm(bytez,
                                                 offset,
                                                 opersize,
                                                 regbase=regbase,
                                                 prefixes=prefixes)

        mod, reg, rm = self.parse_modrm(bytez[offset])

        size = 1

        if mod == 3:  # Easy one, just a reg
            # FIXME only use self.byteRegOffset in 32 bit mode, NOT 64 bit...
            if opersize == 1:
                rm = self.byteRegOffset(rm, prefixes=prefixes)
            elif opersize == 2:
                rm += RMETA_LOW16
            return (size, i386RegOper(rm + regbase, opersize))

        elif mod == 0:
            # means we are [reg] unless rm == 4 (SIB) or rm == 5 ([imm32])
            # BUT JOKES -- the table is totally different in 16 bit mode BECAUSE WHY
            if rm == 5:
                imm = e_bits.parsebytes(bytez, offset + size, 4)
                size += 4
                # NOTE: in 64 bit mode, *this* is where we differ, (This case is RIP relative)
                return (size, i386ImmMemOper(imm, opersize))

            elif rm == 4:
                sibsize, scale, index, base, imm = self.parse_sib(
                    bytez, offset + size, mod, prefixes=prefixes)
                size += sibsize
                if base is not None:
                    base += regbase  # Adjust for different register addressing modes
                if index is not None:
                    index += regbase  # Adjust for different register addressing modes
                oper = i386SibOper(opersize,
                                   reg=base,
                                   imm=imm,
                                   index=index,
                                   scale=scale_lookup[scale])
                return (size, oper)

            else:
                return (size, i386RegMemOper(regbase + rm, opersize))

        elif mod == 1:
            # mod 1 means we are [ reg + disp8 ] (unless rm == 4 which means sib + disp8)
            if rm == 4:
                sibsize, scale, index, base, imm = self.parse_sib(
                    bytez, offset + size, mod, prefixes=prefixes)
                size += sibsize
                disp = e_bits.parsebytes(bytez, offset + size, 1, sign=True)
                size += 1
                if base is not None:
                    base += regbase  # Adjust for different register addressing modes
                if index is not None:
                    index += regbase  # Adjust for different register addressing modes
                oper = i386SibOper(opersize,
                                   reg=base,
                                   index=index,
                                   scale=scale_lookup[scale],
                                   disp=disp)
                return (size, oper)
            else:
                x = e_bits.signed(bytez[offset + size], 1)
                size += 1
                return (size, i386RegMemOper(regbase + rm, opersize, disp=x))

        elif mod == 2:
            # Means we are [ reg + disp32 ] (unless rm == 4  which means SIB + disp32)
            if rm == 4:
                sibsize, scale, index, base, imm = self.parse_sib(
                    bytez, offset + size, mod, prefixes=prefixes)
                size += sibsize
                disp = e_bits.parsebytes(bytez, offset + size, 4, sign=True)
                size += 4
                if base is not None:
                    base += regbase  # Adjust for different register addressing modes
                if index is not None:
                    index += regbase  # Adjust for different register addressing modes
                oper = i386SibOper(opersize,
                                   reg=base,
                                   imm=imm,
                                   index=index,
                                   scale=scale_lookup[scale],
                                   disp=disp)
                return (size, oper)

            else:
                # NOTE: Immediate displacements in SIB are still 4 bytes in 64 bit mode
                disp = e_bits.parsebytes(bytez, offset + size, 4, sign=True)
                size += 4
                return (size, i386RegMemOper(regbase + rm, opersize,
                                             disp=disp))

        else:
            raise Exception("How does mod == %d" % mod)