diff --git a/tests/test_android.py b/tests/test_android.py index 04407433..1556bc02 100644 --- a/tests/test_android.py +++ b/tests/test_android.py @@ -3,7 +3,7 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # -import os, platform, sys, unittest +import platform, sys, unittest from collections import defaultdict sys.path.append("..") @@ -13,47 +13,69 @@ from qiling.os.posix import syscall class Fake_maps(QlFsMappedObject): - def __init__(self, ql): + def __init__(self, ql: Qiling): self.ql = ql + def read(self, size): - stack = next(filter(lambda x : x[3]=='[stack]', self.ql.mem.map_info)) - return ('%x-%x %s\n' % (stack[0], stack[1], stack[3])).encode() + return ''.join(f'{lbound:x}-{ubound:x} {perms}p {label}\n' for lbound, ubound, perms, label, _ in self.ql.mem.get_mapinfo()).encode() + def fstat(self): return defaultdict(int) + def close(self): return 0 -def my_syscall_close(ql, fd): - if fd in [0, 1, 2]: + +def my_syscall_close(ql: Qiling, fd: int) -> int: + if fd in (0, 1, 2): return 0 + return syscall.ql_syscall_close(ql, fd) +# addresses specified on non-fixed mmap calls are used as hints, where the allocated +# address can never be less than the value set for mmap_address. nevertheless, android +# uses a non-fixed mmap call to map "/system/framework/arm64/boot.art" at 0x70000000 +# and fails if mmap allocates it elsewhere. +# +# this override sets a lower value for mmap_address to allow android map the file using +# a non-fixed mmap call to exactly where it wants it to be. +OVERRIDES = {'mmap_address': 0x68000000} + + class TestAndroid(unittest.TestCase): @unittest.skipUnless(platform.system() == 'Linux', 'run only on Linux') def test_android_arm64(self): - test_binary = "../examples/rootfs/arm64_android6.0/bin/arm64_android_jniart" rootfs = "../examples/rootfs/arm64_android6.0" - env = {"ANDROID_DATA":"/data", "ANDROID_ROOT":"/system"} + env = { + 'ANDROID_DATA': r'/data', + 'ANDROID_ROOT': r'/system' + } + + ql = Qiling([test_binary], rootfs, env, profile={'OS64': OVERRIDES}, multithread=True) - ql = Qiling([test_binary], rootfs, env, multithread=True) ql.os.set_syscall("close", my_syscall_close) ql.add_fs_mapper("/proc/self/task/2000/maps", Fake_maps(ql)) ql.run() - del ql + del ql @unittest.skipUnless(platform.system() == 'Linux', 'run only on Linux') def test_android_arm(self): test_binary = "../examples/rootfs/arm64_android6.0/bin/arm_android_jniart" rootfs = "../examples/rootfs/arm64_android6.0" - env = {"ANDROID_DATA":"/data", "ANDROID_ROOT":"/system"} + env = { + 'ANDROID_DATA': r'/data', + 'ANDROID_ROOT': r'/system' + } + + ql = Qiling([test_binary], rootfs, env, profile={'OS32': OVERRIDES}, multithread=True) - ql = Qiling([test_binary], rootfs, env, multithread=True) ql.os.set_syscall("close", my_syscall_close) ql.add_fs_mapper("/proc/self/task/2000/maps", Fake_maps(ql)) ql.run() + del ql