Skip to content

__read_args_v 方法 在 arm64 下对 可变参数列表 的读取有误 #60

Open
@newdive

Description

@newdive
  • bug的复现
    运行 example_uzm.zip 中的 example_uzm_test.py 脚本
    报错如下
File "D:\workspace\programming\python\remote\ExAndroidNativeEmu\androidemu\java\jni_env.py", line 932, in call_object_method_v
    return self.__call_xxx_method(mu, env, obj_idx, method_id, args, 1)
  File "D:\workspace\programming\python\remote\ExAndroidNativeEmu\androidemu\java\jni_env.py", line 907, in __call_xxx_method
    constructor_args = self.__read_args_common(mu, args, method.args_list, args_type)
  File "D:\workspace\programming\python\remote\ExAndroidNativeEmu\androidemu\java\jni_env.py", line 494, in __read_args_common
    return self.__read_args_v(mu, args_ptr, args_type_list)
  File "D:\workspace\programming\python\remote\ExAndroidNativeEmu\androidemu\java\jni_env.py", line 471, in __read_args_v64
    jobj = self.get_reference(ref)
  File "D:\workspace\programming\python\remote\ExAndroidNativeEmu\androidemu\java\jni_env.py", line 289, in get_reference
    raise RuntimeError('Invalid get_reference(%d)' % idx)
RuntimeError: Invalid get_reference(269473136)
  • 原因分析

    脚本对应的 so 文件通过 art中的 InvokeVirtualOrInterfaceWithVarArgs 实现调用 java层 PackageManagergetPackageInfo 方法
    分析 InvokeVirtualOrInterfaceWithVarArgs 方法的源码可知对不定参数的读取是通过 va_arg 来实现的。
    当然默认会使用”栈读取“的方式,这个在 __read_args_v 中已经实现
    但根据文档 IHI0055B_aapcs64.pdf 中对 va_arg 的说明,当 ap.__gr_offs 为负数的时候读取参数是另外的一套逻辑

  • 解决方法

    目前我只是根据 文档 IHI0055B_aapcs64.pdf 中的说明对 __read_args_v64 方法做了如下修改

def __read_args_v64(self, mu, args_ptr, args_type_list):
    ...
    va_ap= int.from_bytes(mu.mem_read(args_ptr+0x8, 8), byteorder='little')
    va_off = int.from_bytes(mu.mem_read(args_ptr+0x18, 4), byteorder='little', signed=True)
    arg_off_acc = 0
    for arg_name in args_type_list:
        if va_off + arg_off_acc < 0:
            v = int.from_bytes(mu.mem_read(va_ap+ va_off + arg_off_acc, ptr_size), byteorder='little')
        else:
            v = int.from_bytes(mu.mem_read(args_ptr + arg_off_acc, ptr_size), byteorder='little')
        ...
        arg_off_acc += ptr_size
    #
    return result

以上改动针对本例可以测试通过,
但根据文档说明考虑到还有其它分支情况的处理且缺乏相应的测试样例,所以就没提交修改。

希望 @maiyao1988 大佬有空时可以了解并处理下这个问题

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions