# HG changeset patch # User Thinker K.F. Li # Date 1313416299 -28800 # Node ID d4533a59c694d0b011a9e4c220d57fed8a8a4958 # Parent 90e181f2a0c5ad33645e1196b52e8ff19db6ef25 inject_classdefs() also inject relative _DEX_StringIds. diff -r 90e181f2a0c5 -r d4533a59c694 paraspace/dexfile.py --- a/paraspace/dexfile.py Mon Aug 15 19:32:46 2011 +0800 +++ b/paraspace/dexfile.py Mon Aug 15 21:51:39 2011 +0800 @@ -2354,6 +2354,10 @@ protoid.returnTypeIdx = rtype protoid.parametersOffRef = param_cond return protoid + + ## \brief Return _DEX_StringId of given index. + def find_strid_idx(self, idx): + return self.stringIds.items[idx] pass diff -r 90e181f2a0c5 -r d4533a59c694 paraspace/injection.py --- a/paraspace/injection.py Mon Aug 15 19:32:46 2011 +0800 +++ b/paraspace/injection.py Mon Aug 15 21:51:39 2011 +0800 @@ -284,13 +284,15 @@ pass return classdefs, undef_typeids - typeidxs = collect_typeidxs_mentioned_by_class(dex, classdef) + typeidxs, stridxs = \ + collect_typeidxs_stridxs_mentioned_by_class(dex, classdef) typeids = [dex.find_typeid_idx(typeidx) for typeidx in typeidxs] + strids = [dex.find_strid_idx(idx) for idx in stridxs] classdefs, typeids = classify_typeids_defined(dex, typeids) - return classdefs, typeids + return classdefs, typeids, strids def dexfile_insert_classdefs(dex_dst, dex_src, classdefs): @@ -299,6 +301,19 @@ return clones +## \brief Insert _DEX_StringId into another DEX. +def dexfile_insert_stringid(dex_dst, dex_src, strid): + clone = _clone_composite(dex_dst, strid) + return clone + + +## \brief Insert _DEX_StringIds into another DEX. +def dexfile_insert_stringids(dex_dst, dex_src, strids): + clones = [dexfile_insert_stringid(dex_dst, dex_src, strid) + for strid in strids] + return clones + + ## \brief Clone and insert a _DEX_TypeId to another DEXFile_linked. # # \param dex_dst is a DEXFile_linked where the cloning one is inserted. @@ -356,18 +371,20 @@ def collect_classdefs_relative(dex, classdefs): rel_classdefs = set(classdefs) rel_typeids = set() + rel_strids = set() classdef_queue = list(classdefs) while classdef_queue: cur_classdef = classdef_queue.pop(0) - classdefs, typeids = _find_class_relative(dex, cur_classdef) + classdefs, typeids, strids = _find_class_relative(dex, cur_classdef) rel_typeids.update(typeids) new_classdefs = list(set(classdefs) - rel_classdefs) classdef_queue = classdef_queue + new_classdefs rel_classdefs.update(new_classdefs) + rel_strids.update(strids) pass - return rel_classdefs, rel_typeids + return rel_classdefs, rel_typeids, rel_strids ## \brief Clone and insert given and relative classes into another DEXFile. @@ -388,7 +405,7 @@ return True return False - relative_classdefs, relative_typeids = \ + relative_classdefs, relative_typeids, relative_strids = \ collect_classdefs_relative(dex_src, classdefs) for classdef in relative_classdefs: @@ -401,8 +418,10 @@ dexfile_insert_classdefs(dex_dst, dex_src, relative_classdefs) cloning_typeids = \ dexfile_insert_or_merge_typeids(dex_dst, dex_src, relative_typeids) + cloning_strids = \ + dexfile_insert_stringids(dex_dst, dex_src, relative_strids) - return cloning_classdefs, cloning_typeids + return cloning_classdefs, cloning_typeids, cloning_strids ## \brief Redirect types, methods and strings for the code of given method. @@ -592,12 +611,12 @@ pass -## \brief Collect all type indices mentioned in the code of given method. +## \brief Collect all type and string indices mentioned in the method code. # # \param method is a \ref _DEX_Method. # \return a list of type indices mentioned in the code. # -def collect_typeidxs_in_method(dex, method): +def collect_typeidxs_stridxs_in_method(dex, method): from paraspace.dexfile import _DEX_Method, DEXFile_linked from paraspace.dalvik_opcodes import decode_insn_blk, all_opcodes from itertools import chain @@ -614,7 +633,7 @@ code, args = op_vector if code == all_opcodes.OP_NEW_INSTANCE: - return (args[1],) + return args[1] if code in (all_opcodes.OP_INVOKE_DIRECT, all_opcodes.OP_INVOKE_VIRTUAL, @@ -623,7 +642,7 @@ all_opcodes.OP_INVOKE_INTERFACE): methodidx = args[2] method_typeidx = get_typeidx_methodidx(methodidx) - return (method_typeidx,) + return method_typeidx if code in (all_opcodes.OP_INVOKE_VIRTUAL_RANGE, all_opcodes.OP_INVOKE_DIRECT_RANGE, @@ -632,33 +651,48 @@ all_opcodes.OP_INVOKE_INTERFACE_RANGE): methodidx = args[1] method_typeidx = get_typeidx_methodidx(methodidx) - return (method_typeidx,) + return method_typeidx + + return None + + def collect_strings_in_op_vector(op_vector): + code, args = op_vector + if code == all_opcodes.OP_CONST_STRING: + stridx = args[1] + return stridx - return () + return None code_blk = DEXFile_linked.get_code_block_method(method) op_vectors = decode_insn_blk(code_blk) types_insns = [collect_types_in_op_vector(op_vector) for op_vector in op_vectors] - typeidxs = list(chain(*types_insns)) + typeidxs = [idx for idx in types_insns if idx is not None] + + strs_insns = [collect_strings_in_op_vector(op_vectors) + for op_vectors in op_vectors] + stridxs = [idx for idx in strs_insns if idx is not None] - return typeidxs + return typeidxs, stridxs -## \brief Collect all type indices mentioned by the code of given class. -def collect_typeidxs_mentioned_by_class(dex, classdef): +## \brief Collect all type and string indices mentioned by the class code. +def collect_typeidxs_stridxs_mentioned_by_class(dex, classdef): from paraspace.dexfile import DEXFile_linked assert isinstance(dex, DEXFile_linked) typeidxs = set() + stridxs = set() methods = DEXFile_linked.get_methods_classdef(classdef) for method in methods: - method_typeidxs = collect_typeidxs_in_method(dex, method) + method_typeidxs, method_stridxs = \ + collect_typeidxs_stridxs_in_method(dex, method) typeidxs.update(method_typeidxs) + stridxs.update(method_stridxs) pass - return list(typeidxs) + return list(typeidxs), list(stridxs) ## \brief Make a mapping for type indices of injection. @@ -690,7 +724,7 @@ ## \brief Redirect code for methods of injected classes. def redirect_injected_code(dex_dst, dex_src, classdefs): - relative_classdefs, relative_typeids = \ + relative_classdefs, relative_typeids, relative_strids = \ collect_classdefs_relative(dex_src, classdefs) typeidxs_redir = \ @@ -724,7 +758,7 @@ assert isinstance(dex_dst, DEXFile_linked) assert isinstance(dex_src, DEXFile_linked) - injected_classdefs, injected_typeids = \ + injected_classdefs, injected_typeids, injected_strids = \ dexfile_insert_classdefs_relative(dex_dst, dex_src, classdefs) redirect_injected_code(dex_dst, dex_src, classdefs) return injected_classdefs diff -r 90e181f2a0c5 -r d4533a59c694 paraspace/tests/injection_test.py --- a/paraspace/tests/injection_test.py Mon Aug 15 19:32:46 2011 +0800 +++ b/paraspace/tests/injection_test.py Mon Aug 15 21:51:39 2011 +0800 @@ -181,8 +181,8 @@ def collect_types_in_method_test(): from paraspace.dex_deptracker import prepare_dep_decls - from paraspace.injection import collect_typeidxs_in_method - from paraspace.injection import collect_typeidxs_mentioned_by_class + from paraspace.injection import collect_typeidxs_stridxs_in_method + from paraspace.injection import collect_typeidxs_stridxs_mentioned_by_class from paraspace.dexfile import DEXFile_linked _install_dexfile_4_deptracker() @@ -203,15 +203,17 @@ init_method = fakefile_linked.find_method_name('', fakefile_def) - typeidxs = collect_typeidxs_in_method(fakefile_linked, init_method) + typeidxs, stridxs = \ + collect_typeidxs_stridxs_in_method(fakefile_linked, init_method) assert len(typeidxs) == 1 typeid = fakefile_linked.find_typeid_idx(typeidxs[0]) typeid_name = DEXFile_linked.get_typeid_name(typeid) assert typeid_name == 'Ljava/io/File;' - typeidxs = collect_typeidxs_mentioned_by_class(fakefile_linked, - fakefile_def) + typeidxs, stridxs = \ + collect_typeidxs_stridxs_mentioned_by_class(fakefile_linked, \ + fakefile_def) assert len(typeidxs) == 1 typeid = fakefile_linked.find_typeid_idx(typeidxs[0]) @@ -261,9 +263,10 @@ assert fakefile_dataheader.directMethodsSize == 1 assert fakefile_dataheader.virtualMethodsSize == 0 - classdefs, typeids = dexfile_insert_classdefs_relative(helloworld_linked, - fakefile_linked, - [fakefile_def]) + classdefs, typeids, strids = \ + dexfile_insert_classdefs_relative(helloworld_linked, \ + fakefile_linked, \ + [fakefile_def]) assert classdefs assert len(classdefs) == 1 assert classdefs[0] != fakefile_def