def inspect(ctxt, oid): 'inspect an object' ctxt.sess.suspend() try: oid = long(oid) rtval = find_object(ctxt, oid) if rtval is None: andbug.screed.section('object <%s> not found' % oid) else: obj, thread = rtval with andbug.screed.section( 'object <%s> %s in %s' % (str(obj.oid), str(obj.jni), str(thread))): log.debug( "study", "In inspect obj.oid=" + str(obj.oid) + "\t jni=" + str(obj.jni) + "\t thread=" + str(thread)) for k, v in obj.fields.items(): log.debug( "study", "In inspect k=" + str(k) + "\t v=" + str(v) + "\t type=" + type(v).__name__) andbug.screed.item('%s=%s <%s>' % (k, v, type(v).__name__)) except ValueError: print('!! error, invalid oid param. expecting <long> and got <%s>.' % type(oid).__name__) finally: ctxt.sess.resume()
def adb(*args): log.debug(adb, ' '.join(map(str, args))) try: return sh(seq("adb", *args)) except OSError as err: raise ConfigError( 'could not find "adb" from the Android SDK in your PATH')
def find_object(ctxt, oid): for t in ctxt.sess.threads(): for f in t.frames: for k, v in f.values.items(): log.debug("study", "In inspect.find_object k=" + str(k) + "\t v=" + str(v)) if type(v) is andbug.vm.Object and v.oid == oid: return (v, t) #v:变量的值, t:所在的线程信息 return None
def processResponse(self, ident, code, data): 'internal to the i/o thread w/ recv ctrl; processes incoming response' log.debug("study", "In Connection.processResponse ident=" + str(ident) + "\t code=" + str(code) + "\t data=") chan = self.qmap.pop(ident, None) #从字典中读取,并删除该数据 if not chan: return buf = JdwpBuffer() buf.config(*self.sizes) buf.prepareUnpack(data) return chan.put((code, buf))
def processRequest(self, ident, code, data): 'internal to the i/o thread w/ recv ctrl; processes incoming request' log.debug("study", "In Connection.processRequest ident=" + str(ident) + "\t code=" + str(code) + "\t data=") chan = self.rmap.get(code) #所有中断都由该chan队列处理,每次只是从rmap读出内容,而没有将rmap对应的chan清除 if not chan: return #TODO buf = JdwpBuffer() buf.config(*self.sizes) buf.prepareUnpack(data) return chan.put((ident, buf)) #将解析后的数据压入队列中
def processBind(self, qr, ident, chan): 'internal[内部的] to i/o thread; performs a query or request bind' #根据qr值的不同,以ident为关键字,以chan为值,放入不同的字典中 log.debug("study", "In Connection(Thread).processBind qr=" + str(qr) + "\t ident=" + str(ident) + "\t chan=" + str(chan)) log.debug("study", "++bindqueue.get FOR q ++") if qr == 'q': self.qmap[ident] = chan elif qr == 'r': self.rmap[ident] = chan
def find_object(ctxt, oid): for t in ctxt.sess.threads(): for f in t.frames: for k, v in f.values.items(): log.debug( "study", "In inspect.find_object k=" + str(k) + "\t v=" + str(v)) if type(v) is andbug.vm.Object and v.oid == oid: return (v, t) #v:变量的值, t:所在的线程信息 return None
def hook(self, code, chan): ''' when code requests are received, they will be put in chan for processing ''' #使用锁 with self.xmitlock: self.bindqueue.put(('r', code, chan)) #加入一个先进先出的队列 log.debug("study", "++ for hook function bindqueue.put FOR r ++ code=" + str(code))
def methods(ctxt, cpath, mquery=None): 'lists the methods of a class' cpath, mname, mjni = andbug.options.parse_mquery(cpath, mquery) #cpath=Lcom/example/test/MainActivity; mname=onCreate [函数名] mjni=None[可能是参数信息不确定] infor = "cpath="+ str(cpath) + "\t mname="+ str(mname) + "\t mjni=" + str(mjni); log.debug("study", infor); title = "Methods " + ((cpath + "->" + mquery) if mquery else (cpath)) with andbug.screed.section(title): for m in ctxt.sess.classes(cpath).methods(filtername=mname, jni=mjni): andbug.screed.item(str(m))
def methods(ctxt, cpath, mquery=None): 'lists the methods of a class' cpath, mname, mjni = andbug.options.parse_mquery( cpath, mquery ) #cpath=Lcom/example/test/MainActivity; mname=onCreate [函数名] mjni=None[可能是参数信息不确定] infor = "cpath=" + str(cpath) + "\t mname=" + str( mname) + "\t mjni=" + str(mjni) log.debug("study", infor) title = "Methods " + ((cpath + "->" + mquery) if mquery else (cpath)) with andbug.screed.section(title): for m in ctxt.sess.classes(cpath).methods(filtername=mname, jni=mjni): andbug.screed.item(str(m))
def report_hit(t): ''' 处理METHOD_ENTRY事件回调函数, t有两个参数,分别 t[0] thread t[1] Location ''' t = t[0] #t是一个Thread类型的变量 with andbug.screed.section("Breakpoint hit in %s, process suspended." % t): t.sess.suspend() #暂停当前线程 for f in t.frames: #t.frames是返回当前的堆栈信息 name = str(f.loc) if f.native: #判断堆栈中函数的类型,是否是内部函数。如dalvik.system.NativeStart.main([Ljava/lang/String;)V <native> name += ' <native>' with andbug.screed.refer(name): log.debug("study", "function name:" + str(name) ) parse_frame_detail(f)
def report_hit(t): ''' 处理METHOD_ENTRY事件回调函数, t有两个参数,分别 t[0] thread t[1] Location ''' t = t[0] #t是一个Thread类型的变量 with andbug.screed.section("Breakpoint hit in %s, process suspended." % t): t.sess.suspend() #暂停当前线程 for f in t.frames: #t.frames是返回当前的堆栈信息 name = str(f.loc) if f.native: #判断堆栈中函数的类型,是否是内部函数。如dalvik.system.NativeStart.main([Ljava/lang/String;)V <native> name += ' <native>' with andbug.screed.refer(name): log.debug("study", "function name:" + str(name)) parse_frame_detail(f)
def process(self): 'invoked repeatedly by the processing thread' size, ident, flags, code = self.readHeader() #TODO: HANDLE CLOSE #读取数据头,包含一下元素size、ident、flags、code log.debug("study", "In Connection(Thread).process size=" + str(size) + "\t ident="+ str(ident) + "\t flags=" +str(flags) + "\t code=" + str(code)) data = self.read(size) #TODO: HANDLE CLOSE #根据Header中的长度信息,读取具体数据。 try: # We process binds[绑定] after receiving messages to prevent a race while True: self.processBind(*self.bindqueue.get(False)) #bindqueue.get(False)参数为False,队列将引发Empty异常 except EmptyQueue: log.debug("study", "Except for Empty Queue") pass #TODO: update binds with all from bindqueue #对于来自虚拟机的事件消息,self.processBind(*self.bindqueue.get(False))不起作用,直接触发EmptyQueue异常,后续调用processRequest函数 if flags == 0x80: self.processResponse(ident, code, data) #答复数据包的flag是0x80 else: self.processRequest(ident, code, data) #请求数据包的flag是0x00
def inspect(ctxt, oid): 'inspect an object' ctxt.sess.suspend() try: oid = long(oid) rtval = find_object(ctxt, oid) if rtval is None: andbug.screed.section('object <%s> not found' % oid) else: obj, thread = rtval with andbug.screed.section('object <%s> %s in %s' % (str(obj.oid), str(obj.jni), str(thread))): log.debug("study", "In inspect obj.oid=" + str(obj.oid) + "\t jni=" + str(obj.jni) + "\t thread=" + str(thread)) for k, v in obj.fields.items(): log.debug("study", "In inspect k=" + str(k) + "\t v=" + str(v) + "\t type=" + type(v).__name__) andbug.screed.item('%s=%s <%s>' % (k, v, type(v).__name__)) except ValueError: print('!! error, invalid oid param. expecting <long> and got <%s>.' % type(oid).__name__) finally: ctxt.sess.resume()
def request(self, code, data='', timeout=None): 'send a request, then waits for a response; returns response' queue = Queue() log.debug("study", "In Connection.request code=" + str(code) + "\t data=" + str(data)) with self.xmitlock: ident = self.acquireIdent() self.bindqueue.put(('q', ident, queue)) #每发送一个请求向bindqueue中压入一个数据 log.debug("study", "++bindqueue.put FOR q ++") self.writeContent(ident, 0x0, code, data) try: log.debug("study", "wait_code:" + str(code)) return queue.get(1, timeout) #向虚拟机发出指令后一直处于等待状态,知道queue队列中出现返回信息,接下来处理 except EmptyQueue: return None, None
def adb(*args): log.debug(adb, ' '.join(map(str, args))) try: return sh(seq("adb", *args)) except OSError as err: raise ConfigError('could not find "adb" from the Android SDK in your PATH')