def test_aget_kind(self, pyeval, aget_kind): v2_mock_variable_obj = RegisterObject( "v2", "some_list_like[1,2,3,4]", "java.io.file.close()", value_type="[Ljava/lang/Integer;", ) v3_mock_variable_obj = RegisterObject("v3", "2", None, value_type="I") pyeval.table_obj.insert(2, v2_mock_variable_obj) pyeval.table_obj.insert(3, v3_mock_variable_obj) if "-" in aget_kind: index = aget_kind.index("-") + 1 postfix = aget_kind[index:] if postfix == "object": expected_value_type = "Ljava/lang/Integer;" else: expected_value_type = pyeval.type_mapping[postfix] else: expected_value_type = "Ljava/lang/Integer;" instruction = [aget_kind, "v1", "v2", "v3"] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(1) == RegisterObject( "v1", "some_list_like[1,2,3,4][2]", value_type=expected_value_type)
def test_new_instance(self, pyeval): instruction = ["new-instance", "v3", "Lcom/google/progress/SMSHelper;"] override_original_instruction = [ "new-instance", "v4", "Ljava/lang/Object;", ] pyeval.NEW_INSTANCE(instruction) assert pyeval.table_obj.pop(3) == RegisterObject( "v3", "Lcom/google/progress/SMSHelper;", value_type="Lcom/google/progress/SMSHelper;", ) assert pyeval.table_obj.pop(4) == RegisterObject( "v4", "Lcom/google/progress/SMSHelper;", value_type="Lcom/google/progress/SMSHelper;", ) pyeval.NEW_INSTANCE(override_original_instruction) assert pyeval.table_obj.pop(4) == RegisterObject( "v4", "Ljava/lang/Object;", value_type="Ljava/lang/Object;")
def test_invoke_and_move(self, pyeval): v6_mock_variable_obj = RegisterObject("v6", "some_string", None, value_type="Ljava/lang/String;") pyeval.table_obj.insert(6, v6_mock_variable_obj) assert pyeval.table_obj.pop(6) == RegisterObject( "v6", "some_string", value_type="Ljava/lang/String;") first_instruction = [ "invoke-virtual", "v6", "Lcom/google/progress/ContactsCollector;->getContactList()Ljava/lang/String;", ] second_instruction = ["move-result-object", "v1"] pyeval.INVOKE_VIRTUAL(first_instruction) pyeval.MOVE_RESULT_OBJECT(second_instruction) assert pyeval.table_obj.pop(1) == RegisterObject( "v1", ("Lcom/google/progress/ContactsCollector;" "->getContactList()Ljava/lang/String;(some_string)"), value_type="Ljava/lang/String;", )
def test_neg_and_not_wide_kind(self, pyeval, neg_not_wide_kind): instruction = [neg_not_wide_kind, "v1", "v5"] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(1) == RegisterObject("v1", "some_number", value_type="I") assert pyeval.table_obj.pop(2) == RegisterObject("v2", "an_array", value_type="[I")
def test_move_wide_kind(self, pyeval, move_wide_kind): instruction = [move_wide_kind, "v1", "v4"] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(1) == RegisterObject( "v1", "Lcom/google/progress/SMSHelper;", value_type="Lcom/google/progress/SMSHelper;", ) assert pyeval.table_obj.pop(2) == RegisterObject("v2", "some_number", value_type="I")
def _assign_value_wide(self, instruction, value_type=""): """ For 64 bit, it has two register, which is vx and vx+1 """ reg = instruction[1] value = instruction[2] index = int(reg[1:]) reg_plus_one = f"v{index + 1}" variable_object = RegisterObject(reg, value, value_type=value_type) variable_object2 = RegisterObject(reg_plus_one, value, value_type=value_type) self.table_obj.insert(index, variable_object) self.table_obj.insert(index + 1, variable_object2)
def test_aget_wide_kind(self, pyeval, aget_wide_kind): instruction = [aget_wide_kind, "v1", "v6", "v5"] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(1) == RegisterObject( "v1", "an_array[some_number]", value_type="I")
def _transfer_register(self, source_list, destination, str_format, data=None, value_type=None): source_register_list = [ self.table_obj.pop(index) for index in source_list ] if not value_type: value_type = source_register_list[0].current_type value_dict = { f"src{index}": register.value for index, register in enumerate(source_register_list) } value_dict["data"] = data new_register = RegisterObject( f"v{destination}", str_format.format(**value_dict), value_type=value_type, ) self.table_obj.insert(destination, new_register)
def test_move_exception(self, pyeval): instruction = ["move-exception", "v1"] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(1) == RegisterObject( "v1", "Exception", value_type="Ljava/lang/Throwable;")
def test_fill_array_data(self, pyeval): instruction = ["fill-array-data", "v6", "array-data-address"] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(6) == RegisterObject( "v6", "Embedded-array-data()[", value_type="[I")
def _assign_value(self, instruction, value_type=""): reg = instruction[1] value = instruction[2] index = int(reg[1:]) variable_object = RegisterObject(reg, value, value_type=value_type) self.table_obj.insert(index, variable_object)
def test_binop_kind_with_wide_type(self, pyeval, binop_wide_kind): instruction = [binop_wide_kind, "v1", "v4", "v6"] index = binop_wide_kind.index("-") + 1 postfix = binop_wide_kind[index:] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(1) == RegisterObject( "v1", "binop(Lcom/google/progress/SMSHelper;, an_array)", value_type=pyeval.type_mapping[postfix], ) assert pyeval.table_obj.pop(2) == RegisterObject( "v2", "binop(some_number, a_float)", value_type=pyeval.type_mapping[postfix], )
def test_new_array(self, pyeval): instruction = ["new-array", "v1", "v5", "[java/lang/String;"] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(1) == RegisterObject( "v1", "new-array()[(some_number)", value_type="[java/lang/String;", )
def test_type_casting_with_simple_type_to_wide_type( self, pyeval, cast_simple_to_wide_kind): instruction = [cast_simple_to_wide_kind, "v1", "v5"] index = cast_simple_to_wide_kind.index("-") + 1 postfix = cast_simple_to_wide_kind[index:] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(1) == RegisterObject( "v1", "casting(some_number)", value_type=pyeval.type_mapping[postfix], ) assert pyeval.table_obj.pop(2) == RegisterObject( "v2", "casting(some_number)", value_type=pyeval.type_mapping[postfix], )
def test_aput_kind(self, pyeval, aput_kind): instruction = [aput_kind, "v4", "v6", "v5"] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(6) == RegisterObject( "v6", "an_array[some_number]:Lcom/google/progress/SMSHelper;", value_type="[I", )
def MOVE_RESULT_WIDE(self, instruction): """ move-result-wide vx Move the long/double result value of the previous method invocation into vx,vx+1. """ reg = instruction[1] index = int(reg[1:]) try: pre_ret = self.ret_stack.pop() variable_object = RegisterObject(reg, pre_ret, value_type=self.ret_type) variable_object2 = RegisterObject(f"v{index + 1}", pre_ret, value_type=self.ret_type) self.table_obj.insert(index, variable_object) self.table_obj.insert(index + 1, variable_object2) except IndexError as e: log.exception(f"{e} in MOVE_RESULT_WIDE")
def test_move_with_valid_instrcution(self, pyeval): instruction = ["move-result-object", "v1"] expected_return_value = "some_function()V(used_register_1, used_register_2)" expected_return_type = "Lclass;" pyeval.ret_stack.append(expected_return_value) pyeval.ret_type = expected_return_type pyeval._move_result(instruction) assert pyeval.table_obj.pop(1) == RegisterObject( "v1", expected_return_value, None, value_type=expected_return_type)
def test_simple_binop_kind(self, pyeval, simple_binop_kind): instruction = [simple_binop_kind, "v1", "v5", "v6"] index = simple_binop_kind.index("-") + 1 postfix = simple_binop_kind[index:] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(1) == RegisterObject( "v1", "binop(some_number, an_array)", value_type=pyeval.type_mapping[postfix], )
def _move_result(self, instruction): reg = instruction[1] index = int(reg[1:]) try: pre_ret = self.ret_stack.pop() variable_object = RegisterObject(reg, pre_ret, value_type=self.ret_type) self.table_obj.insert(index, variable_object) self.ret_type = "" except IndexError as e: log.exception(f"{e} in _move_result")
def test_binop_kind_with_literal(self, pyeval, binop_lit_kind): instruction = [binop_lit_kind, "v1", "v5", "literal_number"] l_index = binop_lit_kind.index("-") + 1 r_index = binop_lit_kind.index("/") postfix = binop_lit_kind[l_index:r_index] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(1) == RegisterObject( "v1", "binop(some_number, literal_number)", value_type=pyeval.type_mapping[postfix], )
def test_binop_kind_in_place(self, pyeval, binop_2addr_kind): instruction = [binop_2addr_kind, "v4", "v6"] l_index = binop_2addr_kind.index("-") + 1 r_index = binop_2addr_kind.index("/") postfix = binop_2addr_kind[l_index:r_index] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(4) == RegisterObject( "v4", "binop(Lcom/google/progress/SMSHelper;, an_array)", value_type=pyeval.type_mapping[postfix], )
def test_const_string_jumbo(self, pyeval): instruction = [ "const-string/jumbo", "v8", "https://github.com/quark-engine/quark-engine", ] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(8) == RegisterObject( "v8", "https://github.com/quark-engine/quark-engine", value_type="Ljava/lang/String;", )
def test_const_class(self, pyeval): instruction = [ "const-class", "v8", "Landroid/telephony/SmsMessage;", ] pyeval.eval[instruction[0]](instruction) assert pyeval.table_obj.pop(8) == RegisterObject( "v8", "Landroid/telephony/SmsMessage;", value_type="Ljava/lang/Class;", )
def pyeval(apkinfo): pyeval = PyEval(apkinfo) # mock_hash_table = [...[], [v4_mock_variable_obj], [], [], # [v9_mock_variable_obj]....] v4_mock_variable_obj = RegisterObject( "v4", "Lcom/google/progress/SMSHelper;", value_type="Lcom/google/progress/SMSHelper;", ) v5_mock_variable_obj = RegisterObject("v5", "some_number", "java.lang.String.toString()", value_type="I") v6_mock_variable_obj = RegisterObject("v6", "an_array", "java.lang.Collection.toArray()", value_type="[I") v7_mock_variable_obj = RegisterObject("v7", "a_float", value_type="F") v8_mock_variable_obj = RegisterObject( "v8", "ArrayMap object", value_type="Landroid/support/v4/util/ArrayMap;", ) v9_mock_variable_obj = RegisterObject( "v9", "some_string", "java.io.file.close()", value_type="Ljava/lang/String;", ) pyeval.table_obj.insert(4, v4_mock_variable_obj) pyeval.table_obj.insert(5, v5_mock_variable_obj) pyeval.table_obj.insert(6, v6_mock_variable_obj) pyeval.table_obj.insert(7, v7_mock_variable_obj) pyeval.table_obj.insert(8, v8_mock_variable_obj) pyeval.table_obj.insert(9, v9_mock_variable_obj) yield pyeval del pyeval
def test_init_with_called_by_func(self): register_obj = RegisterObject("v1", "value", "func") assert register_obj._register_name == "v1" assert register_obj._value == "value" assert register_obj._called_by_func == ["func"]
def standard_register_obj(): register_obj = RegisterObject("v1", "value", "func") yield register_obj del register_obj