Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

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

Open
newdive opened this issue Mar 17, 2022 · 1 comment
Open

Comments

@newdive
Copy link

newdive commented Mar 17, 2022

  • 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 大佬有空时可以了解并处理下这个问题

@maiyao1988
Copy link
Owner

ok,我先详细了解一下。

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants