Пример #1
0
def retrieve_string_value(string_ptr):
    length_val = memory.readMemory32(string_ptr + config.offset_string_length)
    reference_ptr = memory.readMemory32(string_ptr +
                                        config.offset_string_reference)
    char_array = memory.retrieve_char_array(reference_ptr)

    return char_array
Пример #2
0
def resolve_mirror_Class(class_ptr):
	# find the clinit_thread_id_ field
	address_Class_clinit_thread_id_ = class_ptr
	pid_val = int(execution_state.getVariableService().readValue("$AARCH64::$System::$Memory::$CONTEXTIDR_EL1.PROCID")) & 0xffffffff
	while True:
		if memory.readMemory32(address_Class_clinit_thread_id_) == pid_val:
			break
		else:
			address_Class_clinit_thread_id_ = address_Class_clinit_thread_id_ + 0x4
	
	# get the methods_ field
	address_methods_ = address_Class_clinit_thread_id_ - 0x4 - 0x4 - 0x4 - 0x8 - 0x8
	methods_array_ptr = memory.readMemory32(address_methods_)
	
	methods_cnt = memory.readMemory32(methods_array_ptr)
	if config.debug:
		print "[ClassModification] len(methods_) = %#x" % methods_cnt
	
	method_list = []
	current_method_ptr = methods_array_ptr + 0x4
	for idx in range(methods_cnt):
		field_0	= current_method_ptr + config.offset_ArtMethod_declaring_class_  # specially, we record the address rather than its value
		field_1 = memory.readMemory32(current_method_ptr + config.offset_ArtMethod_access_flags_)
		field_2 = memory.readMemory32(current_method_ptr + config.offset_ArtMethod_dex_code_item_offset_)
		field_3 = memory.readMemory32(current_method_ptr + config.offset_ArtMethod_dex_method_index_)
		field_4 = memory.readMemory16(current_method_ptr + config.offset_ArtMethod_method_index_)
		field_5 = memory.readMemory16(current_method_ptr + config.offset_ArtMethod_hotness_count_)
		field_6 = memory.readMemory32(current_method_ptr + config.offset_ArtMethod_dex_cache_resolved_methods_)
		field_7 = memory.readMemory32(current_method_ptr + config.offset_ArtMethod_data_)
		field_8 = memory.readMemory32(current_method_ptr + config.offset_ArtMethod_entry_point_from_quick_compiled_code)
		
		method_list.append((field_0, field_1, field_2, field_3, field_4, field_5, field_6, field_7, field_8))
		current_method_ptr = current_method_ptr + 0x20
		
	return method_list
Пример #3
0
def parse_proto_id_item(dex_file_off, proto_ids_off, proto_id):
    proto_id_item_ptr = dex_file_off + proto_ids_off + proto_id * 0xc

    shorty_idx = memory.readMemory32(proto_id_item_ptr + offset_shorty_idx)
    return_type_idx = memory.readMemory32(proto_id_item_ptr +
                                          offset_return_type_idx)

    parameters_off = memory.readMemory32(proto_id_item_ptr +
                                         offset_parameters_off)
    type_list_ptr = dex_file_off + parameters_off
    type_list_size = memory.readMemory32(type_list_ptr + offset_type_list_size)
    type_list_list_ptr = type_list_ptr + offset_type_list_list
    type_item_list = []
    for type_item_idx in range(type_list_size):
        type_idx = memory.readMemory16(type_list_list_ptr +
                                       type_item_idx * 0x2)
        type_item_list.append(type_idx)
Пример #4
0
def get_string_id_item_data_off(dex_file_off, string_ids_off, string_id):
    string_data_item_ptr = dex_file_off + string_ids_off + string_id * 0x4
    string_data_item_off = memory.readMemory32(string_data_item_ptr +
                                               offset_string_data_off)

    utf16_size, offset_data_off = utility.readuleb128(dex_file_off +
                                                      string_data_item_off +
                                                      offset_utf16_size_off)

    return dex_file_off + string_data_item_off + offset_data_off
Пример #5
0
def parse_string_id_item(dex_file_off, string_ids_off, string_id):
    string_data_item_ptr = dex_file_off + string_ids_off + string_id * 0x4
    string_data_item_off = memory.readMemory32(string_data_item_ptr +
                                               offset_string_data_off)

    utf16_size, offset_data_off = utility.readuleb128(dex_file_off +
                                                      string_data_item_off +
                                                      offset_utf16_size_off)
    data = memory.retrieve_char_array(dex_file_off + string_data_item_off +
                                      offset_data_off)
Пример #6
0
def get_parameters_list(dex_file_off, proto_ids_off, proto_id):
    proto_id_item_ptr = dex_file_off + proto_ids_off + proto_id * 0xc

    parameters_off = memory.readMemory32(proto_id_item_ptr +
                                         offset_parameters_off)
    if parameters_off == 0:
        # it refers that this prototype has no parameters
        return []

    type_list_ptr = dex_file_off + parameters_off
    type_list_size = memory.readMemory32(type_list_ptr + offset_type_list_size)
    assert type_list_size < 100
    type_list_list_ptr = type_list_ptr + offset_type_list_list
    type_item_list = []
    for type_item_idx in range(type_list_size):
        type_idx = memory.readMemory16(type_list_list_ptr +
                                       type_item_idx * 0x2)
        type_item_list.append(type_idx)

    return type_item_list
Пример #7
0
def RegisterNatives():
    class_ptr = int(
        execution_state.getRegisterService().getValue("R1")) & 0xffffffff
    methods_ptr = int(
        execution_state.getRegisterService().getValue("R2")) & 0xffffffff
    method_count = int(
        execution_state.getRegisterService().getValue("R3")) & 0xffffffff
    for idx in range(method_count):
        method_name_ptr = memory.readMemory32((methods_ptr + idx * 0xc) + 0x0)
        method_name_val = memory.retrieve_char_array(method_name_ptr)
        method_subsignature_ptr = memory.readMemory32((methods_ptr +
                                                       idx * 0xc) + 0x4)
        method_subsignature_val = memory.retrieve_char_array(
            method_subsignature_ptr)
        method_pointer_ptr = (methods_ptr + idx * 0xc) + 0x8
        method_pointer_val = memory.readMemory32(method_pointer_ptr)
        config.log_print(
            "[RegisterNatives] signature = %s%s, method_ptr = %0#10x" %
            (method_name_val, method_subsignature_val, method_pointer_val))

    # continue the execution of the target application
    execution_state.getExecutionService().resume()
    cleanup()
    return
Пример #8
0
def FindClass():
    # -- HEAD -- #
    start_prolog()

    # -- BODY -- #

    # get the "soa" parameter
    soa_param = int(
        execution_state.getRegisterService().getValue("R1")) & 0xffffffff
    # retrieve the "self_" field (i.e., Thread* const self_)
    thread_ptr = memory.readMemory32(soa_param)

    # get the "descriptor" parameter
    descriptor_param = int(
        execution_state.getRegisterService().getValue("R2")) & 0xffffffff
    descriptor_ptr = descriptor_param

    # read the "descriptor" string
    descriptor_string_val = memory.retrieve_char_array(descriptor_ptr)
    print "[FindClass] descriptor = %s" % descriptor_string_val

    if config.package_name.replace(".", "/") in descriptor_string_val:
        mirror_class_names, mirror_class_ptrs = force_loading(
            descriptor_string_val)
        config.save_class_info(thread_ptr, mirror_class_names,
                               mirror_class_ptrs)

        # -- TAIL -- #
        end_prolog_done()
    else:
        # -- TAIL -- #
        end_prolog()
        # continue the execution of the target application
        execution_state.getExecutionService().resume()
        cleanup()
        return

    # continue the execution of the target application
    execution_state.getExecutionService().resume()
    cleanup()
    return
Пример #9
0
def get_proto_ids_off(header_item_ptr):
    return memory.readMemory32(header_item_ptr + offset_proto_ids_off)
Пример #10
0
def init_art():
    # get the PID
    pid_val = int(execution_state.getVariableService().readValue(
        "$AARCH64::$System::$Memory::$CONTEXTIDR_EL1.PROCID")) & 0xffffffff

    # -1-
    # read the "name" parameter
    name_ptr = int(
        execution_state.getRegisterService().getValue("R0")) & 0xffffffff
    name_val = memory.retrieve_char_array(name_ptr)
    # read the "flags" parameter
    flags_val = int(
        execution_state.getRegisterService().getValue("R1")) & 0xffffffff
    # read the "extinfo" parameter
    extinfo_ptr = int(
        execution_state.getRegisterService().getValue("R2")) & 0xffffffff

    if config.debug:
        print "[entrypoint] [do_dlopen] pid = %#x" % pid_val
        print "[entrypoint] [do_dlopen] name = %s" % name_val
        print "[entrypoint] [do_dlopen] flags_val = %#x" % flags_val
        print "[entrypoint] [do_dlopen] extinfo_ptr = %0#10x" % extinfo_ptr

    # the first loaded Oat file must be our target
    if not config.package_filter(name_val):
        # should not be reached
        assert False

    config.log_print("[entrypoint] [do_dlopen] pid = %#x" % pid_val)

    # -2-
    # goto the invocation of the find_library method
    brk_find_library_offset = config.linker_base + find_library_offset - config.linker_file_offset + config.linker_memory_offset
    execution_state.getExecutionService().resumeTo(brk_find_library_offset)
    try:
        execution_state.getExecutionService().waitForStop(
            120000)  # wait for 120s
    except DebugException:
        raise RuntimeError("wtf !!!")

    # retrieve soinfo pointer
    si_ptr = int(
        execution_state.getRegisterService().getValue("R0")) & 0xffffffff
    if config.debug:
        print "[entrypoint] [do_dlopen] si = %0#10x" % si_ptr

    base_ptr = si_ptr + config.offset_soinfo_base
    base_val = memory.readMemory32(base_ptr)
    size_ptr = si_ptr + config.offset_soinfo_size
    size_val = memory.readMemory32(size_ptr)

    if base_val == 0x0 or size_val == 0x0:
        # -3-
        # goto the invocation of the call_constructors method
        brk_call_constructors_offset = config.linker_base + call_constructors_offset - config.linker_file_offset + config.linker_memory_offset
        execution_state.getExecutionService().resumeTo(
            brk_call_constructors_offset)
        try:
            execution_state.getExecutionService().waitForStop(
                120000)  # wait for 120s
        except DebugException:
            raise RuntimeError("wtf !!!")

        base_ptr = si_ptr + config.offset_soinfo_base
        base_val = memory.readMemory32(base_ptr)
        size_ptr = si_ptr + config.offset_soinfo_size
        size_val = memory.readMemory32(size_ptr)

    if config.debug:
        print "[entrypoint] [do_dlopen] si->base = %0#10x" % base_val
        print "[entrypoint] [do_dlopen] si->size = %#x" % size_val

    config.log_print(
        "[entrypoint] [do_dlopen] name = %s, si->base = %0#10x, si->size = %#x"
        % (name_val, base_val, size_val))
    if not base_val == 0x0:
        config.save_range_info(base_val, base_val + size_val - 0x1)

    # initialization
    setup(pid_val)

    # continue the execution of the target application
    execution_state.getExecutionService().resume()
    cleanup()
    return
Пример #11
0
def gettimeofday():
    pid = int(execution_state.getVariableService().readValue(
        "$AARCH64::$System::$Memory::$CONTEXTIDR_EL1.PROCID")) & 0xffffffff

    # get timeval pointer and timezone pointer
    timeval_ptr = int(
        execution_state.getRegisterService().getValue("R0")) & 0xffffffff
    timezone_ptr = int(
        execution_state.getRegisterService().getValue("R1")) & 0xffffffff
    if config.debug:
        print "[gettimeofday] pid = %#x, timeval_ptr = %0#10x, timezone_ptr = %0#10x" % (
            pid, timeval_ptr, timezone_ptr)
    config.log_print(
        "[gettimeofday] pid = %#x, timeval_ptr = %0#10x, timezone_ptr = %0#10x"
        % (pid, timeval_ptr, timezone_ptr))

    if timeval_ptr == 0x0:
        execution_state.getExecutionService().resume()
        cleanup()
        return

    # disable itself
    for idx in range(
            0,
            execution_state.getBreakpointService().getBreakpointCount()):
        brk_object = execution_state.getBreakpointService().getBreakpoint(idx)
        if (int(brk_object.getAddresses()[0])
                & 0xffffffff) == config.brk_gettimeofday:
            brk_object.disable()

    brk_gettimeofday = config.libc_base + config.gettimeofday_end - config.libc_file_offset + config.libc_memory_offset
    execution_state.getExecutionService().resumeTo(brk_gettimeofday)
    try:
        execution_state.getExecutionService().waitForStop(
            60000)  # wait for 60s
    except DebugException:
        raise RuntimeError("wtf !!!")

    # obtain tv_sec value
    tv_sec_ptr = timeval_ptr + 0x0
    tv_sec = memory.readMemory32(tv_sec_ptr)

    # obtain tv_usec_value
    tv_usec_ptr = timeval_ptr + 0x4
    tv_usec = memory.readMemory32(tv_usec_ptr)

    if config.debug:
        print "[gettimeofday] (origin) pid = %#x, tv_sec = %0#10x, tv_usec = %0#10x" % (
            pid, tv_sec, tv_usec)
    config.log_print(
        "[gettimeofday] (origin) pid = %#x, tv_sec = %0#10x, tv_usec = %0#10x"
        % (pid, tv_sec, tv_usec))

    # anti time checking
    tv_sec_old, tv_usec_old = config.load_time_info()
    if tv_sec < tv_sec_old:
        pass
    else:
        if tv_sec_old != 0 and tv_usec_old != 0:
            time_interval = (tv_sec * 1000000L +
                             tv_usec) - (tv_sec_old * 1000000L + tv_usec_old)
            if time_interval > 1 * TIME_INTERVAL:
                tv_sec_new = int(
                    ((tv_sec_old * 1000000L + tv_usec_old) + 1 * TIME_INTERVAL)
                    / 1000000L)
                tv_usec_new = int(((tv_sec_old * 1000000L + tv_usec_old) +
                                   1 * TIME_INTERVAL) -
                                  (tv_sec_new * 1000000L))
                time_old = tv_sec_old * 1000000L + tv_usec_old
                time_new = tv_sec_new * 1000000L + tv_usec_new
                assert time_new == (time_old + 1 * TIME_INTERVAL)

                time_memory_old = tv_sec_old * (2**32) * 1L + tv_usec_old
                print "[old] sec = %#x, usec = %#x, in-memory = %#x" % (
                    tv_sec_old, tv_usec_old, time_memory_old)
                time_memory_new = tv_sec_new * (2**32) * 1L + tv_usec_new
                print "[new] sec = %#x, usec = %#x, in-memory = %#x" % (
                    tv_sec_new, tv_usec_new, time_memory_new)

                config.save_time_info(tv_sec_new, tv_usec_new)
                memory_set_cmd = "memory set %0#10x 0 %#x" % (timeval_ptr +
                                                              0x0, tv_sec_new)
                execution_state.executeDSCommand(memory_set_cmd)
                memory_set_cmd = "memory set %0#10x 0 %#x" % (timeval_ptr +
                                                              0x4, tv_usec_new)
                execution_state.executeDSCommand(memory_set_cmd)

                # obtain tv_sec value
                tv_sec_ptr = timeval_ptr + 0x0
                tv_sec = memory.readMemory32(tv_sec_ptr)

                # obtain tv_usec_value
                tv_usec_ptr = timeval_ptr + 0x4
                tv_usec = memory.readMemory32(tv_usec_ptr)

                if config.debug:
                    print "[gettimeofday] (adjust) pid = %#x, tv_sec = %0#10x, tv_usec = %0#10x" % (
                        pid, tv_sec, tv_usec)
                config.log_print(
                    "[gettimeofday] (adjust) pid = %#x, tv_sec = %0#10x, tv_usec = %0#10x"
                    % (pid, tv_sec, tv_usec))
            else:
                config.save_time_info(tv_sec, tv_usec)
        elif tv_sec_old == 0 and tv_usec_old == 0:
            config.save_time_info(tv_sec, tv_usec)
        else:
            raise RuntimeError("invalid timeval valus !!!")

    # enable itself
    for idx in range(
            0,
            execution_state.getBreakpointService().getBreakpointCount()):
        brk_object = execution_state.getBreakpointService().getBreakpoint(idx)
        if (int(brk_object.getAddresses()[0])
                & 0xffffffff) == config.brk_gettimeofday:
            brk_object.enable()

    # continue the execution of the target application
    execution_state.getExecutionService().resume()
    cleanup()
    return
Пример #12
0
def LoadMethod():
    # -1-

    # get the "dst" parameter
    dst_ptr = int(execution_state.getRegisterService().getValue("SP")) + 0x4
    dst_val = memory.readMemory32(dst_ptr)
    if config.debug:
        print "[LoadMethod] dst = %0#10x" % dst_val

    # very strange !!!
    if (dst_val == 0x0) or (dst_val == 0x00000001):
        execution_state.getExecutionService().resume()
        return

    # get the return address of the LoadMethod
    brk_return_address = int(
        execution_state.getRegisterService().getValue("LR")) & 0xfffffffe
    if config.debug:
        print "[LoadMethod] return address = %0#10x" % brk_return_address

    # -2-

    # resume to the end of the LoadMethod
    brk_LoadMethod_end = config.libart_base + config.LoadMethod_end - config.libart_file_offset + config.libart_memory_offset
    execution_state.getExecutionService().resumeTo(brk_LoadMethod_end)
    try:
        execution_state.getExecutionService().waitForStop(
            120000)  # wait for 120s
    except DebugException:
        raise RuntimeError("wtf !!!")

    # get the pointer that refers to ArtMethod
    art_method_ptr = dst_val

    # read the "declaring_class_" field of ArtMethod
    art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
    # read the "root_" field of GcRoot
    art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
    # read the "refeence_" field of CompressesReference
    art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
    art_method_declaring_class_root_reference_val = memory.readMemory32(
        art_method_declaring_class_root_reference_ptr)

    class_ptr = art_method_declaring_class_root_reference_val

    # read the "dex_cache_" field of Class
    class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
    # read the "reference_" field of HeapReference
    class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
    class_dex_cache_reference_val = memory.readMemory32(
        class_dex_cache_reference_ptr)
    dex_cache_ptr = class_dex_cache_reference_val
    # read the "dex_file_" field of DexCache
    dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
    dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)

    dex_file_ptr = dex_cache_dex_file_val

    # read the "begin_" field of DexFile
    dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
    dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val

    # read the "size_" field of DexFile
    dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
    dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

    # read the "location_" field of DexFile
    dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
    # retrieve the value of std::string
    dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val

    # we only focus on the Java invocation appeared in the target package
    if not config.package_filter(dex_file_location_string_val):
        # continue the execution of the target application
        execution_state.getExecutionService().resume()
        cleanup()
        return

    # read the "access_flags_" field of ArtMethod
    art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
    art_method_access_flags_value = memory.readMemory32(
        art_method_access_flags_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::access_flags_ = %#x (%s)" % (
            art_method_access_flags_value,
            config.resolve_access_flags(art_method_access_flags_value))

    # read the "dex_code_item_offset_" field of ArtMethod
    art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
    art_method_dex_code_item_offset_value = memory.readMemory32(
        art_method_dex_code_item_offset_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value

    # read the "tries_size" field of the "DexFile::CodeItem" structure
    tries_size_off = (
        (dex_file_begin_val + art_method_dex_code_item_offset_value)
        & 0xffffffff) + config.offset_DexFile_CodeItem_tries_size_
    tries_size_val = memory.readMemory16(tries_size_off)
    if config.debug:
        print "[LoadMethod] ArtMethod::CodeItem::tries_size_ = %#x" % tries_size_val

    # read the "insns_size_in_code_units_" field of the "DexFile::CodeItem" structure
    code_item_insns_size_in_code_units_off = (
        (dex_file_begin_val + art_method_dex_code_item_offset_value) &
        0xffffffff) + config.offset_DexFile_CodeItem_insns_size_in_code_units_
    code_item_insns_size_in_code_units_val = memory.readMemory32(
        code_item_insns_size_in_code_units_off)
    if config.debug:
        print "[LoadMethod] ArtMethod::CodeItem::insns_size_in_code_units_ = %#x" % code_item_insns_size_in_code_units_val

    # read the "dex_method_index_" field of ArtMethod
    art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
    art_method_dex_method_index_val = memory.readMemory32(
        art_method_dex_method_index_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val

    # resolve
    string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
    type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
    proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
    method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)

    class_idx = method_id_item.get_class_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    class_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, class_idx)
    class_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, class_descriptor_idx)
    # if config.debug:
    # print "[LoadMethod] class name = %s" % class_descriptor_content

    name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off,
                                           art_method_dex_method_index_val)
    name_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, name_idx)
    # if config.debug:
    # print "[LoadMethod] method name = %s" % name_content

    proto_idx = method_id_item.get_proto_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    proto_return_type_idx = proto_id_item.get_return_type_idx(
        dex_file_begin_val, proto_ids_off, proto_idx)
    proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, proto_return_type_idx)
    proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
    # if config.debug:
    # print "[LoadMethod] return type = %s" % proto_return_type_descriptor_content

    parameters_content = ""
    proto_parameters_list = proto_id_item.get_parameters_list(
        dex_file_begin_val, proto_ids_off, proto_idx)
    if len(proto_parameters_list) == 0:
        parameters_content = "()"
    else:
        for parameter_idx in range(len(proto_parameters_list)):
            parameter_type_idx = proto_parameters_list[parameter_idx]
            parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, parameter_type_idx)
            parameter_type_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off,
                parameter_type_descriptor_idx)

            if len(proto_parameters_list) == 1:
                parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
            else:
                if parameter_idx == 0:
                    parameters_content = parameters_content + "(" + parameter_type_descriptor_content
                elif parameter_idx == (len(proto_parameters_list) - 1):
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
                else:
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content
    # if config.debug:
    # print "[DoCall] parameters = %s" % parameters_content

    method_signature = "%s %s->%s %s%s" % (
        config.resolve_method_access_flags(art_method_access_flags_value),
        class_descriptor_content, proto_return_type_descriptor_content,
        name_content, parameters_content)
    if config.debug:
        print "[LoadMethod] method signature = %s" % method_signature

    config.log_print("[LoadMethod] origin     method signature = %s" %
                     method_signature)

    origin_ArtMethod_declaring_class = class_ptr
    origin_ArtMethod_access_flags = art_method_access_flags_value
    origin_ArtMethod_dex_code_item_offset = art_method_dex_code_item_offset_value
    origin_ArtMethod_dex_method_index = art_method_dex_method_index_val
    origin_ArtMethod_signature = method_signature

    # -3-

    # resume to the return address of the LoadMethod
    execution_state.getExecutionService().resumeTo(brk_return_address)
    try:
        execution_state.getExecutionService().waitForStop(
            120000)  # wait for 120s
    except DebugException:
        raise RuntimeError("wtf !!!")

    # read the "declaring_class_" field of ArtMethod
    art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
    # read the "root_" field of GcRoot
    art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
    # read the "refeence_" field of CompressesReference
    art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
    art_method_declaring_class_root_reference_val = memory.readMemory32(
        art_method_declaring_class_root_reference_ptr)

    class_ptr = art_method_declaring_class_root_reference_val

    # read the "dex_cache_" field of Class
    class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
    # read the "reference_" field of HeapReference
    class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
    class_dex_cache_reference_val = memory.readMemory32(
        class_dex_cache_reference_ptr)
    dex_cache_ptr = class_dex_cache_reference_val
    # read the "dex_file_" field of DexCache
    dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
    dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)

    dex_file_ptr = dex_cache_dex_file_val

    # read the "begin_" field of DexFile
    dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
    dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val

    # read the "size_" field of DexFile
    dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
    dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

    # read the "location_" field of DexFile
    dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
    # retrieve the value of std::string
    dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val

    # # we only focus on the Java invocation appeared in the target package
    # if not config.package_filter(dex_file_location_string_val):
    # # continue the execution of the target application
    # execution_state.getExecutionService().resume()
    # cleanup()
    # return

    # read the "access_flags_" field of ArtMethod
    art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
    art_method_access_flags_value = memory.readMemory32(
        art_method_access_flags_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::access_flags_ = %#x (%s)" % (
            art_method_access_flags_value,
            config.resolve_access_flags(art_method_access_flags_value))

    # read the "dex_code_item_offset_" field of ArtMethod
    art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
    art_method_dex_code_item_offset_value = memory.readMemory32(
        art_method_dex_code_item_offset_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value

    # read the "tries_size" field of the "DexFile::CodeItem" structure
    tries_size_off = (
        (dex_file_begin_val + art_method_dex_code_item_offset_value)
        & 0xffffffff) + config.offset_DexFile_CodeItem_tries_size_
    tries_size_val = memory.readMemory16(tries_size_off)
    if config.debug:
        print "[LoadMethod] ArtMethod::CodeItem::tries_size_ = %#x" % tries_size_val

    # read the "insns_size_in_code_units_" field of the "DexFile::CodeItem" structure
    code_item_insns_size_in_code_units_off = (
        (dex_file_begin_val + art_method_dex_code_item_offset_value) &
        0xffffffff) + config.offset_DexFile_CodeItem_insns_size_in_code_units_
    code_item_insns_size_in_code_units_val = memory.readMemory32(
        code_item_insns_size_in_code_units_off)
    if config.debug:
        print "[LoadMethod] ArtMethod::CodeItem::insns_size_in_code_units_ = %#x" % code_item_insns_size_in_code_units_val

    # read the "dex_method_index_" field of ArtMethod
    art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
    art_method_dex_method_index_val = memory.readMemory32(
        art_method_dex_method_index_ptr)
    if config.debug:
        print "[LoadMethod] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val

    # resolve
    string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
    type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
    proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
    method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)

    class_idx = method_id_item.get_class_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    class_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, class_idx)
    class_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, class_descriptor_idx)
    # if config.debug:
    # print "[LoadMethod] class name = %s" % class_descriptor_content

    name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off,
                                           art_method_dex_method_index_val)
    name_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, name_idx)
    # if config.debug:
    # print "[LoadMethod] method name = %s" % name_content

    proto_idx = method_id_item.get_proto_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    proto_return_type_idx = proto_id_item.get_return_type_idx(
        dex_file_begin_val, proto_ids_off, proto_idx)
    proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, proto_return_type_idx)
    proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
    # if config.debug:
    # print "[LoadMethod] return type = %s" % proto_return_type_descriptor_content

    parameters_content = ""
    proto_parameters_list = proto_id_item.get_parameters_list(
        dex_file_begin_val, proto_ids_off, proto_idx)
    if len(proto_parameters_list) == 0:
        parameters_content = "()"
    else:
        for parameter_idx in range(len(proto_parameters_list)):
            parameter_type_idx = proto_parameters_list[parameter_idx]
            parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, parameter_type_idx)
            parameter_type_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off,
                parameter_type_descriptor_idx)

            if len(proto_parameters_list) == 1:
                parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
            else:
                if parameter_idx == 0:
                    parameters_content = parameters_content + "(" + parameter_type_descriptor_content
                elif parameter_idx == (len(proto_parameters_list) - 1):
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
                else:
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content
    # if config.debug:
    # print "[DoCall] parameters = %s" % parameters_content

    method_signature = "%s %s->%s %s%s" % (
        config.resolve_method_access_flags(art_method_access_flags_value),
        class_descriptor_content, proto_return_type_descriptor_content,
        name_content, parameters_content)
    if config.debug:
        print "[LoadMethod] method signature = %s" % method_signature

    config.log_print("[LoadMethod] suspicious method signature = %s" %
                     method_signature)

    suspicious_ArtMethod_declaring_class = class_ptr
    suspicious_ArtMethod_access_flags = art_method_access_flags_value
    suspicious_ArtMethod_dex_code_item_offset = art_method_dex_code_item_offset_value
    suspicious_ArtMethod_dex_method_index = art_method_dex_method_index_val
    suspicious_ArtMethod_signature = method_signature

    # if (origin_ArtMethod_declaring_class != suspicious_ArtMethod_declaring_class) or \
    # (origin_ArtMethod_access_flags != suspicious_ArtMethod_access_flags) or \
    # (origin_ArtMethod_dex_code_item_offset != suspicious_ArtMethod_dex_code_item_offset):
    # config.log_print("[LoadMethod] hooked !!!")
    # assert origin_ArtMethod_dex_method_index == suspicious_ArtMethod_dex_method_index
    # config.log_print("[LoadMethod][origin]     declaring_class_ = %0#10x, access_flags_ = %#x, dex_code_item_offset_ = %0#10x" % (origin_ArtMethod_declaring_class, origin_ArtMethod_access_flags, origin_ArtMethod_dex_code_item_offset))
    # config.log_print("[LoadMethod][suspicious] declaring_class_ = %0#10x, access_flags_ = %#x, dex_code_item_offset_ = %0#10x" % (suspicious_ArtMethod_declaring_class, suspicious_ArtMethod_access_flags, suspicious_ArtMethod_dex_code_item_offset))

    # # dump the code_item on-demand
    # padding = 0x2 if (tries_size_val > 0) and (code_item_insns_size_in_code_units_val % 2 == 1) else 0x0
    # code_item_size = config.offset_DexFile_CodeItem_insns_size_in_code_units_ + 0x4 + 0x2 * code_item_insns_size_in_code_units_val + padding + 0x8 * tries_size_val
    # code_item_size = code_item_size + encoded_catch_handler_list.parse_encoded_catch_handler_list(dex_file_begin_val, suspicious_ArtMethod_dex_code_item_offset + code_item_size, tries_size_val)
    # file_path = os.path.join(config.workspace, config.dex_directory, "code_item_%#x_%0#10x.bin" % (origin_ArtMethod_dex_method_index, origin_ArtMethod_dex_code_item_offset))
    # file_format = "binary"
    # file_vtl_start_address = (dex_file_begin_val + suspicious_ArtMethod_dex_code_item_offset) & 0xffffffff
    # file_vtl_end_address = ((dex_file_begin_val + suspicious_ArtMethod_dex_code_item_offset) & 0xffffffff) + code_item_size - 0x1
    # memory.dump(file_path, file_format, file_vtl_start_address, file_vtl_end_address)

    # Notice: for ijiami-16, we force dump the code_item
    if (art_method_dex_code_item_offset_value != 0x0):
        padding = 0x2 if (tries_size_val > 0) and (
            code_item_insns_size_in_code_units_val % 2 == 1) else 0x0
        code_item_size = config.offset_DexFile_CodeItem_insns_size_in_code_units_ + 0x4 + 0x2 * code_item_insns_size_in_code_units_val + padding + 0x8 * tries_size_val
        code_item_size = code_item_size + encoded_catch_handler_list.parse_encoded_catch_handler_list(
            dex_file_begin_val, suspicious_ArtMethod_dex_code_item_offset +
            code_item_size, tries_size_val)
        file_path = os.path.join(
            config.workspace, config.dex_directory,
            "code_item_%#x_%0#10x.bin" %
            (origin_ArtMethod_dex_method_index,
             origin_ArtMethod_dex_code_item_offset))
        file_format = "binary"
        file_vtl_start_address = (
            dex_file_begin_val +
            suspicious_ArtMethod_dex_code_item_offset) & 0xffffffff
        file_vtl_end_address = (
            (dex_file_begin_val + suspicious_ArtMethod_dex_code_item_offset)
            & 0xffffffff) + code_item_size - 0x1
        memory.dump(file_path, file_format, file_vtl_start_address,
                    file_vtl_end_address)

    # continue the execution of the target application
    execution_state.getExecutionService().resume()
    cleanup()
    return
Пример #13
0
def parse_header_item(header_item_ptr):
    magic = memory.retrieve_byte_array(header_item_ptr + offset_magic, 0x8)
    checksum = memory.readMemory32(header_item_ptr + offset_checksum)
    signature = memory.retrieve_byte_array(header_item_ptr + offset_signature,
                                           0x14)
    file_szie = memory.readMemory32(header_item_ptr + offset_file_size)
    header_size = memory.readMemory32(header_item_ptr + offset_header_size)
    assert header_size == 0x70
    endian_tag = memory.readMemory32(header_item_ptr + offset_endian_tag)
    link_size = memory.readMemory32(header_item_ptr + offset_link_size)
    link_off = memory.readMemory32(header_item_ptr + offset_link_off)
    map_off = memory.readMemory32(header_item_ptr + offset_map_off)
    string_ids_size = memory.readMemory32(header_item_ptr +
                                          offset_string_ids_size)
    string_ids_off = memory.readMemory32(header_item_ptr +
                                         offset_string_ids_off)
    type_ids_size = memory.readMemory32(header_item_ptr + offset_type_ids_size)
    type_ids_off = memory.readMemory32(header_item_ptr + offset_type_ids_off)
    proto_ids_size = memory.readMemory32(header_item_ptr +
                                         offset_proto_ids_size)
    proto_ids_off = memory.readMemory32(header_item_ptr + offset_proto_ids_off)
    field_ids_size = memory.readMemory32(header_item_ptr +
                                         offset_field_ids_size)
    field_ids_off = memory.readMemory32(header_item_ptr + offset_field_ids_off)
    method_ids_size = memory.readMemory32(header_item_ptr +
                                          offset_method_ids_size)
    method_ids_off = memory.readMemory32(header_item_ptr +
                                         offset_method_ids_off)
    class_defs_size = memory.readMemory32(header_item_ptr +
                                          offset_class_defs_size)
    class_defs_off = memory.readMemory32(header_item_ptr +
                                         offset_class_defs_off)
    data_size = memory.readMemory32(header_item_ptr + offset_data_size)
    data_off = memory.readMemory32(header_item_ptr + offset_data_off)

    if config.debug:
        print "[header_item] magic = %s" % byte_array_to_hex_string(magic)
        print "[header_item] checksum = %#x" % checksum
        print "[header_item] signature = %s" % byte_array_to_hex_string(
            signature)
        print "[header_item] file_szie = %#x" % file_szie
        print "[header_item] header_size = %#x" % header_size
        print "[header_item] endian_tag = %#x" % endian_tag
        print "[header_item] link_size = %#x" % link_size
        print "[header_item] link_off = %#x" % link_off
        print "[header_item] map_off = %#x" % map_off
        print "[header_item] string_ids_size = %#x" % string_ids_size
        print "[header_item] string_ids_off = %#x" % string_ids_off
        print "[header_item] type_ids_size = %#x" % type_ids_size
        print "[header_item] type_ids_off = %#x" % type_ids_off
        print "[header_item] proto_ids_size = %#x" % proto_ids_size
        print "[header_item] proto_ids_off = %#x" % proto_ids_off
        print "[header_item] field_ids_size = %#x" % field_ids_size
        print "[header_item] field_ids_off = %#x" % field_ids_off
        print "[header_item] method_ids_size = %#x" % method_ids_size
        print "[header_item] method_ids_off = %#x" % method_ids_off
        print "[header_item] class_defs_size = %#x" % class_defs_size
        print "[header_item] class_defs_off = %#x" % class_defs_off
        print "[header_item] data_size = %#x" % data_size
        print "[header_item] data_off = %#x" % data_off
Пример #14
0
def ArtInterpreterToCompiledCodeBridge():
    # # *essential* for robustness, remove the ArtQuickToInterpreterBridge breakpoint to guarantee that we have at least one available hardware breakpoint
    # rm_brks = []
    # for breakpoint_index in range(0, execution_state.getBreakpointService().getBreakpointCount()):
    # breakpoint_object = execution_state.getBreakpointService().getBreakpoint(breakpoint_index)
    # if (int(breakpoint_object.getAddresses()[0]) & 0xffffffff) == config.brk_ArtQuickToInterpreterBridge:
    # rm_brks.append(breakpoint_object)
    # for brk_obj in rm_brks:
    # brk_obj.remove()

    # -1- for caller

    # get the "caller" parameter
    caller_ptr = int(execution_state.getRegisterService().getValue("R1"))
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] caller = %0#10x" % caller_ptr

    # get the pointer that refers to ArtMethod
    art_method_ptr = caller_ptr

    # read the "declaring_class_" field of ArtMethod
    art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
    # read the "root_" field of GcRoot
    art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
    # read the "refeence_" field of CompressesReference
    art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
    art_method_declaring_class_root_reference_val = memory.readMemory32(
        art_method_declaring_class_root_reference_ptr)

    class_ptr = art_method_declaring_class_root_reference_val

    # read the "dex_cache_" field of Class
    class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
    # read the "reference_" field of HeapReference
    class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
    class_dex_cache_reference_val = memory.readMemory32(
        class_dex_cache_reference_ptr)
    dex_cache_ptr = class_dex_cache_reference_val
    # read the "dex_file_" field of DexCache
    dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
    dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)

    dex_file_ptr = dex_cache_dex_file_val

    # read the "begin_" field of DexFile
    dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
    dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val

    # read the "size_" field of DexFile
    dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
    dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

    # read the "location_" field of DexFile
    dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
    # retrieve the value of std::string
    dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val

    # # we only focus on the method invocation from the target package
    # if not config.package_filter(dex_file_location_string_val):
    # # continue the execution of the target application
    # execution_state.getExecutionService().resume()
    # cleanup()
    # return

    # read the "access_flags_" field of ArtMethod
    art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
    art_method_access_flags_value = memory.readMemory32(
        art_method_access_flags_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::access_flags_ = %#x (%s)" % (
            art_method_access_flags_value,
            config.resolve_access_flags(art_method_access_flags_value))

    # read the "dex_code_item_offset_" field of ArtMethod
    art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
    art_method_dex_code_item_offset_value = memory.readMemory32(
        art_method_dex_code_item_offset_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value

    # read the "dex_method_index_" field of ArtMethod
    art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
    art_method_dex_method_index_val = memory.readMemory32(
        art_method_dex_method_index_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val

    # resolve
    string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
    type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
    proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
    method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)

    class_idx = method_id_item.get_class_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    class_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, class_idx)
    class_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, class_descriptor_idx)
    # if config.debug:
    # print "[ArtInterpreterToCompiledCodeBridge] class name = %s" % class_descriptor_content

    name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off,
                                           art_method_dex_method_index_val)
    name_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, name_idx)
    # if config.debug:
    # print "[ArtInterpreterToCompiledCodeBridge] method name = %s" % name_content

    proto_idx = method_id_item.get_proto_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    proto_return_type_idx = proto_id_item.get_return_type_idx(
        dex_file_begin_val, proto_ids_off, proto_idx)
    proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, proto_return_type_idx)
    proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
    # if config.debug:
    # print "[ArtInterpreterToCompiledCodeBridge] return type = %s" % proto_return_type_descriptor_content

    parameters_content = ""
    proto_parameters_list = proto_id_item.get_parameters_list(
        dex_file_begin_val, proto_ids_off, proto_idx)
    if len(proto_parameters_list) == 0:
        parameters_content = "()"
    else:
        for parameter_idx in range(len(proto_parameters_list)):
            parameter_type_idx = proto_parameters_list[parameter_idx]
            parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, parameter_type_idx)
            parameter_type_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off,
                parameter_type_descriptor_idx)

            if len(proto_parameters_list) == 1:
                parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
            else:
                if parameter_idx == 0:
                    parameters_content = parameters_content + "(" + parameter_type_descriptor_content
                elif parameter_idx == (len(proto_parameters_list) - 1):
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
                else:
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content
    # if config.debug:
    # print "[ArtInterpreterToCompiledCodeBridge] parameters = %s" % parameters_content

    caller_method_signature = "%s %s->%s %s%s" % (
        config.resolve_method_access_flags(art_method_access_flags_value),
        class_descriptor_content, proto_return_type_descriptor_content,
        name_content, parameters_content)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] caller signature = %s" % caller_method_signature

    # -2- for callee

    # get the "shadow_frame" parameter
    shadow_frame_ptr = int(execution_state.getRegisterService().getValue("R2"))
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] shadow_frame = %0#10x" % shadow_frame_ptr
    # retrieve the "method_" field of ShadowFrame structure
    shadow_frame_method_ptr = memory.readMemory32(
        shadow_frame_ptr + config.offset_ShadowFrame_method_)

    # get the pointer that refers to ArtMethod
    art_method_ptr = shadow_frame_method_ptr

    # read the "declaring_class_" field of ArtMethod
    art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
    # read the "root_" field of GcRoot
    art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
    # read the "refeence_" field of CompressesReference
    art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
    art_method_declaring_class_root_reference_val = memory.readMemory32(
        art_method_declaring_class_root_reference_ptr)

    class_ptr = art_method_declaring_class_root_reference_val

    # read the "dex_cache_" field of Class
    class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
    # read the "reference_" field of HeapReference
    class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
    class_dex_cache_reference_val = memory.readMemory32(
        class_dex_cache_reference_ptr)
    dex_cache_ptr = class_dex_cache_reference_val
    # read the "dex_file_" field of DexCache
    dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
    dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)

    dex_file_ptr = dex_cache_dex_file_val

    # read the "begin_" field of DexFile
    dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
    dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val

    # read the "size_" field of DexFile
    dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
    dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

    # read the "location_" field of DexFile
    dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
    # retrieve the value of std::string
    dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val

    # if config.package_filter(dex_file_location_string_val):
    # # we make an assumption that method invocations within the target package will not trigger the ArtQuickToInterpreterBridge breakpoint
    # pass
    # else:
    # # reset the ArtQuickToInterpreterBridge breakpoint itself
    # pid = int(execution_state.getVariableService().readValue("$AARCH64::$System::$Memory::$CONTEXTIDR_EL1.PROCID")) & 0xffffffff
    # brk_ArtQuickToInterpreterBridge_cmd = "hbreak" + " " + str(hex(config.brk_ArtQuickToInterpreterBridge)).replace('L', '') + " " + "context" + " " + str(hex(pid)).replace('L', '')
    # execution_state.executeDSCommand(brk_ArtQuickToInterpreterBridge_cmd)
    # for idx in range(0, execution_state.getBreakpointService().getBreakpointCount()):
    # brk_object = execution_state.getBreakpointService().getBreakpoint(idx)
    # if (int(brk_object.getAddresses()[0]) & 0xffffffff) == config.brk_ArtQuickToInterpreterBridge:
    # bs_ArtQuickToInterpreterBridge_cmd = "break-script" + " " + str(brk_object.getId()) + " " + os.path.join(config.workspace, config.script_directory, config.ArtQuickToInterpreterBridge_script)
    # execution_state.executeDSCommand(bs_ArtQuickToInterpreterBridge_cmd)
    # brk_object.enable()

    # # # continue the execution of the target application
    # # execution_state.getExecutionService().resume()
    # # return

    # read the "access_flags_" field of ArtMethod
    art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
    art_method_access_flags_value = memory.readMemory32(
        art_method_access_flags_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::access_flags_ = %#x (%s)" % (
            art_method_access_flags_value,
            config.resolve_access_flags(art_method_access_flags_value))

    # read the "dex_code_item_offset_" field of ArtMethod
    art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
    art_method_dex_code_item_offset_value = memory.readMemory32(
        art_method_dex_code_item_offset_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value

    # read the "dex_method_index_" field of ArtMethod
    art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
    art_method_dex_method_index_val = memory.readMemory32(
        art_method_dex_method_index_ptr)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val

    # resolve
    string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
    type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
    proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
    method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)

    class_idx = method_id_item.get_class_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    class_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, class_idx)
    class_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, class_descriptor_idx)
    # if config.debug:
    # print "[ArtInterpreterToCompiledCodeBridge] class name = %s" % class_descriptor_content

    name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off,
                                           art_method_dex_method_index_val)
    name_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, name_idx)
    # if config.debug:
    # print "[ArtInterpreterToCompiledCodeBridge] method name = %s" % name_content

    proto_idx = method_id_item.get_proto_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    proto_return_type_idx = proto_id_item.get_return_type_idx(
        dex_file_begin_val, proto_ids_off, proto_idx)
    proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, proto_return_type_idx)
    proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
    # if config.debug:
    # print "[ArtInterpreterToCompiledCodeBridge] return type = %s" % proto_return_type_descriptor_content

    parameters_content = ""
    proto_parameters_list = proto_id_item.get_parameters_list(
        dex_file_begin_val, proto_ids_off, proto_idx)
    if len(proto_parameters_list) == 0:
        parameters_content = "()"
    else:
        for parameter_idx in range(len(proto_parameters_list)):
            parameter_type_idx = proto_parameters_list[parameter_idx]
            parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, parameter_type_idx)
            parameter_type_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off,
                parameter_type_descriptor_idx)

            if len(proto_parameters_list) == 1:
                parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
            else:
                if parameter_idx == 0:
                    parameters_content = parameters_content + "(" + parameter_type_descriptor_content
                elif parameter_idx == (len(proto_parameters_list) - 1):
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
                else:
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content
    # if config.debug:
    # print "[ArtInterpreterToCompiledCodeBridge] parameters = %s" % parameters_content

    callee_method_signature = "%s %s->%s %s%s" % (
        config.resolve_method_access_flags(art_method_access_flags_value),
        class_descriptor_content, proto_return_type_descriptor_content,
        name_content, parameters_content)
    if config.debug:
        print "[ArtInterpreterToCompiledCodeBridge] callee signature = %s" % callee_method_signature

    config.log_print(
        "[ArtInterpreterToCompiledCodeBridge] caller signature = %s" %
        caller_method_signature)
    config.log_print(
        "[ArtInterpreterToCompiledCodeBridge] callee signature = %s" %
        callee_method_signature)

    # continue the execution of the target application
    execution_state.getExecutionService().resume()
    cleanup()
    return
Пример #15
0
def get_class_idx(dex_file_off, class_defs_off, class_def_id):
	class_def_item_ptr = dex_file_off + class_defs_off + class_def_id * 0x20
	return memory.readMemory32(class_def_item_ptr + offset_class_idx)
Пример #16
0
def dump_modified_method(origin_method_list, suspicious_method_list):
	assert len(origin_method_list) == len(suspicious_method_list)
	
	for idx in range(len(origin_method_list)):
		origin_method = origin_method_list[idx]
		suspicious_method = suspicious_method_list[idx]
		if origin_method != suspicious_method:
			assert origin_method[0] == suspicious_method[0]
			assert origin_method[3] == suspicious_method[3]
			
			# read the "declaring_class_" field of ArtMethod
			art_method_declaring_class_ptr = origin_method[0]
			# read the "root_" field of GcRoot
			art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
			# read the "refeence_" field of CompressesReference
			art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
			art_method_declaring_class_root_reference_val = memory.readMemory32(art_method_declaring_class_root_reference_ptr)
			
			class_ptr = art_method_declaring_class_root_reference_val
			
			# read the "dex_cache_" field of Class
			class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
			# read the "reference_" field of HeapReference
			class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
			class_dex_cache_reference_val = memory.readMemory32(class_dex_cache_reference_ptr)
			dex_cache_ptr = class_dex_cache_reference_val
			# read the "dex_file_" field of DexCache
			dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
			dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)
			
			dex_file_ptr = dex_cache_dex_file_val
			
			# read the "begin_" field of DexFile
			dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
			dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
			
			art_method_dex_method_index_val = origin_method[3]
			
			# resolve 
			string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
			type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
			proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
			method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)
			
			class_idx = method_id_item.get_class_idx(dex_file_begin_val, method_ids_off, art_method_dex_method_index_val)
			class_descriptor_idx = type_id_item.get_descriptor_idx(dex_file_begin_val, type_ids_off, class_idx)
			class_descriptor_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, class_descriptor_idx)
				
			name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off, art_method_dex_method_index_val)
			name_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, name_idx)
			
			proto_idx = method_id_item.get_proto_idx(dex_file_begin_val, method_ids_off, art_method_dex_method_index_val)
			proto_return_type_idx = proto_id_item.get_return_type_idx(dex_file_begin_val, proto_ids_off, proto_idx)
			proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(dex_file_begin_val, type_ids_off, proto_return_type_idx)
			proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
			
			parameters_content = ""
			proto_parameters_list = proto_id_item.get_parameters_list(dex_file_begin_val, proto_ids_off, proto_idx)
			if len(proto_parameters_list) == 0:
				parameters_content = "()"
			else:
				for parameter_idx in range(len(proto_parameters_list)):
					parameter_type_idx = proto_parameters_list[parameter_idx]
					parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(dex_file_begin_val, type_ids_off, parameter_type_idx)
					parameter_type_descriptor_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, parameter_type_descriptor_idx)
				
					if len(proto_parameters_list) == 1:
						parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
					else:
						if parameter_idx == 0:
							parameters_content = parameters_content + "(" + parameter_type_descriptor_content
						elif parameter_idx == (len(proto_parameters_list) - 1):
							parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
						else:
							parameters_content = parameters_content + "," + parameter_type_descriptor_content
			
			method_signature = "?? %s->%s %s%s" % (class_descriptor_content, proto_return_type_descriptor_content, name_content, parameters_content)
			
			config.log_print("[ClassModification] mirror::Class has been modified !!!")
			config.log_print("[ClassModification][origin]     signature = %s, access_flags_ = %#x, dex_code_item_offset_ = %0#10x, entry_point_from_quick_compiled_code = %0#10x" % (method_signature, origin_method[1], origin_method[2], origin_method[8]))
			config.log_print("[ClassModification][suspicious] signature = %s, access_flags_ = %#x, dex_code_item_offset_ = %0#10x, entry_point_from_quick_compiled_code = %0#10x" % (method_signature, suspicious_method[1], suspicious_method[2], suspicious_method[8]))
			
			if origin_method[2] != suspicious_method[2]:
				# dump the code_item on-demand
				tries_size_off = ((dex_file_begin_val + suspicious_method[2]) & 0xffffffff) + config.offset_DexFile_CodeItem_tries_size_
				print "[ClassModification] tries_size_off = %#x" % tries_size_off
				tries_size_val = memory.readMemory16(tries_size_off)
				code_item_insns_size_in_code_units_off = ((dex_file_begin_val + suspicious_method[2]) & 0xffffffff) + config.offset_DexFile_CodeItem_insns_size_in_code_units_
				print "[ClassModification] code_item_insns_size_in_code_units_off = %#x" % code_item_insns_size_in_code_units_off
				code_item_insns_size_in_code_units_val = memory.readMemory32(code_item_insns_size_in_code_units_off)
				padding = 0x2 if (tries_size_val > 0) and (code_item_insns_size_in_code_units_val % 2 == 1) else 0x0
				code_item_size = config.offset_DexFile_CodeItem_insns_size_in_code_units_ + 0x4 + 0x2 * code_item_insns_size_in_code_units_val + padding + 0x8 * tries_size_val
				code_item_size = code_item_size + encoded_catch_handler_list.parse_encoded_catch_handler_list(dex_file_begin_val, suspicious_method[2] + code_item_size, tries_size_val)
				file_path = os.path.join(config.workspace, config.dex_directory, "code_item_%#x_%0#10x.bin" % (origin_method[3], origin_method[2]))
				file_format = "binary"
				file_vtl_start_address = (dex_file_begin_val + suspicious_method[2]) & 0xffffffff
				file_vtl_end_address = ((dex_file_begin_val + suspicious_method[2]) & 0xffffffff) + code_item_size - 0x1
				memory.dump(file_path, file_format, file_vtl_start_address, file_vtl_end_address)
Пример #17
0
def force_initializing(origin_class_ptr, mirror_class_ptrs, mirror_class_names):
	# save register values
	origin_R0_val = int(execution_state.getRegisterService().getValue("R0")) & 0xffffffff
	origin_R1_val = int(execution_state.getRegisterService().getValue("R1")) & 0xffffffff
	origin_R2_val = int(execution_state.getRegisterService().getValue("R2")) & 0xffffffff
	origin_R3_val = int(execution_state.getRegisterService().getValue("R3")) & 0xffffffff
	origin_R9_val = int(execution_state.getRegisterService().getValue("R9")) & 0xffffffff
	origin_R10_val = int(execution_state.getRegisterService().getValue("R10")) & 0xffffffff
	origin_R11_val = int(execution_state.getRegisterService().getValue("R11")) & 0xffffffff
	origin_R12_val = int(execution_state.getRegisterService().getValue("R12")) & 0xffffffff
	origin_SP_val = int(execution_state.getRegisterService().getValue("SP")) & 0xffffffff
	origin_LR_val = int(execution_state.getRegisterService().getValue("LR")) & 0xffffffff
	origin_CPSR_val = int(execution_state.getRegisterService().getValue("CPSR")) & 0xffffffff
	
	# save stack content
	page_size = 0x1000
	page_vtl_start_address = origin_SP_val - (origin_SP_val % page_size)
	# print "[InitClass] origin SP = %0#10x" % origin_SP_val
	# print "[InitClass] origin page = %0#10x" % page_vtl_start_address
	origin_content = execution_state.getMemoryService().read(page_vtl_start_address, page_size)
	# print origin_content
	
	for idx in range(len(mirror_class_ptrs)):
		class_name = mirror_class_names[idx]
		print "[InitClass] force init class -> %s" % class_name
		config.log_print("[InitClass] force init class -> %s" % (class_name))
		class_ptr = mirror_class_ptrs[idx]
		
		# recover register values
		execution_state.getRegisterService().setValue("R0", origin_R0_val)
		execution_state.getRegisterService().setValue("R1", origin_R1_val)
		execution_state.getRegisterService().setValue("R2", origin_R2_val)
		execution_state.getRegisterService().setValue("R3", origin_R3_val)
		execution_state.getRegisterService().setValue("R9", origin_R9_val)
		execution_state.getRegisterService().setValue("R10", origin_R10_val)
		execution_state.getRegisterService().setValue("R11", origin_R11_val)
		execution_state.getRegisterService().setValue("R12", origin_R12_val)
		execution_state.getRegisterService().setValue("SP", origin_SP_val)
		execution_state.getRegisterService().setValue("LR", origin_LR_val)
		execution_state.getRegisterService().setValue("CPSR", origin_CPSR_val)
		
		# recover stack content
		execution_state.getMemoryService().write(page_vtl_start_address, origin_content)
		
		# hook
		execution_state.getMemoryService().writeMemory32(origin_R2_val, class_ptr)
		
		# execute
		while True:
			execution_state.getExecutionService().resumeTo(config.brk_InitClass_end)
			try:
				execution_state.getExecutionService().waitForStop(10 * 60 * 1000)  # wait for 10mins
			except DebugException:
				raise RuntimeError("wtf !!!")
			
			reference_ptr = int(execution_state.getRegisterService().getValue("R4")) & 0xffffffff
			ret_address = memory.readMemory32((int(execution_state.getRegisterService().getValue("SP")) & 0xffffffff) + 0x20 + 0x4 * 5)
			if origin_LR_val == ret_address and origin_R2_val == reference_ptr:
				break
		
		execution_state.getRegisterService().setValue("PC", config.brk_InitClass)
		print "[InitClass] force init done <- %s" % class_name
		config.log_print("[InitClass] force init done <- %s" % (class_name))
	
	# recover register values
	execution_state.getRegisterService().setValue("R0", origin_R0_val)
	execution_state.getRegisterService().setValue("R1", origin_R1_val)
	execution_state.getRegisterService().setValue("R2", origin_R2_val)
	execution_state.getRegisterService().setValue("R3", origin_R3_val)
	execution_state.getRegisterService().setValue("R9", origin_R9_val)
	execution_state.getRegisterService().setValue("R10", origin_R10_val)
	execution_state.getRegisterService().setValue("R11", origin_R11_val)
	execution_state.getRegisterService().setValue("R12", origin_R12_val)
	execution_state.getRegisterService().setValue("SP", origin_SP_val)
	execution_state.getRegisterService().setValue("LR", origin_LR_val)
	execution_state.getRegisterService().setValue("CPSR", origin_CPSR_val)
	
	# recover stack content
	execution_state.getMemoryService().write(page_vtl_start_address, origin_content)
	
	# recover memory content
	execution_state.getMemoryService().writeMemory32(origin_R2_val, origin_class_ptr)
	
	return
Пример #18
0
def get_method_ids_off(header_item_ptr):
    return memory.readMemory32(header_item_ptr + offset_method_ids_off)
Пример #19
0
def get_descriptor_idx(dex_file_off, type_ids_off, type_id):
    type_id_item_ptr = dex_file_off + type_ids_off + type_id * 0x4
    return memory.readMemory32(type_id_item_ptr + offset_descriptor_idx)
Пример #20
0
def parse_type_id_item(dex_file_off, type_ids_off, type_id):
    type_id_item_ptr = dex_file_off + type_ids_off + type_id * 0x4

    descriptor_idx = memory.readMemory32(type_id_item_ptr +
                                         offset_descriptor_idx)
Пример #21
0
def InvokeWithArgArray():
    # -1- for callee

    # get the "method" parameter
    method_ptr = int(
        execution_state.getRegisterService().getValue("R1")) & 0xffffffff
    if config.debug:
        print "[InvokeWithArgArray] callee = %0#10x" % method_ptr

    # get the pointer that refers to ArtMethod
    art_method_ptr = method_ptr

    # read the "declaring_class_" field of ArtMethod
    art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
    # read the "root_" field of GcRoot
    art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
    # read the "refeence_" field of CompressesReference
    art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
    art_method_declaring_class_root_reference_val = memory.readMemory32(
        art_method_declaring_class_root_reference_ptr)

    class_ptr = art_method_declaring_class_root_reference_val

    # read the "dex_cache_" field of Class
    class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
    # read the "reference_" field of HeapReference
    class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
    class_dex_cache_reference_val = memory.readMemory32(
        class_dex_cache_reference_ptr)
    dex_cache_ptr = class_dex_cache_reference_val
    # read the "dex_file_" field of DexCache
    dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
    dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)

    dex_file_ptr = dex_cache_dex_file_val

    # read the "begin_" field of DexFile
    dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
    dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
    if config.debug:
        print "[InvokeWithArgArray] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val

    # read the "size_" field of DexFile
    dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
    dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
    if config.debug:
        print "[InvokeWithArgArray] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

    # read the "location_" field of DexFile
    dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
    # retrieve the value of std::string
    dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
    if config.debug:
        print "[InvokeWithArgArray] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val

    # read the "access_flags_" field of ArtMethod
    art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
    art_method_access_flags_value = memory.readMemory32(
        art_method_access_flags_ptr)
    if config.debug:
        print "[InvokeWithArgArray] ArtMethod::access_flags_ = %#x (%s)" % (
            art_method_access_flags_value,
            config.resolve_access_flags(art_method_access_flags_value))

    # read the "dex_code_item_offset_" field of ArtMethod
    art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
    art_method_dex_code_item_offset_value = memory.readMemory32(
        art_method_dex_code_item_offset_ptr)
    if config.debug:
        print "[InvokeWithArgArray] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value

    # read the "dex_method_index_" field of ArtMethod
    art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
    art_method_dex_method_index_val = memory.readMemory32(
        art_method_dex_method_index_ptr)
    if config.debug:
        print "[InvokeWithArgArray] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val

    # resolve
    string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
    type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
    proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
    method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)

    class_idx = method_id_item.get_class_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    class_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, class_idx)
    class_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, class_descriptor_idx)
    # if config.debug:
    # print "[InvokeWithArgArray] class name = %s" % class_descriptor_content

    name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off,
                                           art_method_dex_method_index_val)
    name_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, name_idx)
    # if config.debug:
    # print "[InvokeWithArgArray] method name = %s" % name_content

    proto_idx = method_id_item.get_proto_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    proto_return_type_idx = proto_id_item.get_return_type_idx(
        dex_file_begin_val, proto_ids_off, proto_idx)
    proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, proto_return_type_idx)
    proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
    # if config.debug:
    # print "[InvokeWithArgArray] return type = %s" % proto_return_type_descriptor_content

    parameters_content = ""
    proto_parameters_list = proto_id_item.get_parameters_list(
        dex_file_begin_val, proto_ids_off, proto_idx)
    if len(proto_parameters_list) == 0:
        parameters_content = "()"
    else:
        for parameter_idx in range(len(proto_parameters_list)):
            parameter_type_idx = proto_parameters_list[parameter_idx]
            parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, parameter_type_idx)
            parameter_type_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off,
                parameter_type_descriptor_idx)

            if len(proto_parameters_list) == 1:
                parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
            else:
                if parameter_idx == 0:
                    parameters_content = parameters_content + "(" + parameter_type_descriptor_content
                elif parameter_idx == (len(proto_parameters_list) - 1):
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
                else:
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content
    # if config.debug:
    # print "[InvokeWithArgArray] parameters = %s" % parameters_content

    callee_method_signature = "%s %s->%s %s%s" % (
        config.resolve_method_access_flags(art_method_access_flags_value),
        class_descriptor_content, proto_return_type_descriptor_content,
        name_content, parameters_content)
    if config.debug:
        print "[InvokeWithArgArray] callee signature = %s" % callee_method_signature

    return_address = int(
        execution_state.getRegisterService().getValue("LR")) & 0xffffffff
    config.log_print("[InvokeWithArgArray] callee signature = %s, LR = %#x" %
                     (callee_method_signature, return_address))

    if "getSystemService" in callee_method_signature:
        cleanup()
        return

    if "getSubscriberId" in callee_method_signature:
        cleanup()
        return

    if "getNetworkOperatorName" in callee_method_signature:
        cleanup()
        return

    # continue the execution of the target application
    execution_state.getExecutionService().resume()
    cleanup()
    return
Пример #22
0
def ClassModification():
    # at the very beginning, we remove the DexFile breakpoint
    rm_brks = []
    for breakpoint_index in range(
            0,
            execution_state.getBreakpointService().getBreakpointCount()):
        breakpoint_object = execution_state.getBreakpointService(
        ).getBreakpoint(breakpoint_index)
        if (int(breakpoint_object.getAddresses()[0])
                & 0xffffffff) == config.brk_DexFile:
            rm_brks.append(breakpoint_object)
    for brk_obj in rm_brks:
        brk_obj.remove()

    # -1- DoCall

    # get the "shadow_frame" parameter
    shadow_frame_ptr = int(execution_state.getRegisterService().getValue("R2"))
    if config.debug:
        print "[ClassModification] shadow_frame = %0#10x" % shadow_frame_ptr

    # retrieve the "method_" field of ShadowFrame structure
    shadow_frame_method_ptr = memory.readMemory32(
        shadow_frame_ptr + config.offset_ShadowFrame_method_)

    # get the pointer that refers to ArtMethod
    art_method_ptr = shadow_frame_method_ptr
    if config.debug:
        print "[ClassModification] caller = %0#10x" % art_method_ptr

    # read the "declaring_class_" field of ArtMethod
    art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
    # read the "root_" field of GcRoot
    art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
    # read the "refeence_" field of CompressesReference
    art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
    art_method_declaring_class_root_reference_val = memory.readMemory32(
        art_method_declaring_class_root_reference_ptr)

    class_ptr = art_method_declaring_class_root_reference_val
    caller_class_ptr = class_ptr

    # read the "dex_cache_" field of Class
    class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
    # read the "reference_" field of HeapReference
    class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
    class_dex_cache_reference_val = memory.readMemory32(
        class_dex_cache_reference_ptr)
    dex_cache_ptr = class_dex_cache_reference_val
    # read the "dex_file_" field of DexCache
    dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
    dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)

    dex_file_ptr = dex_cache_dex_file_val

    # read the "begin_" field of DexFile
    dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
    dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val

    # read the "size_" field of DexFile
    dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
    dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

    # read the "location_" field of DexFile
    dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
    # retrieve the value of std::string
    dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val

    # we only focus on the Java invocation appeared in the target package
    if not config.package_filter(dex_file_location_string_val):
        # continue the execution of the target application
        execution_state.getExecutionService().resume()
        cleanup()
        return

    # read the "access_flags_" field of ArtMethod
    art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
    art_method_access_flags_value = memory.readMemory32(
        art_method_access_flags_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::access_flags_ = %#x (%s)" % (
            art_method_access_flags_value,
            config.resolve_access_flags(art_method_access_flags_value))

    # read the "dex_code_item_offset_" field of ArtMethod
    art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
    art_method_dex_code_item_offset_value = memory.readMemory32(
        art_method_dex_code_item_offset_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value

    # read the "dex_method_index_" field of ArtMethod
    art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
    art_method_dex_method_index_val = memory.readMemory32(
        art_method_dex_method_index_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val

    # resolve
    string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
    type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
    proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
    method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)

    class_idx = method_id_item.get_class_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    class_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, class_idx)
    class_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, class_descriptor_idx)
    # if config.debug:
    # print "[ClassModification] class name = %s" % class_descriptor_content

    name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off,
                                           art_method_dex_method_index_val)
    name_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, name_idx)
    # if config.debug:
    # print "[ClassModification] method name = %s" % name_content

    proto_idx = method_id_item.get_proto_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    proto_return_type_idx = proto_id_item.get_return_type_idx(
        dex_file_begin_val, proto_ids_off, proto_idx)
    proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, proto_return_type_idx)
    proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
    # if config.debug:
    # print "[ClassModification] return type = %s" % proto_return_type_descriptor_content

    parameters_content = ""
    proto_parameters_list = proto_id_item.get_parameters_list(
        dex_file_begin_val, proto_ids_off, proto_idx)
    if len(proto_parameters_list) == 0:
        parameters_content = "()"
    else:
        for parameter_idx in range(len(proto_parameters_list)):
            parameter_type_idx = proto_parameters_list[parameter_idx]
            parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, parameter_type_idx)
            parameter_type_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off,
                parameter_type_descriptor_idx)

            if len(proto_parameters_list) == 1:
                parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
            else:
                if parameter_idx == 0:
                    parameters_content = parameters_content + "(" + parameter_type_descriptor_content
                elif parameter_idx == (len(proto_parameters_list) - 1):
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
                else:
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content
    # if config.debug:
    # print "[ClassModification] parameters = %s" % parameters_content

    caller_method_signature = "%s %s->%s %s%s" % (
        config.resolve_method_access_flags(art_method_access_flags_value),
        class_descriptor_content, proto_return_type_descriptor_content,
        name_content, parameters_content)
    if config.debug:
        print "[ClassModification] caller signature = %s" % caller_method_signature

    # -2- for callee

    # get the "called_method" parameter
    callee_ptr = int(execution_state.getRegisterService().getValue("R0"))

    # get the pointer that refers to ArtMethod
    art_method_ptr = callee_ptr
    if config.debug:
        print "[ClassModification] callee = %0#10x" % art_method_ptr

    # read the "declaring_class_" field of ArtMethod
    art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
    # read the "root_" field of GcRoot
    art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
    # read the "refeence_" field of CompressesReference
    art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
    art_method_declaring_class_root_reference_val = memory.readMemory32(
        art_method_declaring_class_root_reference_ptr)

    class_ptr = art_method_declaring_class_root_reference_val
    callee_class_ptr = class_ptr

    # read the "dex_cache_" field of Class
    class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
    # read the "reference_" field of HeapReference
    class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
    class_dex_cache_reference_val = memory.readMemory32(
        class_dex_cache_reference_ptr)
    dex_cache_ptr = class_dex_cache_reference_val
    # read the "dex_file_" field of DexCache
    dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
    dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)

    dex_file_ptr = dex_cache_dex_file_val

    # read the "begin_" field of DexFile
    dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
    dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val

    # read the "size_" field of DexFile
    dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
    dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

    # read the "location_" field of DexFile
    dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
    # retrieve the value of std::string
    dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val

    # we only focus on the Java invocation appeared in the target package
    if not config.package_filter(dex_file_location_string_val):
        # continue the execution of the target application
        execution_state.getExecutionService().resume()
        cleanup()
        return

    # read the "access_flags_" field of ArtMethod
    art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
    art_method_access_flags_value = memory.readMemory32(
        art_method_access_flags_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::access_flags_ = %#x (%s)" % (
            art_method_access_flags_value,
            config.resolve_access_flags(art_method_access_flags_value))

    # we only focus on the Java -> native invocation
    if not (art_method_access_flags_value & config.ACC_NATIVE
            == config.ACC_NATIVE):
        # continue the execution of the target application
        execution_state.getExecutionService().resume()
        cleanup()
        return

    # read the "dex_code_item_offset_" field of ArtMethod
    art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
    art_method_dex_code_item_offset_value = memory.readMemory32(
        art_method_dex_code_item_offset_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value

    # read the "dex_method_index_" field of ArtMethod
    art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
    art_method_dex_method_index_val = memory.readMemory32(
        art_method_dex_method_index_ptr)
    if config.debug:
        print "[ClassModification] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val

    # resolve
    string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
    type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
    proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
    method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)

    class_idx = method_id_item.get_class_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    class_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, class_idx)
    class_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, class_descriptor_idx)
    # if config.debug:
    # print "[ClassModification] class name = %s" % class_descriptor_content

    name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off,
                                           art_method_dex_method_index_val)
    name_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, name_idx)
    # if config.debug:
    # print "[ClassModification] method name = %s" % name_content

    proto_idx = method_id_item.get_proto_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    proto_return_type_idx = proto_id_item.get_return_type_idx(
        dex_file_begin_val, proto_ids_off, proto_idx)
    proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, proto_return_type_idx)
    proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
    # if config.debug:
    # print "[ClassModification] return type = %s" % proto_return_type_descriptor_content

    parameters_content = ""
    proto_parameters_list = proto_id_item.get_parameters_list(
        dex_file_begin_val, proto_ids_off, proto_idx)
    if len(proto_parameters_list) == 0:
        parameters_content = "()"
    else:
        for parameter_idx in range(len(proto_parameters_list)):
            parameter_type_idx = proto_parameters_list[parameter_idx]
            parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, parameter_type_idx)
            parameter_type_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off,
                parameter_type_descriptor_idx)

            if len(proto_parameters_list) == 1:
                parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
            else:
                if parameter_idx == 0:
                    parameters_content = parameters_content + "(" + parameter_type_descriptor_content
                elif parameter_idx == (len(proto_parameters_list) - 1):
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
                else:
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content
    # if config.debug:
    # print "[ClassModification] parameters = %s" % parameters_content

    callee_method_signature = "%s %s->%s %s%s" % (
        config.resolve_method_access_flags(art_method_access_flags_value),
        class_descriptor_content, proto_return_type_descriptor_content,
        name_content, parameters_content)
    if config.debug:
        print "[ClassModification] callee signature = %s" % callee_method_signature

    config.log_print("[ClassModification]          caller signature = %s" %
                     caller_method_signature)
    config.log_print("[ClassModification] previous callee signature = %s" %
                     callee_method_signature)

    # resolve the mirror::Class structure
    origin_method_list = resolve_mirror_Class(caller_class_ptr)
    suspicious_method_list = None  # we will fill this list afterwards

    # -2- GenericJniMethodEnd

    # disable the DoCall breakpoint to avoid noisy
    for breakpoint_index in range(
            0,
            execution_state.getBreakpointService().getBreakpointCount()):
        breakpoint_object = execution_state.getBreakpointService(
        ).getBreakpoint(breakpoint_index)
        if (int(breakpoint_object.getAddresses()[0])
                & 0xffffffff) == config.brk_DoCall:
            breakpoint_object.disable()

    # resume to the start address of the GenericJniMethodEnd method
    previous_callee_method_signature = callee_method_signature
    brk_GenericJniMethodEnd = config.libart_base + config.GenericJniMethodEnd_start - config.libart_file_offset + config.libart_memory_offset
    while True:
        execution_state.getExecutionService().resumeTo(brk_GenericJniMethodEnd)
        try:
            execution_state.getExecutionService().waitForStop(
                60000)  # wait for 60s
        except DebugException:
            raise RuntimeError("wtf !!!")

        # get the pointer that refers to ArtMethod*
        art_method_ptr_ptr = int(
            execution_state.getRegisterService().getValue("SP")) + 0x8
        # get the pointer that refers to ArtMethod
        art_method_ptr = memory.readMemory32(art_method_ptr_ptr)

        # read the "declaring_class_" field of ArtMethod
        art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
        # read the "root_" field of GcRoot
        art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
        # read the "reference_" field of CompressesReference
        art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
        art_method_declaring_class_root_reference_val = memory.readMemory32(
            art_method_declaring_class_root_reference_ptr)

        class_ptr = art_method_declaring_class_root_reference_val

        # read the "dex_cache_" field of Class
        class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
        # read the "reference_" field of HeapReference
        class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
        class_dex_cache_reference_val = memory.readMemory32(
            class_dex_cache_reference_ptr)
        dex_cache_ptr = class_dex_cache_reference_val
        # read the "dex_file_" field of DexCache
        dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
        dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)

        dex_file_ptr = dex_cache_dex_file_val

        # read the "begin_" field of DexFile
        dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
        dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
        if config.debug:
            print "[ClassModification] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val

        callee_method_signature = "unknown"
        if dex_file_begin_val == 0x0:
            pass
        else:
            # read the "size_" field of DexFile
            dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
            dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
            if config.debug:
                print "[ClassModification] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

            # read the "location_" field of DexFile
            dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
            # retrieve the value of std::string
            dex_file_location_string_val = retrieve_string_value(
                dex_file_location_ptr)
            if config.debug:
                print "[ClassModification] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val

            # we focus on the JNI method defined in the target packages
            if not config.package_filter(dex_file_location_string_val):
                # continue the while-loop
                continue

            # read the "access_flags_" field of ArtMethod
            art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
            art_method_access_flags_value = memory.readMemory32(
                art_method_access_flags_ptr)
            if config.debug:
                print "[ClassModification] ArtMethod::access_flags_ = %#x (%s)" % (
                    art_method_access_flags_value,
                    config.resolve_access_flags(art_method_access_flags_value))

            # read the "dex_code_item_offset_" field of ArtMethod
            art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
            art_method_dex_code_item_offset_value = memory.readMemory32(
                art_method_dex_code_item_offset_ptr)
            if config.debug:
                print "[ClassModification] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value

            # read the "dex_method_index_" field of ArtMethod
            art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
            art_method_dex_method_index_val = memory.readMemory32(
                art_method_dex_method_index_ptr)
            if config.debug:
                print "[ClassModification] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val

            # resolve
            string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
            type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
            proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
            method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)

            class_idx = method_id_item.get_class_idx(
                dex_file_begin_val, method_ids_off,
                art_method_dex_method_index_val)
            class_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, class_idx)
            class_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off, class_descriptor_idx)
            # if config.debug:
            # print "[ClassModification] class name = %s" % class_descriptor_content

            name_idx = method_id_item.get_name_idx(
                dex_file_begin_val, method_ids_off,
                art_method_dex_method_index_val)
            name_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off, name_idx)
            # if config.debug:
            # print "[ClassModification] method name = %s" % name_content

            proto_idx = method_id_item.get_proto_idx(
                dex_file_begin_val, method_ids_off,
                art_method_dex_method_index_val)
            proto_return_type_idx = proto_id_item.get_return_type_idx(
                dex_file_begin_val, proto_ids_off, proto_idx)
            proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, proto_return_type_idx)
            proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off,
                proto_return_type_descriptor_idx)
            # if config.debug:
            # print "[ClassModification] return type = %s" % proto_return_type_descriptor_content

            parameters_content = ""
            proto_parameters_list = proto_id_item.get_parameters_list(
                dex_file_begin_val, proto_ids_off, proto_idx)
            if len(proto_parameters_list) == 0:
                parameters_content = "()"
            else:
                for parameter_idx in range(len(proto_parameters_list)):
                    parameter_type_idx = proto_parameters_list[parameter_idx]
                    parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(
                        dex_file_begin_val, type_ids_off, parameter_type_idx)
                    parameter_type_descriptor_content = string_id_item.get_string_id_item_data(
                        dex_file_begin_val, string_ids_off,
                        parameter_type_descriptor_idx)

                    if len(proto_parameters_list) == 1:
                        parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
                    else:
                        if parameter_idx == 0:
                            parameters_content = parameters_content + "(" + parameter_type_descriptor_content
                        elif parameter_idx == (len(proto_parameters_list) - 1):
                            parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
                        else:
                            parameters_content = parameters_content + "," + parameter_type_descriptor_content
            # if config.debug:
            # print "[ClassModification] parameters = %s" % parameters_content

            callee_method_signature = "%s %s->%s %s%s" % (
                config.resolve_method_access_flags(
                    art_method_access_flags_value), class_descriptor_content,
                proto_return_type_descriptor_content, name_content,
                parameters_content)
            if config.debug:
                print "[ClassModification] method signature = %s" % callee_method_signature

        config.log_print("[ClassModification] current  callee signature = %s" %
                         callee_method_signature)

        if callee_method_signature == previous_callee_method_signature:
            # resolve the mirror::Class structure
            suspicious_method_list = resolve_mirror_Class(caller_class_ptr)
            break  # jump out of the while-loop

    # -3-

    # make a comparison between the origin_method_list and the suspicous_method_list
    assert suspicious_method_list is not None
    for idx in range(len(origin_method_list)):
        origin_method = origin_method_list[idx]
        suspicious_method = suspicious_method_list[idx]
        if origin_method != suspicious_method:
            assert origin_method[0] == suspicious_method[0]
            assert origin_method[3] == suspicious_method[3]

            # read the "declaring_class_" field of ArtMethod
            art_method_declaring_class_ptr = origin_method[0]
            # read the "root_" field of GcRoot
            art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
            # read the "refeence_" field of CompressesReference
            art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
            art_method_declaring_class_root_reference_val = memory.readMemory32(
                art_method_declaring_class_root_reference_ptr)

            class_ptr = art_method_declaring_class_root_reference_val

            # read the "dex_cache_" field of Class
            class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
            # read the "reference_" field of HeapReference
            class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
            class_dex_cache_reference_val = memory.readMemory32(
                class_dex_cache_reference_ptr)
            dex_cache_ptr = class_dex_cache_reference_val
            # read the "dex_file_" field of DexCache
            dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
            dex_cache_dex_file_val = memory.readMemory32(
                dex_cache_dex_file_ptr)

            dex_file_ptr = dex_cache_dex_file_val

            # read the "begin_" field of DexFile
            dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
            dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)

            art_method_dex_method_index_val = origin_method[3]

            # resolve
            string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
            type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
            proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
            method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)

            class_idx = method_id_item.get_class_idx(
                dex_file_begin_val, method_ids_off,
                art_method_dex_method_index_val)
            class_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, class_idx)
            class_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off, class_descriptor_idx)

            name_idx = method_id_item.get_name_idx(
                dex_file_begin_val, method_ids_off,
                art_method_dex_method_index_val)
            name_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off, name_idx)

            proto_idx = method_id_item.get_proto_idx(
                dex_file_begin_val, method_ids_off,
                art_method_dex_method_index_val)
            proto_return_type_idx = proto_id_item.get_return_type_idx(
                dex_file_begin_val, proto_ids_off, proto_idx)
            proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, proto_return_type_idx)
            proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off,
                proto_return_type_descriptor_idx)

            parameters_content = ""
            proto_parameters_list = proto_id_item.get_parameters_list(
                dex_file_begin_val, proto_ids_off, proto_idx)
            if len(proto_parameters_list) == 0:
                parameters_content = "()"
            else:
                for parameter_idx in range(len(proto_parameters_list)):
                    parameter_type_idx = proto_parameters_list[parameter_idx]
                    parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(
                        dex_file_begin_val, type_ids_off, parameter_type_idx)
                    parameter_type_descriptor_content = string_id_item.get_string_id_item_data(
                        dex_file_begin_val, string_ids_off,
                        parameter_type_descriptor_idx)

                    if len(proto_parameters_list) == 1:
                        parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
                    else:
                        if parameter_idx == 0:
                            parameters_content = parameters_content + "(" + parameter_type_descriptor_content
                        elif parameter_idx == (len(proto_parameters_list) - 1):
                            parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
                        else:
                            parameters_content = parameters_content + "," + parameter_type_descriptor_content

            method_signature = "%s %s->%s %s%s" % (
                config.resolve_method_access_flags(
                    art_method_access_flags_value), class_descriptor_content,
                proto_return_type_descriptor_content, name_content,
                parameters_content)

            config.log_print(
                "[ClassModification] mirror::Class has been modified !!!")
            config.log_print(
                "[ClassModification][origin]     signature = %s, access_flags_ = %#x, dex_code_item_offset_ = %0#10x, entry_point_from_quick_compiled_code = %0#10x"
                % (method_signature, origin_method[1], origin_method[2],
                   origin_method[8]))
            config.log_print(
                "[ClassModification][suspicious] signature = %s, access_flags_ = %#x, dex_code_item_offset_ = %0#10x, entry_point_from_quick_compiled_code = %0#10x"
                % (method_signature, suspicious_method[1],
                   suspicious_method[2], suspicious_method[8]))

    # enable the DoCall breakpoint
    for breakpoint_index in range(
            0,
            execution_state.getBreakpointService().getBreakpointCount()):
        breakpoint_object = execution_state.getBreakpointService(
        ).getBreakpoint(breakpoint_index)
        if (int(breakpoint_object.getAddresses()[0])
                & 0xffffffff) == config.brk_DoCall:
            breakpoint_object.enable()

    # continue the execution of the target application
    execution_state.getExecutionService().resume()
    cleanup()
    return
Пример #23
0
def parse_class_def_item(dex_file_off, class_defs_off, class_def_id):
	class_def_item_ptr = dex_file_off + class_defs_off + class_def_id * 0x20
	
	class_idx = memory.readMemory32(class_def_item_ptr + offset_class_idx)
Пример #24
0
def get_string_ids_off(header_item_ptr):
    return memory.readMemory32(header_item_ptr + offset_string_ids_off)
Пример #25
0
def LoadClassMembers():
    # at the very beginning, we are required to ensure that the LoadMethod breakpoint is enabled
    for idx in range(
            0,
            execution_state.getBreakpointService().getBreakpointCount()):
        brk_object = execution_state.getBreakpointService().getBreakpoint(idx)
        if (int(brk_object.getAddresses()[0])
                & 0xffffffff) == config.brk_LoadMethod:
            brk_object.enable()

    # get the "dex_file" parameter
    dex_file_param = int(
        execution_state.getRegisterService().getValue("R2")) & 0xffffffff
    dex_file_ptr = dex_file_param

    # read the "location_" field
    dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
    # retrieve the value of the std::string structure
    dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
    if config.debug:
        print "[LoadClassMembers] location_ = %s" % dex_file_location_string_val

    # we only focus on the DexFile whose location is suspicious
    if not config.package_filter(dex_file_location_string_val):
        # disable the LoadMethod breakpoint here
        for idx in range(
                0,
                execution_state.getBreakpointService().getBreakpointCount()):
            brk_object = execution_state.getBreakpointService().getBreakpoint(
                idx)
            if (int(brk_object.getAddresses()[0])
                    & 0xffffffff) == config.brk_LoadMethod:
                brk_object.disable()

        # continue the execution of the target application
        execution_state.getExecutionService().resume()
        cleanup()
        return

    # read the "begin_" field
    dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
    dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
    if config.debug:
        print "[LoadClassMembers] begin_ = %0#10x" % dex_file_begin_val

    # read the "size_" field
    dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
    dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
    if config.debug:
        print "[LoadClassMembers] size_ = %#x" % dex_file_size_val

    # parse the header_item of the dex file
    header_item.parse_header_item(dex_file_begin_val)

    # # calculate the "size_" value from the "map_off" field of the header_item
    # dex_file_size_val_calc = 0x0
    # if config.package_filter(dex_file_location_string_val):
    # map_off = header_item.get_map_off(dex_file_begin_val)
    # map_list_ptr = dex_file_begin_val + map_off
    # map_list_size_val = memory.readMemory32(map_list_ptr + 0x0)
    # dex_file_size_val_calc = map_off + (0x4) + map_list_size_val * (0x2 + 0x2 + 0x4 + 0x4)

    # config.log_print("[LoadClassMembers] begin_ = %0#10x, size_ = %#x (inferring size = %#x), location_ = %s" % (dex_file_begin_val, dex_file_size_val, dex_file_size_val_calc, dex_file_location_string_val))
    config.log_print(
        "[LoadClassMembers] begin_ = %0#10x, size_ = %#x, location_ = %s" %
        (dex_file_begin_val, dex_file_size_val, dex_file_location_string_val))

    # get the "class_data" parameter
    class_data_param = int(
        execution_state.getRegisterService().getValue("R3")) & 0xffffffff
    class_data_off = class_data_param - dex_file_begin_val

    # parse class_data_item
    static_fields_size_off = 0x0
    static_fields_size, length_static_fields_size = class_data_item.get_static_fields_size(
        dex_file_begin_val, class_data_off, static_fields_size_off)
    config.log_print(
        "[LoadClassMembers] [class_data_item] static_fields_size = %#x" %
        static_fields_size)

    instance_fields_size_off = static_fields_size_off + length_static_fields_size
    instance_fields_size, length_instance_fields_size = class_data_item.get_instance_fields_size(
        dex_file_begin_val, class_data_off, instance_fields_size_off)
    config.log_print(
        "[LoadClassMembers] [class_data_item] instance_fields_size = %#x" %
        instance_fields_size)

    direct_methods_size_off = instance_fields_size_off + length_instance_fields_size
    direct_methods_size, length_direct_methods_size = class_data_item.get_direct_methods_size(
        dex_file_begin_val, class_data_off, direct_methods_size_off)
    config.log_print(
        "[LoadClassMembers] [class_data_item] direct_methods_size = %#x" %
        direct_methods_size)

    virtual_methods_size_off = direct_methods_size_off + length_direct_methods_size
    virtual_methods_size, length_virtual_methods_size = class_data_item.get_virtual_methods_size(
        dex_file_begin_val, class_data_off, virtual_methods_size_off)
    config.log_print(
        "[LoadClassMembers] [class_data_item] virtual_methods_size = %#x" %
        virtual_methods_size)

    static_fields_off = virtual_methods_size_off + length_virtual_methods_size
    static_fields, length_static_fields = class_data_item.get_static_fields(
        dex_file_begin_val, class_data_off, static_fields_off,
        static_fields_size)
    for idx in range(static_fields_size):
        config.log_print(
            "[LoadClassMembers] [class_data_item] static_fields[%d].field_idx_diff = %#x"
            % (idx, static_fields[idx][0]))
        config.log_print(
            "[LoadClassMembers] [class_data_item] static_fields[%d].access_flags = %0#10x"
            % (idx, static_fields[idx][1]))

    instance_fields_off = static_fields_off + length_static_fields
    instance_fields, length_instance_fields = class_data_item.get_instance_fields(
        dex_file_begin_val, class_data_off, instance_fields_off,
        instance_fields_size)
    for idx in range(instance_fields_size):
        config.log_print(
            "[LoadClassMembers] [class_data_item] instance_fields[%d].field_idx_diff = %#x"
            % (idx, instance_fields[idx][0]))
        config.log_print(
            "[LoadClassMembers] [class_data_item] instance_fields[%d].access_flags = %0#10x"
            % (idx, instance_fields[idx][1]))

    direct_methods_off = instance_fields_off + length_instance_fields
    direct_methods, length_direct_methods = class_data_item.get_direct_methods(
        dex_file_begin_val, class_data_off, direct_methods_off,
        direct_methods_size)
    for idx in range(direct_methods_size):
        config.log_print(
            "[LoadClassMembers] [class_data_item] direct_methods[%d].method_idx_diff = %#x"
            % (idx, direct_methods[idx][0]))
        config.log_print(
            "[LoadClassMembers] [class_data_item] direct_methods[%d].access_flags = %0#10x"
            % (idx, direct_methods[idx][1]))
        config.log_print(
            "[LoadClassMembers] [class_data_item] direct_methods[%d].code_off = %0#10x"
            % (idx, direct_methods[idx][2]))

    virtual_methods_off = direct_methods_off + length_direct_methods
    virtual_methods, length_virtual_methods = class_data_item.get_virtual_methods(
        dex_file_begin_val, class_data_off, virtual_methods_off,
        virtual_methods_size)
    for idx in range(virtual_methods_size):
        config.log_print(
            "[LoadClassMembers] [class_data_item] virtual_methods[%d].method_idx_diff = %#x"
            % (idx, virtual_methods[idx][0]))
        config.log_print(
            "[LoadClassMembers] [class_data_item] virtual_methods[%d].access_flags = %0#10x"
            % (idx, virtual_methods[idx][1]))
        config.log_print(
            "[LoadClassMembers] [class_data_item] virtual_methods[%d].code_off = %0#10x"
            % (idx, virtual_methods[idx][2]))

    class_data_size = virtual_methods_off + length_virtual_methods
    if class_data_off < 0:
        config.log_print(
            "[LoadClassMembers] class_data = %0#10x (offset = %#x, size = %#x)"
            % (class_data_param, 0xffffffff + class_data_off, class_data_size))
    else:
        config.log_print(
            "[LoadClassMembers] class_data = %0#10x (offset = %#x, size = %#x)"
            % (class_data_param, class_data_off, class_data_size))

    # dump the class_data_item
    if (class_data_off < 0) or (class_data_off > dex_file_size_val):
        file_path = os.path.join(
            config.workspace, config.dex_directory,
            "class_data_item_%0#10x.bin" %
            (class_data_off if class_data_off > 0 else
             (0xffffffff + class_data_off)))
        file_format = "binary"
        file_vtl_start_address = class_data_param
        file_vtl_end_address = class_data_param + class_data_size - 0x1
        memory.dump(file_path, file_format, file_vtl_start_address,
                    file_vtl_end_address)

    # dump the in-memory DexFile
    file_path = os.path.join(config.workspace, config.dex_directory,
                             dex_file_location_string_val.split("/")[-1])
    if os.path.exists(file_path):
        os.remove(file_path)
    file_format = "binary"
    file_vtl_start_address = dex_file_begin_val
    file_vtl_end_address = dex_file_begin_val + dex_file_size_val - 0x1
    file_path = memory.dump(file_path, file_format, file_vtl_start_address,
                            file_vtl_end_address)

    # continue the execution of the target application
    execution_state.getExecutionService().resume()
    cleanup()
    return
Пример #26
0
def gettimeofday():
    # -- HEAD -- #
    start_prolog()

    # -- BODY -- #

    pid = int(execution_state.getVariableService().readValue(
        "$AARCH64::$System::$Memory::$CONTEXTIDR_EL1.PROCID")) & 0xffffffff

    # only focus on the invocation from app -> gettimeofday
    lr = int(execution_state.getRegisterService().getValue("LR")) & 0xffffffff
    if not config.in_app_range(lr):
        # -- TAIL -- #
        end_prolog()

        # continue the execution of the target application
        execution_state.getExecutionService().resume()
        cleanup()
        return

    # get timeval pointer
    timeval_ptr = int(
        execution_state.getRegisterService().getValue("R0")) & 0xffffffff
    if config.debug:
        print "[gettimeofday] pid = %#x, lr = %0#10x, timeval_ptr = %0#10x" % (
            pid, lr, timeval_ptr)
    config.log_print(
        "[gettimeofday] pid = %#x, lr = %0#10x, timeval_ptr = %0#10x" %
        (pid, lr, timeval_ptr))

    brk_gettimeofday = config.libc_base + config.gettimeofday_end - config.libc_file_offset + config.libc_memory_offset
    execution_state.getExecutionService().resumeTo(brk_gettimeofday)
    try:
        execution_state.getExecutionService().waitForStop(
            60000)  # wait for 60s
    except DebugException:
        raise RuntimeError("wtf !!!")

    # obtain tv_sec value
    tv_sec_ptr = timeval_ptr + 0x0
    tv_sec = memory.readMemory32(tv_sec_ptr)

    # obtain tv_usec_value
    tv_usec_ptr = timeval_ptr + 0x4
    tv_usec = memory.readMemory32(tv_usec_ptr)

    if config.debug:
        print "[gettimeofday] (origin) pid = %#x, tv_sec = %0#10x, tv_usec = %0#10x" % (
            pid, tv_sec, tv_usec)
    # config.log_print("[gettimeofday] (origin) pid = %#x, tv_sec = %0#10x, tv_usec = %0#10x" % (pid, tv_sec, tv_usec))

    # anti time checking
    tv_sec_old, tv_usec_old = config.load_time_info()
    if tv_sec <= tv_sec_old:
        tv_sec = tv_sec_old + 0x1

    if tv_sec < tv_sec_old:
        # TODO: should raise an exception, but we just ignore it at this time
        assert False
    else:
        if tv_sec_old != 0 and tv_usec_old != 0:
            time_interval = (tv_sec * 1000000L +
                             tv_usec) - (tv_sec_old * 1000000L + tv_usec_old)
            if time_interval > TIME_INTERVAL:
                tv_sec_new = int(
                    ((tv_sec_old * 1000000L + tv_usec_old) + TIME_INTERVAL) /
                    1000000L)
                tv_usec_new = int((
                    (tv_sec_old * 1000000L + tv_usec_old) + TIME_INTERVAL) -
                                  (tv_sec_new * 1000000L))

                # verification
                time_old = tv_sec_old * 1000000L + tv_usec_old
                time_new = tv_sec_new * 1000000L + tv_usec_new
                assert time_new == (time_old + TIME_INTERVAL)

                time_memory_old = tv_sec_old * (2**32) * 0x1L + tv_usec_old
                print "[old] sec = %#x, usec = %#x, in-memory = %#x" % (
                    tv_sec_old, tv_usec_old, time_memory_old)
                time_memory_new = tv_sec_new * (2**32) * 0x1L + tv_usec_new
                print "[new] sec = %#x, usec = %#x, in-memory = %#x" % (
                    tv_sec_new, tv_usec_new, time_memory_new)

                config.save_time_info(tv_sec_new, tv_usec_new)

                memory_set_cmd = "memory set %0#10x 0 %#x" % (timeval_ptr +
                                                              0x0, tv_sec_new)
                execution_state.executeDSCommand(memory_set_cmd)
                memory_set_cmd = "memory set %0#10x 0 %#x" % (timeval_ptr +
                                                              0x4, tv_usec_new)
                execution_state.executeDSCommand(memory_set_cmd)

                # obtain tv_sec value
                tv_sec_ptr = timeval_ptr + 0x0
                tv_sec = memory.readMemory32(tv_sec_ptr)

                # obtain tv_usec_value
                tv_usec_ptr = timeval_ptr + 0x4
                tv_usec = memory.readMemory32(tv_usec_ptr)

                if config.debug:
                    print "[gettimeofday] (adjust) pid = %#x, tv_sec = %0#10x, tv_usec = %0#10x" % (
                        pid, tv_sec, tv_usec)
                # config.log_print("[gettimeofday] (adjust) pid = %#x, tv_sec = %0#10x, tv_usec = %0#10x" % (pid, tv_sec, tv_usec))
            else:
                config.save_time_info(tv_sec, tv_usec)
        elif tv_sec_old == 0 and tv_usec_old == 0:
            config.save_time_info(tv_sec, tv_usec)
        else:
            raise RuntimeError("invalid timeval valus !!!")

    # -- TAIL -- #
    end_prolog()

    # continue the execution of the target application
    execution_state.getExecutionService().resume()
    cleanup()
    return
Пример #27
0
def ArtQuickToInterpreterBridge():
	# # at the very beginning, we are required to ensure that the DoCall breakpoint has been enabled
	# for idx in range(0, execution_state.getBreakpointService().getBreakpointCount()):
		# brk_object = execution_state.getBreakpointService().getBreakpoint(idx)
		# enable the DoCall breakpoint
		# if (int(brk_object.getAddresses()[0]) & 0xffffffff) == config.brk_DoCall:
			# brk_object.enable()

	# -1- for caller
	
	# get the "sp" parameter
	sp_ptr = int(execution_state.getRegisterService().getValue("R2"))
	if config.debug:
		print "[ArtQuickToInterpreterBridge] sp = %0#10x" % sp_ptr
	
	# get the pointer that refers to ArtMethod
	art_method_ptr = memory.readMemory32(sp_ptr)
	
	# read the "declaring_class_" field of ArtMethod
	art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
	# read the "root_" field of GcRoot
	art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
	# read the "reference_" field of CompressesReference
	art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
	art_method_declaring_class_root_reference_val = memory.readMemory32(art_method_declaring_class_root_reference_ptr)
	
	class_ptr = art_method_declaring_class_root_reference_val
	
	caller_method_signature = "unknown"
	if class_ptr == 0x0:
		pass
	else:
		# read the "dex_cache_" field of Class
		class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
		# read the "reference_" field of HeapReference
		class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
		class_dex_cache_reference_val = memory.readMemory32(class_dex_cache_reference_ptr)
		dex_cache_ptr = class_dex_cache_reference_val
		# read the "dex_file_" field of DexCache
		dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
		dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)
		
		dex_file_ptr = dex_cache_dex_file_val
		
		# read the "begin_" field of DexFile
		dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
		dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
		if config.debug:
			print "[ArtQuickToInterpreterBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val
			
		# read the "size_" field of DexFile
		dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
		dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
		if config.debug:
			print "[ArtQuickToInterpreterBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

		# read the "location_" field of DexFile
		dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
		# retrieve the value of std::string
		dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
		if config.debug:
			print "[ArtQuickToInterpreterBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val
			
		# # we only focus on the Compiled Code -> Java invocation appeared in the target package
		# if not config.package_filter(dex_file_location_string_val):
			# # continue the execution of the target application
			# execution_state.getExecutionService().resume()
			# cleanup()
			# return
			
		# read the "access_flags_" field of ArtMethod
		art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
		art_method_access_flags_value = memory.readMemory32(art_method_access_flags_ptr)
		if config.debug:
			print "[ArtQuickToInterpreterBridge] ArtMethod::access_flags_ = %#x (%s)" % (art_method_access_flags_value, config.resolve_access_flags(art_method_access_flags_value))
			
		# read the "dex_code_item_offset_" field of ArtMethod
		art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
		art_method_dex_code_item_offset_value = memory.readMemory32(art_method_dex_code_item_offset_ptr)
		if config.debug:
			print "[ArtQuickToInterpreterBridge] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value
		
		# read the "dex_method_index_" field of ArtMethod
		art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
		art_method_dex_method_index_val = memory.readMemory32(art_method_dex_method_index_ptr)
		if config.debug:
			print "[ArtQuickToInterpreterBridge] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val
			
		# resolve 
		string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
		type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
		proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
		method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)
		
		class_idx = method_id_item.get_class_idx(dex_file_begin_val, method_ids_off, art_method_dex_method_index_val)
		class_descriptor_idx = type_id_item.get_descriptor_idx(dex_file_begin_val, type_ids_off, class_idx)
		class_descriptor_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, class_descriptor_idx)
		# if config.debug:
			# print "[ArtQuickToInterpreterBridge] class name = %s" % class_descriptor_content
			
		name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off, art_method_dex_method_index_val)
		name_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, name_idx)
		# if config.debug:
			# print "[ArtQuickToInterpreterBridge] method name = %s" % name_content
		
		proto_idx = method_id_item.get_proto_idx(dex_file_begin_val, method_ids_off, art_method_dex_method_index_val)
		proto_return_type_idx = proto_id_item.get_return_type_idx(dex_file_begin_val, proto_ids_off, proto_idx)
		proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(dex_file_begin_val, type_ids_off, proto_return_type_idx)
		proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
		# if config.debug:
			# print "[ArtQuickToInterpreterBridge] return type = %s" % proto_return_type_descriptor_content
		
		parameters_content = ""
		proto_parameters_list = proto_id_item.get_parameters_list(dex_file_begin_val, proto_ids_off, proto_idx)
		if len(proto_parameters_list) == 0:
			parameters_content = "()"
		else:
			for parameter_idx in range(len(proto_parameters_list)):
				parameter_type_idx = proto_parameters_list[parameter_idx]
				parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(dex_file_begin_val, type_ids_off, parameter_type_idx)
				parameter_type_descriptor_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, parameter_type_descriptor_idx)
			
				if len(proto_parameters_list) == 1:
					parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
				else:
					if parameter_idx == 0:
						parameters_content = parameters_content + "(" + parameter_type_descriptor_content
					elif parameter_idx == (len(proto_parameters_list) - 1):
						parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
					else:
						parameters_content = parameters_content + "," + parameter_type_descriptor_content
		# if config.debug:
			# print "[ArtQuickToInterpreterBridge] parameters = %s" % parameters_content
		
		caller_method_signature = "%s %s->%s %s%s" % (config.resolve_method_access_flags(art_method_access_flags_value), class_descriptor_content, proto_return_type_descriptor_content, name_content, parameters_content)
		if config.debug:
			print "[ArtQuickToInterpreterBridge] caller signature = %s" % caller_method_signature
	
	# -2- for callee
	
	# get the "method" parameter
	method_ptr = int(execution_state.getRegisterService().getValue("R0"))
	if config.debug:
		print "[ArtQuickToInterpreterBridge] method = %0#10x" % method_ptr
		
	# get the pointer that refers to ArtMethod
	art_method_ptr = method_ptr
	
	# read the "declaring_class_" field of ArtMethod
	art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
	# read the "root_" field of GcRoot
	art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
	# read the "reference_" field of CompressesReference
	art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
	art_method_declaring_class_root_reference_val = memory.readMemory32(art_method_declaring_class_root_reference_ptr)
	
	class_ptr = art_method_declaring_class_root_reference_val
	
	# read the "dex_cache_" field of Class
	class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
	# read the "reference_" field of HeapReference
	class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
	class_dex_cache_reference_val = memory.readMemory32(class_dex_cache_reference_ptr)
	dex_cache_ptr = class_dex_cache_reference_val
	# read the "dex_file_" field of DexCache
	dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
	dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)
	
	dex_file_ptr = dex_cache_dex_file_val
	
	# read the "begin_" field of DexFile
	dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
	dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
	if config.debug:
		print "[ArtQuickToInterpreterBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val
		
	# read the "size_" field of DexFile
	dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
	dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
	if config.debug:
		print "[ArtQuickToInterpreterBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

	# read the "location_" field of DexFile
	dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
	# retrieve the value of std::string
	dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
	if config.debug:
		print "[ArtQuickToInterpreterBridge] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val
		
	# we only focus on the Compiled Code -> Java invocation appeared in the target package
	if not config.package_filter(dex_file_location_string_val):
		# continue the execution of the target application
		execution_state.getExecutionService().resume()
		cleanup()
		return
		
	# read the "access_flags_" field of ArtMethod
	art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
	art_method_access_flags_value = memory.readMemory32(art_method_access_flags_ptr)
	if config.debug:
		print "[ArtQuickToInterpreterBridge] ArtMethod::access_flags_ = %#x (%s)" % (art_method_access_flags_value, config.resolve_access_flags(art_method_access_flags_value))
		
	# read the "dex_code_item_offset_" field of ArtMethod
	art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
	art_method_dex_code_item_offset_value = memory.readMemory32(art_method_dex_code_item_offset_ptr)
	if config.debug:
		print "[ArtQuickToInterpreterBridge] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value
	
	# read the "dex_method_index_" field of ArtMethod
	art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
	art_method_dex_method_index_val = memory.readMemory32(art_method_dex_method_index_ptr)
	if config.debug:
		print "[ArtQuickToInterpreterBridge] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val
		
	# resolve 
	string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
	type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
	proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
	method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)
	
	class_idx = method_id_item.get_class_idx(dex_file_begin_val, method_ids_off, art_method_dex_method_index_val)
	class_descriptor_idx = type_id_item.get_descriptor_idx(dex_file_begin_val, type_ids_off, class_idx)
	class_descriptor_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, class_descriptor_idx)
	# if config.debug:
		# print "[ArtQuickToInterpreterBridge] class name = %s" % class_descriptor_content
		
	name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off, art_method_dex_method_index_val)
	name_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, name_idx)
	# if config.debug:
		# print "[ArtQuickToInterpreterBridge] method name = %s" % name_content
	
	proto_idx = method_id_item.get_proto_idx(dex_file_begin_val, method_ids_off, art_method_dex_method_index_val)
	proto_return_type_idx = proto_id_item.get_return_type_idx(dex_file_begin_val, proto_ids_off, proto_idx)
	proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(dex_file_begin_val, type_ids_off, proto_return_type_idx)
	proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
	# if config.debug:
		# print "[ArtQuickToInterpreterBridge] return type = %s" % proto_return_type_descriptor_content
	
	parameters_content = ""
	proto_parameters_list = proto_id_item.get_parameters_list(dex_file_begin_val, proto_ids_off, proto_idx)
	if len(proto_parameters_list) == 0:
		parameters_content = "()"
	else:
		for parameter_idx in range(len(proto_parameters_list)):
			parameter_type_idx = proto_parameters_list[parameter_idx]
			parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(dex_file_begin_val, type_ids_off, parameter_type_idx)
			parameter_type_descriptor_content = string_id_item.get_string_id_item_data(dex_file_begin_val, string_ids_off, parameter_type_descriptor_idx)
		
			if len(proto_parameters_list) == 1:
				parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
			else:
				if parameter_idx == 0:
					parameters_content = parameters_content + "(" + parameter_type_descriptor_content
				elif parameter_idx == (len(proto_parameters_list) - 1):
					parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
				else:
					parameters_content = parameters_content + "," + parameter_type_descriptor_content
	# if config.debug:
		# print "[ArtQuickToInterpreterBridge] parameters = %s" % parameters_content
	
	callee_method_signature = "%s %s->%s %s%s" % (config.resolve_method_access_flags(art_method_access_flags_value), class_descriptor_content, proto_return_type_descriptor_content, name_content, parameters_content)
	if config.debug:
		print "[ArtQuickToInterpreterBridge] callee signature = %s" % callee_method_signature
	
	config.log_print("[ArtQuickToInterpreterBridge] caller signature = %s" % caller_method_signature)
	config.log_print("[ArtQuickToInterpreterBridge] callee signature = %s" % callee_method_signature)
	
	# continue the execution of the target application
	execution_state.getExecutionService().resume()
	cleanup()
	return
Пример #28
0
def get_class_defs_size(header_item_ptr):
    return memory.readMemory32(header_item_ptr + offset_class_defs_size)
Пример #29
0
def DoCall():
    # -1- for caller

    # get the "shadow_frame" parameter
    shadow_frame_ptr = int(execution_state.getRegisterService().getValue("R2"))
    if config.debug:
        print "[DoCall] shadow_frame = %0#10x" % shadow_frame_ptr

    # retrieve the "method_" field of ShadowFrame structure
    shadow_frame_method_ptr = memory.readMemory32(
        shadow_frame_ptr + config.offset_ShadowFrame_method_)

    # get the pointer that refers to ArtMethod
    art_method_ptr = shadow_frame_method_ptr

    # read the "declaring_class_" field of ArtMethod
    art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
    # read the "root_" field of GcRoot
    art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
    # read the "refeence_" field of CompressesReference
    art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
    art_method_declaring_class_root_reference_val = memory.readMemory32(
        art_method_declaring_class_root_reference_ptr)

    class_ptr = art_method_declaring_class_root_reference_val

    # read the "dex_cache_" field of Class
    class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
    # read the "reference_" field of HeapReference
    class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
    class_dex_cache_reference_val = memory.readMemory32(
        class_dex_cache_reference_ptr)
    dex_cache_ptr = class_dex_cache_reference_val
    # read the "dex_file_" field of DexCache
    dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
    dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)

    dex_file_ptr = dex_cache_dex_file_val

    # read the "begin_" field of DexFile
    dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
    dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val

    # read the "size_" field of DexFile
    dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
    dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

    # read the "location_" field of DexFile
    dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
    # retrieve the value of std::string
    dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val

    # # we only focus on the Java invocation appeared in the target package
    # if not config.package_filter(dex_file_location_string_val):
    # # continue the execution of the target application
    # execution_state.getExecutionService().resume()
    # cleanup()
    # return

    # read the "access_flags_" field of ArtMethod
    art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
    art_method_access_flags_value = memory.readMemory32(
        art_method_access_flags_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::access_flags_ = %#x (%s)" % (
            art_method_access_flags_value,
            config.resolve_access_flags(art_method_access_flags_value))

    # read the "dex_code_item_offset_" field of ArtMethod
    art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
    art_method_dex_code_item_offset_value = memory.readMemory32(
        art_method_dex_code_item_offset_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value

    # read the "dex_method_index_" field of ArtMethod
    art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
    art_method_dex_method_index_val = memory.readMemory32(
        art_method_dex_method_index_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val

    # resolve
    string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
    type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
    proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
    method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)

    class_idx = method_id_item.get_class_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    class_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, class_idx)
    class_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, class_descriptor_idx)
    # if config.debug:
    # print "[DoCall] class name = %s" % class_descriptor_content

    name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off,
                                           art_method_dex_method_index_val)
    name_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, name_idx)
    # if config.debug:
    # print "[DoCall] method name = %s" % name_content

    proto_idx = method_id_item.get_proto_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    proto_return_type_idx = proto_id_item.get_return_type_idx(
        dex_file_begin_val, proto_ids_off, proto_idx)
    proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, proto_return_type_idx)
    proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
    # if config.debug:
    # print "[DoCall] return type = %s" % proto_return_type_descriptor_content

    parameters_content = ""
    proto_parameters_list = proto_id_item.get_parameters_list(
        dex_file_begin_val, proto_ids_off, proto_idx)
    if len(proto_parameters_list) == 0:
        parameters_content = "()"
    else:
        for parameter_idx in range(len(proto_parameters_list)):
            parameter_type_idx = proto_parameters_list[parameter_idx]
            parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, parameter_type_idx)
            parameter_type_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off,
                parameter_type_descriptor_idx)

            if len(proto_parameters_list) == 1:
                parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
            else:
                if parameter_idx == 0:
                    parameters_content = parameters_content + "(" + parameter_type_descriptor_content
                elif parameter_idx == (len(proto_parameters_list) - 1):
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
                else:
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content
    # if config.debug:
    # print "[DoCall] parameters = %s" % parameters_content

    caller_method_signature = "%s %s->%s %s%s" % (
        config.resolve_method_access_flags(art_method_access_flags_value),
        class_descriptor_content, proto_return_type_descriptor_content,
        name_content, parameters_content)
    if config.debug:
        print "[DoCall] caller signature = %s" % caller_method_signature

    # -2- for callee

    # get the "called_method" parameter
    callee_ptr = int(execution_state.getRegisterService().getValue("R0"))
    if config.debug:
        print "[DoCall] callee = %0#10x" % callee_ptr

    # get the pointer that refers to ArtMethod
    art_method_ptr = callee_ptr

    # read the "declaring_class_" field of ArtMethod
    art_method_declaring_class_ptr = art_method_ptr + config.offset_ArtMethod_declaring_class_
    # read the "root_" field of GcRoot
    art_method_declaring_class_root_ptr = art_method_declaring_class_ptr + config.offset_GcRoot_root_
    # read the "refeence_" field of CompressesReference
    art_method_declaring_class_root_reference_ptr = art_method_declaring_class_root_ptr + config.offset_CompressesReference_reference_
    art_method_declaring_class_root_reference_val = memory.readMemory32(
        art_method_declaring_class_root_reference_ptr)

    class_ptr = art_method_declaring_class_root_reference_val

    # read the "dex_cache_" field of Class
    class_dex_cache_ptr = class_ptr + config.offset_Class_dex_cache_
    # read the "reference_" field of HeapReference
    class_dex_cache_reference_ptr = class_dex_cache_ptr + config.offset_HeapReference_reference_
    class_dex_cache_reference_val = memory.readMemory32(
        class_dex_cache_reference_ptr)
    dex_cache_ptr = class_dex_cache_reference_val
    # read the "dex_file_" field of DexCache
    dex_cache_dex_file_ptr = dex_cache_ptr + config.offset_DexCache_dex_file_
    dex_cache_dex_file_val = memory.readMemory32(dex_cache_dex_file_ptr)

    dex_file_ptr = dex_cache_dex_file_val

    # read the "begin_" field of DexFile
    dex_file_begin_ptr = dex_file_ptr + config.offset_DexFile_begin_
    dex_file_begin_val = memory.readMemory32(dex_file_begin_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::declaring_class_::dex_cache_::dex_file_::begin_ = %0#10x" % dex_file_begin_val

    # read the "size_" field of DexFile
    dex_file_size_ptr = dex_file_ptr + config.offset_DexFile_size_
    dex_file_size_val = memory.readMemory32(dex_file_size_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::declaring_class_::dex_cache_::dex_file_::size_ = %#x" % dex_file_size_val

    # read the "location_" field of DexFile
    dex_file_location_ptr = dex_file_ptr + config.offset_DexFile_location_
    # retrieve the value of std::string
    dex_file_location_string_val = retrieve_string_value(dex_file_location_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::declaring_class_::dex_cache_::dex_file_::location_ = %s" % dex_file_location_string_val

    # read the "access_flags_" field of ArtMethod
    art_method_access_flags_ptr = art_method_ptr + config.offset_ArtMethod_access_flags_
    art_method_access_flags_value = memory.readMemory32(
        art_method_access_flags_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::access_flags_ = %#x (%s)" % (
            art_method_access_flags_value,
            config.resolve_access_flags(art_method_access_flags_value))

    # read the "dex_code_item_offset_" field of ArtMethod
    art_method_dex_code_item_offset_ptr = art_method_ptr + config.offset_ArtMethod_dex_code_item_offset_
    art_method_dex_code_item_offset_value = memory.readMemory32(
        art_method_dex_code_item_offset_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::dex_code_item_offset_ = %#x" % art_method_dex_code_item_offset_value

    # read the "dex_method_index_" field of ArtMethod
    art_method_dex_method_index_ptr = art_method_ptr + config.offset_ArtMethod_dex_method_index_
    art_method_dex_method_index_val = memory.readMemory32(
        art_method_dex_method_index_ptr)
    if config.debug:
        print "[DoCall] ArtMethod::dex_method_index_ = %#x" % art_method_dex_method_index_val

    # resolve
    string_ids_off = header_item.get_string_ids_off(dex_file_begin_val)
    type_ids_off = header_item.get_type_ids_off(dex_file_begin_val)
    proto_ids_off = header_item.get_proto_ids_off(dex_file_begin_val)
    method_ids_off = header_item.get_method_ids_off(dex_file_begin_val)

    class_idx = method_id_item.get_class_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    class_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, class_idx)
    class_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, class_descriptor_idx)
    # if config.debug:
    # print "[DoCall] class name = %s" % class_descriptor_content

    name_idx = method_id_item.get_name_idx(dex_file_begin_val, method_ids_off,
                                           art_method_dex_method_index_val)
    name_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, name_idx)
    # if config.debug:
    # print "[DoCall] method name = %s" % name_content

    proto_idx = method_id_item.get_proto_idx(dex_file_begin_val,
                                             method_ids_off,
                                             art_method_dex_method_index_val)
    proto_return_type_idx = proto_id_item.get_return_type_idx(
        dex_file_begin_val, proto_ids_off, proto_idx)
    proto_return_type_descriptor_idx = type_id_item.get_descriptor_idx(
        dex_file_begin_val, type_ids_off, proto_return_type_idx)
    proto_return_type_descriptor_content = string_id_item.get_string_id_item_data(
        dex_file_begin_val, string_ids_off, proto_return_type_descriptor_idx)
    # if config.debug:
    # print "[DoCall] return type = %s" % proto_return_type_descriptor_content

    parameters_content = ""
    proto_parameters_list = proto_id_item.get_parameters_list(
        dex_file_begin_val, proto_ids_off, proto_idx)
    if len(proto_parameters_list) == 0:
        parameters_content = "()"
    else:
        for parameter_idx in range(len(proto_parameters_list)):
            parameter_type_idx = proto_parameters_list[parameter_idx]
            parameter_type_descriptor_idx = type_id_item.get_descriptor_idx(
                dex_file_begin_val, type_ids_off, parameter_type_idx)
            parameter_type_descriptor_content = string_id_item.get_string_id_item_data(
                dex_file_begin_val, string_ids_off,
                parameter_type_descriptor_idx)

            if len(proto_parameters_list) == 1:
                parameters_content = parameters_content + "(" + parameter_type_descriptor_content + ")"
            else:
                if parameter_idx == 0:
                    parameters_content = parameters_content + "(" + parameter_type_descriptor_content
                elif parameter_idx == (len(proto_parameters_list) - 1):
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content + ")"
                else:
                    parameters_content = parameters_content + "," + parameter_type_descriptor_content
    # if config.debug:
    # print "[DoCall] parameters = %s" % parameters_content

    callee_method_signature = "%s %s->%s %s%s" % (
        config.resolve_method_access_flags(art_method_access_flags_value),
        class_descriptor_content, proto_return_type_descriptor_content,
        name_content, parameters_content)
    if config.debug:
        print "[DoCall] callee signature = %s" % callee_method_signature

    config.log_print("[DoCall] caller signature = %s" %
                     caller_method_signature)
    config.log_print("[DoCall] callee signature = %s" %
                     callee_method_signature)

    # continue the execution of the target application
    execution_state.getExecutionService().resume()
    cleanup()
    return
Пример #30
0
def InitClass():
	# load class info
	thread_ptr, mirror_class_names, mirror_class_ptrs = config.load_class_info()

	thread_ptr_cur = int(execution_state.getRegisterService().getValue("R1")) & 0xffffffff
	if thread_ptr_cur != thread_ptr:
		# -- TAIL -- #
		end_prolog()
		# continue the execution of the target application
		execution_state.getExecutionService().resume()
		cleanup()
		return
	
	origin_reference_ptr = int(execution_state.getRegisterService().getValue("R2")) & 0xffffffff
	origin_class_ptr = memory.readMemory32(origin_reference_ptr)
	if not (origin_class_ptr in mirror_class_ptrs):
		# -- TAIL -- #
		end_prolog()
		# continue the execution of the target application
		execution_state.getExecutionService().resume()
		cleanup()
		return
		
	origin_ret_address = int(execution_state.getRegisterService().getValue("LR")) & 0xffffffff
		
	for idx in range(len(mirror_class_ptrs)):
		class_ptr = mirror_class_ptrs[idx]
		if origin_class_ptr == class_ptr:
			class_name = mirror_class_names[idx]
			print "[InitClass] init class name = %s, ret = %0#10x" % (class_name, origin_ret_address) 
			config.log_print("[InitClass] init class -> %s, ret -> %0#10x" % (class_name, origin_ret_address))
		
	# -- HEAD -- #
	start_prolog()
	
	# -- BODY -- #
	
	origin_method_lists = []
	for idx in range(len(mirror_class_ptrs)):
		class_ptr = mirror_class_ptrs[idx]
		origin_method_list = resolve_mirror_Class(class_ptr)
		origin_method_lists.append(origin_method_list)
	
	force_initializing(origin_class_ptr, mirror_class_ptrs, mirror_class_names)
	
	suspicious_method_lists = []
	for idx in range(len(mirror_class_ptrs)):
		class_ptr = mirror_class_ptrs[idx]
		suspicious_method_list = resolve_mirror_Class(class_ptr)
		suspicious_method_lists.append(suspicious_method_list)
	
	for idx in range(len(mirror_class_ptrs)):
		origin_method_list = origin_method_lists[idx]
		suspicious_method_list = suspicious_method_lists[idx]
		dump_modified_method(origin_method_list, suspicious_method_list)
	
	# -- TAIL -- #
	end_prolog_done()
	
	# continue the execution of the target application
	execution_state.getExecutionService().resume()
	cleanup()
	return