Ejemplo n.º 1
0
class Slot(SessionElement):
    def __init__(self, sess, tid, mid, index):
        SessionElement.__init__(self, sess)
        self.tid = tid
        self.mid = mid
        self.index = index
        self.name = None

    def __str__(self):
        if self.name:
            return 'slot %s at index %i' % (self.name, self.index)
        else:
            return 'slot at index %i' % (self.index)

    def load_slot(self):
        self.sess.pool(Class, self.sess, tid).load_slots()

    firstLoc = defer(load_slot, 'firstLoc')
    locLength = defer(load_slot, 'locLength')
    name = defer(load_slot, 'name')
    jni = defer(load_slot, 'jni')
    gen = defer(load_slot, 'gen')

    @property
    def tag(self):
        return ord(self.jni[0])
Ejemplo n.º 2
0
class Object(Value):
    def __init__(self, sess, oid):
        if oid == 0: raise VoidError()
        SessionElement.__init__(self, sess)
        self.oid = oid

    def __repr__(self):
        return '<obj %s #%x>' % (self.jni, self.oid)

#    def __str__(self):
#        return str(self.fields.values())

    def __str__(self):
        return str("%s <%s>" % (str(self.jni), str(self.oid)))

    @classmethod
    def unpackFrom(impl, sess, buf):
        oid = buf.unpackObjectId()
        # oid = 0 indicates a GC omgfuckup in Dalvik
        # which is NOT as uncommon as we would like..
        if not oid: return None
        return sess.pool(impl, sess, oid)

    def packTo(self, buf):
        buf.packObjectId(self.oid)

    @property
    def gen(self):
        return self.refType.gen

    @property
    def jni(self):
        return self.refType.jni

    def load_refType(self):
        conn = self.sess.conn
        buf = conn.buffer()
        self.packTo(buf)
        code, buf = conn.request(0x0901, buf.data())
        if code != 0:
            raise RequestError(code)
        self.refType = RefType.unpackFrom(self.sess, buf)

    refType = defer(load_refType, 'refType')

    @property
    def fieldList(self):
        r = list(f for f in self.refType.fieldList if not f.static)
        return r

    @property
    def typeTag(self):
        return self.refType.tag

    @property
    def fields(self):
        sess = self.sess
        conn = self.conn
        buf = conn.buffer()
        buf.packTypeId(self.oid)
        fields = self.fieldList
        buf.packInt(len(fields))
        for field in fields:
            buf.packFieldId(field.fid)
        code, buf = conn.request(0x0902, buf.data())
        if code != 0:
            raise RequestError(code)
        ct = buf.unpackInt()
        vals = {}
        for x in range(ct):
            f = fields[x]
            vals[f.name] = unpack_value(sess, buf)

        return vals
Ejemplo n.º 3
0
class Session(object):
    def __init__(self, conn):
        self.pool = andbug.data.pool()
        self.conn = conn
        self.emap = {}
        self.ectl = Lock()
        self.evtq = Queue()
        conn.hook(0x4064, self.evtq)
        self.ethd = threading.Thread(name='Session', target=self.run)
        self.ethd.daemon = 1
        self.ethd.start()

    def run(self):
        while True:
            self.processEvent(*self.evtq.get())

    def hook(self, ident, func=None, queue=None, origin=None):
        return Hook(self, ident, func, queue, origin)

    def processEvent(self, ident, buf):
        pol, ct = buf.unpack('1i')

        for i in range(0, ct):
            ek = buf.unpackU8()
            im = unpack_impl[ek]
            if im is None:
                raise RequestError(ek)
            evt = im(self, buf)
            with self.ectl:
                hook = self.emap.get(evt[0])
            if hook is not None:
                hook.put(evt[1:])

    def load_classes(self):
        code, buf = self.conn.request(0x0114)
        if code != 0:
            raise RequestError(code)

        def load_class():
            tag, tid, jni, gen, flags = buf.unpack('1t$$i')
            obj = self.pool(Class, self, tid)
            obj.tag = tag
            obj.tid = tid
            obj.jni = jni
            obj.gen = gen
            obj.flags = flags
            return obj

        ct = buf.unpackU32()

        self.classList = andbug.data.view(load_class() for i in range(0, ct))
        self.classByJni = andbug.data.multidict()
        for item in self.classList:
            self.classByJni[item.jni] = item

    classList = defer(load_classes, 'classList')
    classByJni = defer(load_classes, 'classByJni')

    def classes(self, jni=None):
        if jni:
            seq = self.classByJni[jni]
        else:
            seq = self.classList
        return andbug.data.view(seq)

    def suspend(self):
        code, buf = self.conn.request(0x0108, '')
        if code != 0:
            raise RequestError(code)

    @property
    def count(self):
        code, buf = self.conn.request(0x0108, '')
        if code != 0:
            raise RequestError(code)

    def resume(self):
        code, buf = self.conn.request(0x0109, '')
        if code != 0:
            raise RequestError(code)

    def exit(self, code=0):
        conn = self.conn
        buf = conn.buffer()
        buf.pack('i', code)
        code, buf = conn.request(0x010A, '')
        if code != 0:
            raise RequestError(code)

    def threads(self, name=None):
        pool = self.pool
        code, buf = self.conn.request(0x0104, '')
        if code != 0:
            raise RequestError(code)
        ct = buf.unpackInt()

        def load_thread():
            tid = buf.unpackObjectId()
            return pool(Thread, self, tid)

        seq = (load_thread() for x in range(0, ct))
        if name is not None:
            if rx_dalvik_tname.match(name):
                seq = (t for t in seq if t.name == name)
            else:
                seq = (t for t in seq if t.name.split(' ', 1)[-1] == name)
        return andbug.data.view(seq)
Ejemplo n.º 4
0
class RefType(SessionElement):
    def __init__(self, sess, tag, tid):
        SessionElement.__init__(self, sess)
        self.tag = tag
        self.tid = tid

    def __repr__(self):
        return '<type %s %s#%x>' % (self.jni, chr(self.tag), self.tid)

    def __str__(self):
        return repr(self)

    @classmethod
    def unpackFrom(impl, sess, buf):
        return sess.pool(impl, sess, buf.unpackU8(), buf.unpackTypeId())

    def packTo(self, buf):
        buf.packObjectId(self.tid)

    def load_signature(self):
        conn = self.conn
        buf = conn.buffer()
        self.packTo(buf)
        code, buf = conn.request(0x020d, buf.data())
        if code != 0:
            raise RequestError(code)
        self.jni = buf.unpackStr()
        self.gen = buf.unpackStr()

    gen = defer(load_signature, 'gen')
    jni = defer(load_signature, 'jni')

    def load_fields(self):
        sess = self.sess
        conn = self.conn
        buf = conn.buffer()
        buf.pack("t", self.tid)
        code, buf = conn.request(0x020E, buf.data())
        if code != 0:
            raise RequestError(code)

        ct = buf.unpackU32()

        def load_field():
            field = Field.unpackFrom(sess, buf)
            name, jni, gen, flags = buf.unpack('$$$i')
            field.name = name
            field.jni = jni
            field.gen = gen
            field.flags = flags
            return field

        self.fieldList = andbug.data.view(load_field() for i in range(ct))

    fieldList = defer(load_fields, 'fieldList')

    @property
    def statics(self):
        sess = self.sess
        conn = self.conn
        buf = conn.buffer()
        buf.packTypeId(self.tid)
        fields = list(f for f in self.fieldList if f.static)
        buf.packInt(len(fields))
        for field in fields:
            buf.packFieldId(field.fid)
        code, buf = conn.request(0x0206, buf.data())
        if code != 0:
            raise RequestError(code)
        ct = buf.unpackInt()

        vals = {}
        for x in range(ct):
            f = fields[x]
            vals[f.name] = unpack_value(sess, buf)
        return vals

    def load_methods(self):
        tid = self.tid
        sess = self.sess
        conn = self.conn
        pool = sess.pool
        buf = conn.buffer()
        buf.pack("t", tid)
        code, buf = conn.request(0x020F, buf.data())
        if code != 0:
            raise RequestError(code)

        ct = buf.unpackU32()

        def load_method():
            mid, name, jni, gen, flags = buf.unpack('m$$$i')
            obj = pool(Method, sess, tid, mid)
            obj.name = name
            obj.jni = jni
            obj.gen = gen
            obj.flags = flags
            return obj

        self.methodList = andbug.data.view(load_method() for i in range(0, ct))
        self.methodByJni = andbug.data.multidict()
        self.methodByName = andbug.data.multidict()

        for item in self.methodList:
            jni = item.jni
            name = item.name
            self.methodByJni[jni] = item
            self.methodByName[name] = item

    methodList = defer(load_methods, 'methodList')
    methodByJni = defer(load_methods, 'methodByJni')
    methodByName = defer(load_methods, 'methodByName')

    methodList = defer(load_methods, 'methodList')
    methodByJni = defer(load_methods, 'methodByJni')
    methodByName = defer(load_methods, 'methodByName')

    def methods(self, name=None, jni=None):
        if name and jni:
            seq = self.methodByName[name]
            seq = filter(x in seq, self.methodByJni[jni])
        elif name:
            seq = andbug.data.view(self.methodByName[name])
        elif jni:
            seq = self.methodByJni[jni]
        else:
            seq = self.methodList
        return andbug.data.view(seq)

    @property
    def name(self):
        name = self.jni
        if name.startswith('L'): name = name[1:]
        if name.endswith(';'): name = name[:-1]
        name = name.replace('/', '.')
        return name
Ejemplo n.º 5
0
class Method(SessionElement):
    def __init__(self, sess, tid, mid):
        SessionElement.__init__(self, sess)
        self.tid = tid
        self.mid = mid

    @property
    def klass(self):
        return self.sess.pool(Class, self.sess, self.tid)

    def __str__(self):
        return '%s.%s%s' % (self.klass, self.name, self.jni)

    def __repr__(self):
        return '<method %s>' % self

    def load_line_table(self):
        sess = self.sess
        conn = sess.conn
        pool = sess.pool
        tid = self.tid
        mid = self.mid
        data = conn.buffer().pack('om', tid, mid)
        code, buf = conn.request(0x0601, data)
        if code != 0: raise RequestError(code)

        f, l, ct = buf.unpack('88i')
        if (f == -1) or (l == -1):
            self.firstLoc = None
            self.lastLoc = None
            self.lineTable = andbug.data.view([])
            #TODO: How do we handle native methods?

        self.firstLoc = pool(Location, sess, tid, mid, f)
        self.lastLoc = pool(Location, sess, tid, mid, l)

        ll = {}
        self.lineLocs = ll

        def line_loc():
            loc, line = buf.unpack('8i')
            loc = pool(Location, sess, tid, mid, loc)
            loc.line = line
            ll[line] = loc

        for i in range(0, ct):
            line_loc()

    firstLoc = defer(load_line_table, 'firstLoc')
    lastLoc = defer(load_line_table, 'lastLoc')
    lineTable = defer(load_line_table, 'lineTable')

    def load_method(self):
        self.klass.load_methods()

    name = defer(load_method, 'name')
    jni = defer(load_method, 'jni')
    gen = defer(load_method, 'gen')
    flags = defer(load_method, 'flags')

    def load_slot_table(self):
        sess = self.sess
        conn = self.conn
        pool = sess.pool
        tid = self.tid
        mid = self.mid
        data = conn.buffer().pack('om', tid, mid)
        code, buf = conn.request(0x0605, data)
        if code != 0: raise RequestError(code)

        act, sct = buf.unpack('ii')

        #TODO: Do we care about the argCnt ?

        def load_slot():
            codeIndex, name, jni, gen, codeLen, index = buf.unpack('l$$$ii')
            slot = pool(Slot, sess, tid, mid, index)
            slot.firstLoc = codeIndex
            slot.locLength = codeLen
            slot.name = name
            slot.jni = jni
            slot.gen = gen

            return slot

        self.slots = andbug.data.view(load_slot() for i in range(0, sct))

    slots = defer(load_slot_table, 'slots')