def rename_val(xml_file, object_name, param_name, filter_list=[], propagate_upd=True, verify_name='', default_value=''): objects_list = xml_file.getroot().iter(object_name) package_name = '{http://schemas.android.com/apk/res/android}' param_set_full_name = package_name + param_name if verify_name != '': param_ver_full_name = package_name + verify_name else: param_ver_full_name = param_set_full_name for obj in objects_list: param_value = obj.get(param_ver_full_name) if verify_filter(param_value, filter_list): if default_value != '': random_value = default_value else: if param_value.startswith('.'): random_value = '.a' + u.get_random(True, 32) else: random_value = 'a.' + u.get_random(True, 32) obj.set(param_set_full_name, random_value) if propagate_upd: yield param_value, random_value else: yield '!NewNoEdit!' + param_value, random_value
def append_defunct_class_now(base_dir, curr_dir, incremental): """Append a random generated class file to the class tree""" if base_dir == curr_dir: class_path = '' else: class_path = curr_dir.replace(base_dir, '') # Remove the root reference class_path = os.path.relpath(curr_dir, base_dir) defunct_class = u.get_defunct_class() random_class_name = u.get_random(True, 16) + str(incremental) defunct_class = defunct_class.replace( '*ClassName*', os.path.join(class_path, random_class_name)) # Random class name defunct_class = defunct_class.replace('*String1*', u.get_random(True, 16)) # Random string defunct_class = defunct_class.replace('*String2*', u.get_random(True, 16)) # Random string defunct_class = defunct_class.replace('*MethodName*', u.get_random(True, 16)) # Random method defunct_class = defunct_class.replace('*SourceName*', u.get_random(True, 16)) # Random source u.write_text_file(os.path.join(curr_dir, random_class_name + '.smali'), defunct_class) # Write the class file
def append_defunct_class_now(base_dir, curr_dirr, incremental): """Append a random generated class file to the class tree""" class_path = curr_dirr.replace(base_dir, '') # Remove the root reference if class_path.startswith('/'): class_path = class_path[1:] defunct_class = u.get_defunct_class() random_class_name = u.get_random(True, 16) + str(incremental) if class_path != '': class_path = class_path + '/' defunct_class = defunct_class.replace( '*ClassName*', class_path + random_class_name) # Random class name defunct_class = defunct_class.replace('*String1*', u.get_random(True, 16)) # Random string defunct_class = defunct_class.replace('*String2*', u.get_random(True, 16)) # Random string defunct_class = defunct_class.replace('*MethodName*', u.get_random(True, 16)) # Random method defunct_class = defunct_class.replace('*SourceName*', u.get_random(True, 16)) # Random source u.write_text_file(curr_dirr + '/' + random_class_name + '.smali', defunct_class) # Write the class file
def obfuscate(): """ The main obfuscator function """ init_package_name() smali_file_list = u.load_smali_file() # Load the smali files res_file_list = set(list(u.load_xml_file()) + list(smali_file_list)) # Load the XML files edited_class = set(find_all_class(smali_file_list)) change_all_class(edited_class, smali_file_list) change_all_res_file(res_file_list, set(get_res_class(edited_class)), package_name) manifest_xml = u.load_manifest() # Load the Manifest file task_affinity = 'a' + u.get_random(True, 7) + '.' + 'a' + u.get_random( True, 7) rename_list = set( list(change_package_name(manifest_xml)) + list(rename_val(manifest_xml, 'activity', 'label', ['@'], False)) + list(rename_val(manifest_xml, 'activity', 'process', ['@'], False)) + list(rename_val(manifest_xml, 'application', 'label', ['@'], False)) + list(rename_val(manifest_xml, 'provider', 'label', ['@'], False)) + list(rename_val(manifest_xml, 'provider', 'process', ['@'], False)) + list(rename_val(manifest_xml, 'activity-alias', 'name', ['@'], False)) + list(rename_val(manifest_xml, 'activity-alias', 'label', ['@'], False)) + list(rename_val(manifest_xml, 'service', 'label', ['@'], False)) + list(rename_val(manifest_xml, 'service', 'process', ['@'], False)) + list(rename_val(manifest_xml, 'receiver', 'label', ['@'], False)) + list(rename_val(manifest_xml, 'receiver', 'process', ['@'], False)) + list(rename_val(manifest_xml, 'intent-filter', 'label', ['@'], False)) + list(rename_val(manifest_xml, 'permission', 'label', ['@'], False)) + list( rename_val(manifest_xml, 'permission', 'description', ['@'], False) ) + list( rename_val(manifest_xml, 'permission-group', 'label', ['@'], False)) + list( rename_val(manifest_xml, 'permission-group', 'description', ['@'], False)) + list(rename_val(manifest_xml, 'permission-tree', 'label', ['@'], False)) + list(rename_val( manifest_xml, 'instrumentation', 'label', ['@'], False)) + list( rename_val(manifest_xml, 'action', 'name', ['@', 'com.android.', 'android.'], False)) + list( rename_val(manifest_xml, 'activity', 'taskAffinity', ['android.', 'com.android.', '@'], False, 'name', task_affinity)) + list( rename_val(manifest_xml, 'application', 'taskAffinity', ['android.', 'com.android.', '@'], False, 'name', task_affinity))) log_tag_bho(manifest_xml, 'data') change_all_res_file_package(res_file_list, rename_list) u.save_manifest(manifest_xml) # Write back the Manifest file''' fix_safe_test(smali_file_list) change_allfile(smali_file_list) change_alldir(u.load_smali_dirs())
def append_defunct_class_now(base_dir, curr_dirr, incremental): """Append a random generated class file to the class tree""" class_path = curr_dirr.replace(base_dir, '') # Remove the root reference if class_path.startswith('/'): class_path = class_path[1:] defunct_class = u.get_defunct_class() random_class_name = u.get_random(True, 16) + str(incremental) if class_path != '': class_path = class_path + '/' defunct_class = defunct_class.replace('*ClassName*', class_path + random_class_name) # Random class name defunct_class = defunct_class.replace('*String1*', u.get_random(True, 16)) # Random string defunct_class = defunct_class.replace('*String2*', u.get_random(True, 16)) # Random string defunct_class = defunct_class.replace('*MethodName*', u.get_random(True, 16)) # Random method defunct_class = defunct_class.replace('*SourceName*', u.get_random(True, 16)) # Random source u.write_text_file(curr_dirr + '/' + random_class_name + '.smali', defunct_class) # Write the class file
def rnd(self, n): """ Return an array of Lognormal random variates usage: Instance.rnd(n) Input ------ n: The number of variates Output ------ Return value: A numpy array with the random variates """ r = util.get_random() l = [] for i in xrange(n): l.append(r.gauss(0, 1)) lp = np.array(l) arnd = np.exp(self.__mu + self.__sigma*lp) return arnd
def rnd(self, n): """ Return an array of Lognormal random variates usage: Instance.rnd(n) Input ------ n: The number of variates Output ------ Return value: A numpy array with the random variates """ r = util.get_random() l = [] for i in xrange(n): l.append(r.gauss(0, 1)) lp = np.array(l) arnd = np.exp(self.__mu + self.__sigma * lp) return arnd
def rnd(self, n): """ Return an array of random variates for the truncated pareto distribution Usage: Instance.rnd(n) Input ----- n: The number of variates needed Output ------ Return value: Numpy array with n TPareto variates """ r = util.get_random() lb = pm.pow(self.__k/self.__m, self.__alpha)/(1 + pm.pow(self.__k/self.__m, self.__alpha)) ub = 1/(1 + pm.pow(self.__k/self.__m, self.__alpha)) l = [] for i in xrange(n): l.append(r.uniform(lb, ub)) lp = np.array(l) k1 = self.__k/pm.pow((1 + pm.pow(self.__k/self.__m, self.__alpha)), 1/self.__alpha) arnd = k1*np.power(lp, -1/self.__alpha) return arnd
def obfuscate(): """ The main obfuscator function """ class_name = 'a' + u.get_random(True, 7) smali_file_list = u.load_smali_file() add_crypt_method(smali_file_list, class_name) find_all_final_string_field(smali_file_list) move_string_class(class_name)
def rnd(self, n): """ Return an array of random variates for the truncated pareto distribution Usage: Instance.rnd(n) Input ----- n: The number of variates needed Output ------ Return value: Numpy array with n TPareto variates """ r = util.get_random() lb = pm.pow(self.__k / self.__m, self.__alpha) / ( 1 + pm.pow(self.__k / self.__m, self.__alpha)) ub = 1 / (1 + pm.pow(self.__k / self.__m, self.__alpha)) l = [] for i in xrange(n): l.append(r.uniform(lb, ub)) lp = np.array(l) k1 = self.__k / pm.pow( (1 + pm.pow(self.__k / self.__m, self.__alpha)), 1 / self.__alpha) arnd = k1 * np.power(lp, -1 / self.__alpha) return arnd
def load_code_block(smali_file): """Read and split smali code into code blocks""" edit_method = False # Editing a method jump_count = 0 # Current jump index for smali_line in u.open_file_input(smali_file): # For each line if is_beg_not_abstract_method( smali_line) and not edit_method: # Method start edit_method = True jump_count = 0 print smali_line, # Print the line unchanged elif is_end_method(smali_line) and edit_method: # Method end edit_method = False print smali_line, # Print the line unchanged elif edit_method: # Reading method if is_block_sign(smali_line): # Block signpost jump_name = u.get_random(True, 15) # Random jump name jump_count += 1 # Increment jump count print ' goto/32 :l_' + jump_name + '_' + str(jump_count) print ' nop' print smali_line, print ' :l_' + jump_name + '_' + str(jump_count) else: print smali_line, # Print the line unchanged else: print smali_line, # Print the line unchanged
def get_match_source_line(smali_line): """Rename a source definition""" source_match = re.search( r'^([ ]*?)\.source(.*?)\"(?P<sourceName>([^\"]*?))\"', smali_line) if source_match is not None: source_name = source_match.group( 'sourceName') # Recover the old source name smali_line = smali_line.replace(source_name, 'a' + u.get_random(True, 8) + '.java') print smali_line,
def obfuscate(): """ The main obfuscator function """ class_name = 'a' + u.get_random(True, 7) asset_file_list = list(u.load_asset_file()) crypt_files(asset_file_list) change_allfile(asset_file_list) change_alldir(u.load_asset_dirs()[:-1]) smali_file_list = u.load_smali_file() # Load smali files change_all_direct_method(smali_file_list, class_name) move_asset_class(class_name)
def add_arithmetic_dranch_in_method(smali_file): """Add a fake arithmetic branch near each valid istruction""" edit_method = False # Out Method junk_name = None this_name = None for smali_line in u.open_file_input(smali_file): # For each line #Entering non abstract method if re.search(r'^([ ]*?)\.method', smali_line) is not None and re.search(r' abstract ', smali_line) is None and re.search(r' native ', smali_line) is None and not edit_method: print smali_line, edit_method = True # In method #Exiting method elif re.search(r'^([ ]*?)\.end method', smali_line) is not None and edit_method: if junk_name is not None and this_name is not None: print ' :' + junk_name print ' goto/32 :' + this_name print smali_line, edit_method = False # Out Method junk_name = None this_name = None elif edit_method: # If in method print smali_line, locals_match = re.search(r'^([ ]*?)\.locals (?P<localCount>([0-9]+))$', smali_line) if locals_match is not None: local_count = locals_match.group('localCount') if int(local_count) >= 2: # If exist at least 2 register rand_int_v0 = u.get_random_int(1, 32) # Random integer in the first one rand_int_v1 = u.get_random_int(1, 32) # Random integer in the second one #Add the fake branch print '' print ' const v0, ' + str(rand_int_v0) print ' const v1, ' + str(rand_int_v1) print ' add-int v0, v0, v1' print ' add-int v0, v0, v1' print ' rem-int v0, v0, v1' junk_name = u.get_random(True, 15) this_name = u.get_random(True, 15) goto32_name = u.get_random(True, 15) print ' if-gtz v0, :' + goto32_name print ' goto/32 :' + junk_name print ' :' + goto32_name print ' :' + this_name else: print smali_line,
def define_code_block(smali_file, valid_op_code): """Try to define a code block""" edit_method = False # Editing a method in_try = False # In a try-catch for smali_line in u.open_file_input(smali_file): # For each line if is_beg_not_abstract_method( smali_line) and not edit_method: # Method start edit_method = True in_try = False print smali_line, # Print the line unchanged elif is_end_method(smali_line) and edit_method: # Method end edit_method = False print smali_line, # Print the line unchanged elif edit_method: line_op_code = re.search(r'^([ ]*)(?P<opCode>([^ \n]+))([ ]|$)', smali_line) # Match a line if line_op_code is not None: op_code = line_op_code.group('opCode') if re.search(r'^([ ]*?):try_start', op_code) is not None: # Try start in_try = True # In try if re.search(r'^([ ]*?):try_end_', op_code) is not None: # Try end in_try = False # Out try if op_code in valid_op_code and not in_try: print '#!Block!#' # Print block signpost new_if = if_mapping.get(op_code, None) if new_if is not None: line_op_code = re.search( r'^([ ]*)(?P<opCode>([^ ]+)) (?P<regGo>[^:]*?):(?P<labelGo>[^ ]*?)$', smali_line) # Match a line if line_op_code is not None: regGo = line_op_code.group('regGo') labelGo = line_op_code.group('labelGo') goto32_name = u.get_random(True, 15) # Random jump name print ' ' + new_if + ' ' + regGo + ':gl_' + goto32_name print ' goto/32 :' + labelGo print ' :gl_' + goto32_name else: print smali_line, else: print smali_line, # Print the line unchanged else: print smali_line, # Print the line unchanged else: print smali_line, # Print the line unchanged
def add_id_random_resource(res_root): """In the 'public.xml' add some random id resource""" last_id_index = 0 for res_line in res_root: # For each resource res_type = res_line.attrib.get('type') # Return the resource type if res_type == 'id': # Resource type is 'id' curr_id = int(res_line.attrib.get('id'), 16) if last_id_index < curr_id: # Max id last_id_index = curr_id last_id_index += 1 # Next free resource id for count_res in range(u.random_res_interval()): # Random number of id resource item_name = u.get_random(False, 16) res_root.append(ET.Element('public', { # Add an id item 'name': item_name, # Item name 'id': str(hex(last_id_index + count_res)), # Item id 'type': 'id' # Item type })) yield item_name # Return the added item name
def define_code_block(smali_file, valid_op_code): """Try to define a code block""" edit_method = False # Editing a method in_try = False # In a try-catch for smali_line in u.open_file_input(smali_file): # For each line if is_beg_not_abstract_method(smali_line) and not edit_method: # Method start edit_method = True in_try = False print smali_line, # Print the line unchanged elif is_end_method(smali_line) and edit_method: # Method end edit_method = False print smali_line, # Print the line unchanged elif edit_method: line_op_code = re.search(r"^([ ]*)(?P<opCode>([^ \n]+))([ ]|$)", smali_line) # Match a line if line_op_code is not None: op_code = line_op_code.group("opCode") if re.search(r"^([ ]*?):try_start", op_code) is not None: # Try start in_try = True # In try if re.search(r"^([ ]*?):try_end_", op_code) is not None: # Try end in_try = False # Out try if op_code in valid_op_code and not in_try: print "#!Block!#" # Print block signpost new_if = if_mapping.get(op_code, None) if new_if is not None: line_op_code = re.search( r"^([ ]*)(?P<opCode>([^ ]+)) (?P<regGo>[^:]*?):(?P<labelGo>[^ ]*?)$", smali_line ) # Match a line if line_op_code is not None: regGo = line_op_code.group("regGo") labelGo = line_op_code.group("labelGo") goto32_name = u.get_random(True, 15) # Random jump name print " " + new_if + " " + regGo + ":gl_" + goto32_name print " goto/32 :" + labelGo print " :gl_" + goto32_name else: print smali_line, else: print smali_line, # Print the line unchanged else: print smali_line, # Print the line unchanged else: print smali_line, # Print the line unchanged
def rnd(self, n): """ Return n random variates of the Double Pareto distribution. usage: Instance.rnd(n) Input ----- n: Number of random variates to generate Output ------ Return value: A numpy array with n random variates """ r = util.get_random() U = [] for i in xrange(n): U.append(r.uniform(0,1)) arnd = self.cdf_inv(U) return arnd
def rnd(self, n): """ Return MODLAV random variates Usage: Instance.rnd(n) Input ----- n = Number of random variates to generate Output ------ Return value: A numpy array of n MODLAV random variates """ r = util.get_random() U = [] for i in xrange(n): U.append(r.uniform(0, 1)) arnd = self.cdf_inv(U) return arnd
def add_id_random_resource(res_root): """In the 'public.xml' add some random id resource""" last_id_index = 0 for res_line in res_root: # For each resource res_type = res_line.attrib.get('type') # Return the resource type if res_type == 'id': # Resource type is 'id' curr_id = int(res_line.attrib.get('id'), 16) if last_id_index < curr_id: # Max id last_id_index = curr_id last_id_index += 1 # Next free resource id for count_res in range( u.random_res_interval()): # Random number of id resource item_name = u.get_random(False, 16) res_root.append( ET.Element( 'public', { # Add an id item 'name': item_name, # Item name 'id': str(hex(last_id_index + count_res)), # Item id 'type': 'id' # Item type })) yield item_name # Return the added item name
def change_package_name(manifest_xml): package_name = manifest_xml.getroot().get('package') new_package_name = package_name.replace('.', '!.!') # Append new_package_name = '!' + new_package_name + '!' new_package_name = new_package_name.replace( '!' + get_main_exec_dir() + '!.', get_main_exec_dir() + '.') # Do not rename /com for class_crypt in re.findall(r'(\![^\!]*?\!)', new_package_name): new_package_name = new_package_name.replace( class_crypt, crypt_identifier(class_crypt[:-1][1:])) manifest_xml.getroot().set('package', new_package_name) # Rename the package manifest_xml.getroot().set( '{http://schemas.android.com/apk/res/android}sharedUserId', u.get_random(True, 16) + '.uid.shared') # Rename the package yield 'http://schemas.android.com/apk/res/' + package_name, 'http://schemas.android.com/apk/res/' + new_package_name yield '<' + package_name, '<' + new_package_name yield '</' + package_name, '</' + new_package_name yield 'package="' + package_name, 'package="' + new_package_name yield '@*' + package_name + ':', '@*' + new_package_name + ':' yield '"' + package_name, '"' + new_package_name yield '/' + package_name + '/', '/' + new_package_name + '/'
def rnd(self, n): """ Return an array of Pareto random variates Usage: Instance.rnd(n) Input ------ n: The number of random variates to return Output ------ Return value: Numpy array of Pareto random variates """ r = util.get_random() l = [] for i in xrange(n): l.append(r.uniform(0, 1)) lp = np.array(l) arnd = self.__k / np.power(lp, 1 / self.__alpha) return arnd
def rnd(self, n): """ Return random variates for the MTPareto distribution Usage: Instance.rnd(n) Input ------ n: Number of random variates to return Output ------- Return value: A numpy array with MTPareto random variates """ r = util.get_random() l = [] for i in xrange(n): l.append(r.uniform(0, 1)) lp = np.array(l) arnd = self.__k * np.power(self.__m / self.__k, lp) return arnd
def rnd(self, n): """ Return random variates for the BiPareto distribution. Usage: Instance.rnd(n) Input ------ n: Number of random variates to return Output ------- Return value: A numpy array with n-BiPareto random variates """ r = util.get_random() l = [] for i in xrange(n): l.append(r.uniform(0, 1)) lp = np.array(l) arnd = self.cdf_inv(lp) return arnd
def load_code_block(smali_file): """Read and split smali code into code blocks""" edit_method = False # Editing a method jump_count = 0 # Current jump index for smali_line in u.open_file_input(smali_file): # For each line if is_beg_not_abstract_method(smali_line) and not edit_method: # Method start edit_method = True jump_count = 0 print smali_line, # Print the line unchanged elif is_end_method(smali_line) and edit_method: # Method end edit_method = False print smali_line, # Print the line unchanged elif edit_method: # Reading method if is_block_sign(smali_line): # Block signpost jump_name = u.get_random(True, 15) # Random jump name jump_count += 1 # Increment jump count print " goto/32 :l_" + jump_name + "_" + str(jump_count) print " nop" print smali_line, print " :l_" + jump_name + "_" + str(jump_count) else: print smali_line, # Print the line unchanged else: print smali_line, # Print the line unchanged
def rnd(self, n): """ Return an array of Pareto random variates Usage: Instance.rnd(n) Input ------ n: The number of random variates to return Output ------ Return value: Numpy array of Pareto random variates """ r = util.get_random() l = [] for i in xrange(n): l.append(r.uniform(0, 1)) lp = np.array(l) arnd = self.__k/np.power(lp, 1/self.__alpha) return arnd
def change_match_line(smali_line, invoke_type, invoke_param, invoke_object, invoke_method, invoke_pass, invoke_return, class_name, new_method): """Change a method call""" string_append = u.get_random(True, 15) is_range_value = is_range(invoke_type) is_static_value = is_static(invoke_type) reg_list = list(get_reg(invoke_param)) if is_range_value: reg_count = reg_range_count(reg_list) else: reg_count = len(reg_list) is_void_value = is_void(invoke_return) is_wide_value = is_wide(invoke_return) is_obj_value = is_obj(invoke_return) local_reg_count = 1 if is_void_value: local_reg_count = 0 if is_wide_value: local_reg_count = 2 return_str = 'return v0' if is_void_value: return_str = 'return-void' if is_wide_value: return_str = 'return-wide v0' if is_obj_value: return_str = 'return-object v0' move_result_str = 'move-result v0' if is_void_value: move_result_str = '' if is_wide_value: move_result_str = 'move-result-wide v0' if is_obj_value: move_result_str = 'move-result-object v0' add_param = '' if not is_static_value: add_param = invoke_object invoke_new = 'invoke-static' if is_range_value: invoke_new += '/range' print ' ' + invoke_new + ' {' + invoke_param + '}, ' + class_name + '->' + string_append + '(' + add_param + invoke_pass + ')' + invoke_return new_method.write('.method public static ' + string_append + '(' + add_param + invoke_pass + ')' + invoke_return + '\n') new_method.write(' .locals ' + str(local_reg_count) + '\n') new_method.write(' .prologue' + '\n') new_method.write('\n') new_method.write(' ' + invoke_type + ' {') if is_range_value: new_method.write('p0 .. p' + str(reg_count-1)) else: for reg_index in range(0, reg_count): new_method.write('p' + str(reg_index)) if reg_count != reg_index + 1: new_method.write(', ') new_method.write('}, ' + invoke_object + '->' + invoke_method + '(' + invoke_pass + ')' + invoke_return + '\n') new_method.write('\n') new_method.write(' ' + move_result_str + '\n') new_method.write('\n') new_method.write(' ' + return_str + '\n') new_method.write('.end method' + '\n')
def add_random_fields(smali_line): """Adds a random (in lenght and name) list of fields to the class""" for _ in range(u.random_nop_interval()): print re.sub(r':', u.get_random(True, 32) + ':', smali_line), # Append
def change_match_line(smali_line, invoke_type, invoke_param, invoke_object, invoke_method, invoke_pass, invoke_return, class_name, new_method): """Change a method call""" string_append = u.get_random(True, 15) is_range_value = is_range(invoke_type) is_static_value = is_static(invoke_type) reg_list = list(get_reg(invoke_param)) if is_range_value: reg_count = reg_range_count(reg_list) else: reg_count = len(reg_list) is_void_value = is_void(invoke_return) is_wide_value = is_wide(invoke_return) is_obj_value = is_obj(invoke_return) local_reg_count = 1 if is_void_value: local_reg_count = 0 if is_wide_value: local_reg_count = 2 return_str = 'return v0' if is_void_value: return_str = 'return-void' if is_wide_value: return_str = 'return-wide v0' if is_obj_value: return_str = 'return-object v0' move_result_str = 'move-result v0' if is_void_value: move_result_str = '' if is_wide_value: move_result_str = 'move-result-wide v0' if is_obj_value: move_result_str = 'move-result-object v0' add_param = '' if not is_static_value: add_param = invoke_object invoke_new = 'invoke-static' if is_range_value: invoke_new += '/range' print ' ' + invoke_new + ' {' + invoke_param + '}, ' + class_name + '->' + string_append + '(' + add_param + invoke_pass + ')' + invoke_return new_method.write('.method public static ' + string_append + '(' + add_param + invoke_pass + ')' + invoke_return + '\n') new_method.write(' .locals ' + str(local_reg_count) + '\n') new_method.write(' .prologue' + '\n') new_method.write('\n') new_method.write(' ' + invoke_type + ' {') if is_range_value: new_method.write('p0 .. p' + str(reg_count - 1)) else: for reg_index in range(0, reg_count): new_method.write('p' + str(reg_index)) if reg_count != reg_index + 1: new_method.write(', ') new_method.write('}, ' + invoke_object + '->' + invoke_method + '(' + invoke_pass + ')' + invoke_return + '\n') new_method.write('\n') new_method.write(' ' + move_result_str + '\n') new_method.write('\n') new_method.write(' ' + return_str + '\n') new_method.write('.end method' + '\n')
def change_match_line(smali_line, invoke_type, invoke_param, invoke_object, invoke_method, invoke_pass, invoke_return, class_name, new_method, all_method_list): """Change a method call""" string_append = u.get_random(True, 15) is_range_value = is_range(invoke_type) is_static_value = is_static(invoke_type) reg_list = list(get_reg(invoke_param)) if is_range_value: reg_count = reg_range_count(reg_list) else: reg_count = len(reg_list) is_void_value = is_void(invoke_return) is_wide_value = is_wide(invoke_return) is_obj_value = is_obj(invoke_return) local_reg_count = 1 if is_void_value: local_reg_count = 0 if is_wide_value: local_reg_count = 2 return_str = 'return v0' if is_void_value: return_str = 'return-void' if is_wide_value: return_str = 'return-wide v0' if is_obj_value: return_str = 'return-object v0' move_result_str = 'move-result v0' if is_void_value: move_result_str = '' if is_wide_value: move_result_str = 'move-result-wide v0' if is_obj_value: move_result_str = 'move-result-object v0' add_param = '' if not is_static_value: add_param = invoke_object invoke_new = 'invoke-static' if is_range_value: invoke_new += '/range' print ' ' + invoke_new + ' {' + invoke_param + '}, ' + class_name + '->' + string_append + '(' + add_param + invoke_pass + ')' + invoke_return new_method.write('.method public static ' + string_append + '(' + add_param + invoke_pass + ')' + invoke_return + '\n') new_method.write(' .locals ' + str(local_reg_count + 8 - 2) + '\n') new_method.write(' .prologue' + '\n') method_search = invoke_object + '->' + invoke_method + '(' + invoke_pass + ')' if method_search in all_method_list: list_invoke = list(split_invoke_pass(invoke_pass)) list_count = len(list_invoke) new_method.write('\n') new_method.write(' const v0, ' + hex(list_count) + '\n') new_method.write(' new-array v1, v0, [Ljava/lang/Class;' + '\n') new_method.write(' new-array v2, v0, [Ljava/lang/Object;' + '\n') new_method.write('\n') if is_static_value: reg_base = 0 else: reg_base = 1 index_list = 0 for curr_invoke in list_invoke: new_method.write(' const v0, ' + hex(index_list) + '\n') index_list += 1 curr_dict = sget_dict.get(curr_invoke, '') if curr_dict != '': new_method.write(' sget-object v3, ' + curr_dict + '\n') else: new_method.write(' const-class v3, ' + curr_invoke + '\n') new_method.write(' aput-object v3, v1, v0' + '\n') curr_dict = cast_dict.get(curr_invoke, '') if curr_dict != '': if is_wide(curr_invoke): new_method.write(' invoke-static/range {p' + str(reg_base) + ' .. p' + str(reg_base + 1) + '}, ') else: new_method.write(' invoke-static/range {p' + str(reg_base) + ' .. p' + str(reg_base) + '}, ') new_method.write(curr_dict + '\n') new_method.write(' move-result-object v3' + '\n') new_method.write(' aput-object v3, v2, v0' + '\n') if is_wide(curr_invoke): reg_base += 1 else: new_method.write(' aput-object p' + str(reg_base) + ', v2, v0' + '\n') reg_base += 1 new_method.write('\n') new_method.write(' const-string v0, "' + invoke_method + '"' + '\n') new_method.write(' const-class v3, ' + invoke_object + '\n') new_method.write('\n') new_method.write( ' invoke-virtual {v3, v0, v1}, Ljava/lang/Class;->getMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;' + '\n') new_method.write(' move-result-object v0' + '\n') new_method.write('\n') if is_static_value: new_method.write( ' invoke-virtual {v0, v3, v2}, Ljava/lang/reflect/Method;->invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;' + '\n') else: new_method.write( ' invoke-virtual {v0, p0, v2}, Ljava/lang/reflect/Method;->invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;' + '\n') new_method.write(' move-result-object v0' + '\n') if is_void_value: new_method.write(' return-void' + '\n') elif is_obj_value: new_method.write(' check-cast v0, ' + invoke_return + '\n') new_method.write(' return-object v0' + '\n') else: curr_dict = type_dict.get(invoke_return, '') new_method.write(' check-cast v0, ' + curr_dict + '\n') curr_dict = reverse_cast_dict.get(invoke_return, '') new_method.write(' invoke-virtual {v0}, ' + curr_dict + '\n') if is_wide_value: new_method.write(' move-result-wide v0' + '\n') new_method.write(' return-wide v0' + '\n') else: new_method.write(' move-result v0' + '\n') new_method.write(' return v0' + '\n') new_method.write('\n') else: new_method.write(' ' + invoke_type + ' {') if is_range_value: new_method.write('p0 .. p' + str(reg_count - 1)) else: for reg_index in range(0, reg_count): new_method.write('p' + str(reg_index)) if reg_count != reg_index + 1: new_method.write(', ') new_method.write('}, ' + invoke_object + '->' + invoke_method + '(' + invoke_pass + ')' + invoke_return + '\n') new_method.write('\n') new_method.write(' ' + move_result_str + '\n') new_method.write('\n') new_method.write(' ' + return_str + '\n') new_method.write('.end method' + '\n')
def change_match_line(smali_line, invoke_type, invoke_param, invoke_object, invoke_method, invoke_pass, invoke_return, class_name, new_method, all_method_list): """Change a method call""" string_append = u.get_random(True, 15) is_range_value = is_range(invoke_type) is_static_value = is_static(invoke_type) reg_list = list(get_reg(invoke_param)) if is_range_value: reg_count = reg_range_count(reg_list) else: reg_count = len(reg_list) is_void_value = is_void(invoke_return) is_wide_value = is_wide(invoke_return) is_obj_value = is_obj(invoke_return) local_reg_count = 1 if is_void_value: local_reg_count = 0 if is_wide_value: local_reg_count = 2 return_str = 'return v0' if is_void_value: return_str = 'return-void' if is_wide_value: return_str = 'return-wide v0' if is_obj_value: return_str = 'return-object v0' move_result_str = 'move-result v0' if is_void_value: move_result_str = '' if is_wide_value: move_result_str = 'move-result-wide v0' if is_obj_value: move_result_str = 'move-result-object v0' add_param = '' if not is_static_value: add_param = invoke_object invoke_new = 'invoke-static' if is_range_value: invoke_new += '/range' print ' ' + invoke_new + ' {' + invoke_param + '}, ' + class_name + '->' + string_append + '(' + add_param + invoke_pass + ')' + invoke_return new_method.write('.method public static ' + string_append + '(' + add_param + invoke_pass + ')' + invoke_return + '\n') new_method.write(' .locals ' + str(local_reg_count + 8 - 2) + '\n') new_method.write(' .prologue' + '\n') method_search = invoke_object + '->' + invoke_method + '(' + invoke_pass + ')' if method_search in all_method_list: list_invoke = list(split_invoke_pass(invoke_pass)) list_count = len(list_invoke) new_method.write('\n') new_method.write(' const v0, ' + hex(list_count) + '\n') new_method.write(' new-array v1, v0, [Ljava/lang/Class;' + '\n') new_method.write(' new-array v2, v0, [Ljava/lang/Object;' + '\n') new_method.write('\n') if is_static_value: reg_base = 0 else: reg_base = 1 index_list = 0 for curr_invoke in list_invoke: new_method.write(' const v0, ' + hex(index_list) + '\n') index_list += 1 curr_dict = sget_dict.get(curr_invoke, '') if curr_dict != '': new_method.write(' sget-object v3, ' + curr_dict + '\n') else: new_method.write(' const-class v3, ' + curr_invoke + '\n') new_method.write(' aput-object v3, v1, v0' + '\n') curr_dict = cast_dict.get(curr_invoke, '') if curr_dict != '': if is_wide(curr_invoke): new_method.write(' invoke-static/range {p' + str(reg_base) + ' .. p' + str(reg_base + 1) + '}, ') else: new_method.write(' invoke-static/range {p' + str(reg_base) + ' .. p' + str(reg_base) + '}, ') new_method.write(curr_dict + '\n') new_method.write(' move-result-object v3' + '\n') new_method.write(' aput-object v3, v2, v0' + '\n') if is_wide(curr_invoke): reg_base += 1 else: new_method.write(' aput-object p' + str(reg_base) + ', v2, v0' + '\n') reg_base += 1 new_method.write('\n') new_method.write(' const-string v0, "' + invoke_method + '"' + '\n') new_method.write(' const-class v3, ' + invoke_object + '\n') new_method.write('\n') new_method.write(' invoke-virtual {v3, v0, v1}, Ljava/lang/Class;->getMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;' + '\n') new_method.write(' move-result-object v0' + '\n') new_method.write('\n') if is_static_value: new_method.write(' invoke-virtual {v0, v3, v2}, Ljava/lang/reflect/Method;->invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;' + '\n') else: new_method.write(' invoke-virtual {v0, p0, v2}, Ljava/lang/reflect/Method;->invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;' + '\n') new_method.write(' move-result-object v0' + '\n') if is_void_value: new_method.write(' return-void' + '\n') elif is_obj_value: new_method.write(' check-cast v0, ' + invoke_return + '\n') new_method.write(' return-object v0' + '\n') else: curr_dict = type_dict.get(invoke_return, '') new_method.write(' check-cast v0, ' + curr_dict + '\n') curr_dict = reverse_cast_dict.get(invoke_return, '') new_method.write(' invoke-virtual {v0}, ' + curr_dict + '\n') if is_wide_value: new_method.write(' move-result-wide v0' + '\n') new_method.write(' return-wide v0' + '\n') else: new_method.write(' move-result v0' + '\n') new_method.write(' return v0' + '\n') new_method.write('\n') else: new_method.write(' ' + invoke_type + ' {') if is_range_value: new_method.write('p0 .. p' + str(reg_count-1)) else: for reg_index in range(0, reg_count): new_method.write('p' + str(reg_index)) if reg_count != reg_index + 1: new_method.write(', ') new_method.write('}, ' + invoke_object + '->' + invoke_method + '(' + invoke_pass + ')' + invoke_return + '\n') new_method.write('\n') new_method.write(' ' + move_result_str + '\n') new_method.write('\n') new_method.write(' ' + return_str + '\n') new_method.write('.end method' + '\n')