def inject(self, smali_tree, level): # get a copy of smali tree st = copy.deepcopy(smali_tree) # load api database print "Loading and processing API database..." level = self.load_api(level) print "Target API Level: %d" % level # check and fix apis in API_LIST method_descs = [] for m in self.entries: c = "" api_name = "" method_name = "" ia = m.find("->") ilb = m.find('(') if ia >= 0: c = m[:ia] if ilb >= 0: method_name = m[ia + 2:ilb] api_name = m[ia + 2:] else: method_name = m[ia + 2:] else: c = m if not self.android_api.classes.has_key(c): print "[Warn] Class not found in API-%d db: %s" % (level, m) continue # just class name if not method_name: ms = self.android_api.classes[c].methods.keys() method_descs.extend(ms) # full signature elif api_name: if not self.android_api.classes[c].methods.has_key(m): if method_name == "<init>": print "[Warn] Method not found in API-%d db: %s" % (level, m) continue c_obj = self.android_api.classes[c] existed = False q = c_obj.supers while q: cn = q.pop(0) c_obj = self.android_api.classes[cn] nm = c_obj.desc + "->" + api_name if c_obj.methods.has_key(nm): existed = True if not nm in self.entries: print "[Warn] Inferred API: %s" % (nm, ) method_descs.append(nm) else: q.extend(self.android_api.classes[cn].supers) if not existed: print "[Warn] Method not found in API-%d db: %s" % (level, m) else: method_descs.append(m) # signature without parameters else: own = False if self.android_api.classes[c].methods_by_name.has_key(method_name): ms = self.android_api.classes[c].methods_by_name[method_name] method_descs.extend(ms) own = True if method_name == "<init>": continue c_obj = self.android_api.classes[c] existed = False q = c_obj.supers while q: cn = q.pop(0) c_obj = self.android_api.classes[cn] if c_obj.methods_by_name.has_key(method_name): existed = True inferred = "%s->%s" % (c_obj.desc, method_name) if not inferred in self.entries: print "[Warn] Inferred API: %s" % inferred method_descs.extend(c_obj.methods_by_name[method_name]) else: q.extend(self.android_api.classes[cn].supers) if (not own) and (not existed): print "[Warn] Method not found in API-%d db: %s" % (level, m) self.method_descs = list(set(method_descs)) """ print "**************************" self.method_descs.sort() print "\n".join(self.method_descs) print "**************************" """ for m in self.method_descs: self.api_dict[m] = "" ia = m.find("->") ilb = m.find('(') if m[ia + 2:ilb] != "<init>": self.api_name_dict[m[ia + 2:]] = m[:ia] print "Done!" print "Injecting..." for c in st.classes: class_ = AndroidClass() class_.isAPI = False class_.desc = c.name class_.name= c.name[1:-1].replace('/', '.') class_.access = c.access if "interface" in c.access: class_.supers.extend(c.implements) else: class_.implements = c.implements class_.supers.append(c.super_name) for m in c.methods: method = AndroidMethod() method.isAPI = False method.desc = "%s->%s" % (c.name, m.descriptor) method.name = m.descriptor.split('(', 1)[0] #print method.desc method.sdesc = method.desc[:method.desc.rfind(')') + 1] method.access = m.access class_.methods[method.sdesc] = method self.android_api.add_class(class_) self.android_api.build_connections(False) #self.android_api.show_not_API() for c in st.classes: for m in c.methods: i = 0 while i < len(m.insns): insn = m.insns[i] if insn.fmt == "35c": md = insn.obj.method_desc on = insn.opcode_name irb = md.find(')') smd = md[:irb + 1] if self.api_dict.has_key(smd): method_type = METHOD_TYPE_BY_OPCODE[on] new_on = OPCODE_MAP[on] if not self.method_map.has_key(md): self.add_stub_method(on, md) if method_type == "constructor": insn_m = copy.deepcopy(insn) insn_m.obj.replace(new_on, \ self.method_map[md]) r = insn_m.obj.registers.pop(0) m.insert_insn(insn_m, i , 0) i += 1 """ insn.obj.replace(new_on, \ self.method_map[md]) r = insn.obj.registers.pop(0) m.insert_insn(InsnNode(\ "move-result-object %s" % r), i + 1, 0) i += 1 """ else: insn.obj.replace(new_on, \ self.method_map[md]) else: ia = md.find("->") cn = md[:ia] api_name = smd[ia + 2:] if self.api_name_dict.has_key(api_name): if self.android_api.classes.has_key(cn): if not self.android_api.classes[cn].methods.has_key(smd): api_cn = self.api_name_dict[api_name] if api_cn in self.android_api.classes[cn].ancestors: self.api_dict[smd] = "" i -= 1 elif insn.fmt == "3rc": md = insn.obj.method_desc on = insn.opcode_name smd = md[:md.rfind(')') + 1] if self.api_dict.has_key(smd): method_type = METHOD_TYPE_BY_OPCODE[on] new_on = OPCODE_MAP[on] if not self.method_map.has_key(md): self.add_stub_method(on, md) if method_type == "constructor": insn_m = copy.deepcopy(insn) insn_m.obj.replace(new_on, \ self.method_map[md]) r = insn_m.obj.reg_start nr = r[0] + str(int(r[1:]) + 1) insn_m.obj.set_reg_start(nr) m.insert_insn(insn_m, i , 0) i += 1 """ insn.obj.replace(new_on, \ self.method_map[md]) r = insn.obj.reg_start nr = r[0] + str(int(r[1:]) + 1) insn.obj.set_reg_start(nr) m.insert_insn(InsnNode(\ "move-result-object %s" % r), i + 1, 0) i += 1 """ else: insn.obj.replace(new_on, \ self.method_map[md]) else: ia = md.find("->") cn = md[:ia] api_name = smd[ia + 2:] if self.api_name_dict.has_key(api_name): if self.android_api.classes.has_key(cn): if not self.android_api.classes[cn].methods.has_key(smd): api_cn = self.api_name_dict[api_name] if api_cn in self.android_api.classes[cn].ancestors: self.api_dict[smd] = "" i -= 1 i += 1 for c in self.stub_classes.values(): st.add_class(c) st.add_class(self.helper) print "Done!" return st