From ab921b26c9b14b67a538d42bd02deef2f895de51 Mon Sep 17 00:00:00 2001 From: tiann Date: Thu, 9 Jul 2020 15:49:06 +0800 Subject: [PATCH 01/11] 64bit makefile Signed-off-by: tiann --- VirtualApp/lib/build.gradle | 3 ++- VirtualApp/lib/src/main/jni/Application.mk | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/VirtualApp/lib/build.gradle b/VirtualApp/lib/build.gradle index 7ae6f7af1..21cbea709 100644 --- a/VirtualApp/lib/build.gradle +++ b/VirtualApp/lib/build.gradle @@ -11,7 +11,8 @@ android { versionName "1.0" externalNativeBuild { ndkBuild { - abiFilters "armeabi-v7a", "x86" + // abiFilters "armeabi-v7a", "x86" + abiFilters "arm64-v8a", "x86_64" } } } diff --git a/VirtualApp/lib/src/main/jni/Application.mk b/VirtualApp/lib/src/main/jni/Application.mk index 453fd7738..dff2fdeac 100644 --- a/VirtualApp/lib/src/main/jni/Application.mk +++ b/VirtualApp/lib/src/main/jni/Application.mk @@ -1,4 +1,4 @@ -APP_ABI := x86 armeabi-v7a +APP_ABI := x86_64 arm64-v8a APP_PLATFORM := android-14 APP_STL := c++_static APP_OPTIM := release From 76b5cdb9ff73458a14a38c589a0e37876a8375d9 Mon Sep 17 00:00:00 2001 From: tiann Date: Thu, 9 Jul 2020 15:51:25 +0800 Subject: [PATCH 02/11] Remove faccessat Signed-off-by: tiann --- VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp index 6f4e1b421..2275cb24e 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp @@ -108,15 +108,6 @@ __BEGIN_DECLS #define FREE(ptr, org_ptr) { if ((void*) ptr != NULL && (void*) ptr != (void*) org_ptr) { free((void*) ptr); } } -// int faccessat(int dirfd, const char *pathname, int mode, int flags); -HOOK_DEF(int, faccessat, int dirfd, const char *pathname, int mode, int flags) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_faccessat, dirfd, redirect_path, mode, flags); - FREE(redirect_path, pathname); - return ret; -} - // int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags); HOOK_DEF(int, fchmodat, int dirfd, const char *pathname, mode_t mode, int flags) { @@ -731,7 +722,6 @@ void IOUniformer::startUniformer(const char *so_path, int api_level, int preview void *handle = dlopen("libc.so", RTLD_NOW); if (handle) { - HOOK_SYMBOL(handle, faccessat); HOOK_SYMBOL(handle, __openat); HOOK_SYMBOL(handle, fchmodat); HOOK_SYMBOL(handle, fchownat); From 394aa6700fd2d3d92b2ae2f140a5891943fe24f9 Mon Sep 17 00:00:00 2001 From: tiann Date: Thu, 9 Jul 2020 15:52:03 +0800 Subject: [PATCH 03/11] Remove __openat Signed-off-by: tiann --- .../src/main/jni/Foundation/IOUniformer.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp index 2275cb24e..288401c88 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp @@ -454,23 +454,6 @@ HOOK_DEF(int, __getcwd, char *buf, size_t size) { } -// int __openat(int fd, const char *pathname, int flags, int mode); -HOOK_DEF(int, __openat, int fd, const char *pathname, int flags, int mode) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_openat, fd, redirect_path, flags, mode); - FREE(redirect_path, pathname); - return ret; -} -// int __open(const char *pathname, int flags, int mode); -HOOK_DEF(int, __open, const char *pathname, int flags, int mode) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_open, redirect_path, flags, mode); - FREE(redirect_path, pathname); - return ret; -} - // int __statfs (__const char *__file, struct statfs *__buf); HOOK_DEF(int, __statfs, __const char *__file, struct statfs *__buf) { int res; @@ -722,7 +705,6 @@ void IOUniformer::startUniformer(const char *so_path, int api_level, int preview void *handle = dlopen("libc.so", RTLD_NOW); if (handle) { - HOOK_SYMBOL(handle, __openat); HOOK_SYMBOL(handle, fchmodat); HOOK_SYMBOL(handle, fchownat); HOOK_SYMBOL(handle, renameat); From f8b737f522ed187ee262f2164f3e0821705088fc Mon Sep 17 00:00:00 2001 From: tiann Date: Thu, 9 Jul 2020 15:53:32 +0800 Subject: [PATCH 04/11] Remove fchmodat Signed-off-by: tiann --- VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp index 288401c88..cdb68ba84 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp @@ -109,14 +109,6 @@ __BEGIN_DECLS #define FREE(ptr, org_ptr) { if ((void*) ptr != NULL && (void*) ptr != (void*) org_ptr) { free((void*) ptr); } } -// int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags); -HOOK_DEF(int, fchmodat, int dirfd, const char *pathname, mode_t mode, int flags) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_fchmodat, dirfd, redirect_path, mode, flags); - FREE(redirect_path, pathname); - return ret; -} // int fchmod(const char *pathname, mode_t mode); HOOK_DEF(int, fchmod, const char *pathname, mode_t mode) { int res; @@ -705,7 +697,6 @@ void IOUniformer::startUniformer(const char *so_path, int api_level, int preview void *handle = dlopen("libc.so", RTLD_NOW); if (handle) { - HOOK_SYMBOL(handle, fchmodat); HOOK_SYMBOL(handle, fchownat); HOOK_SYMBOL(handle, renameat); HOOK_SYMBOL(handle, fstatat64); From 9f1b3ac5c73f39855022fe7d92f76dc82ee830ee Mon Sep 17 00:00:00 2001 From: tiann Date: Thu, 9 Jul 2020 16:13:47 +0800 Subject: [PATCH 05/11] Fix compile error Signed-off-by: tiann --- .../src/main/jni/Foundation/IOUniformer.cpp | 249 ++---------------- .../src/main/jni/Substrate/SubstrateHook.cpp | 2 + 2 files changed, 20 insertions(+), 231 deletions(-) diff --git a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp index cdb68ba84..69c4e2458 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp @@ -4,7 +4,11 @@ #include #include #include + +#ifdef __LP64__ +#else #include +#endif //extern "C" { //#include @@ -69,6 +73,14 @@ void IOUniformer::init_env_before_all() { } } +static inline void +hook_function(void *addr, void *new_func, void **old_func) { +#ifdef __LP64__ +#else + MSHookFunction(addr, new_func, old_func); +#endif + +} static inline void hook_function(void *handle, const char *symbol, void *new_func, void **old_func) { @@ -76,7 +88,7 @@ hook_function(void *handle, const char *symbol, void *new_func, void **old_func) if (addr == NULL) { return; } - MSHookFunction(addr, new_func, old_func); + hook_function(addr, new_func, old_func); } @@ -109,40 +121,12 @@ __BEGIN_DECLS #define FREE(ptr, org_ptr) { if ((void*) ptr != NULL && (void*) ptr != (void*) org_ptr) { free((void*) ptr); } } -// int fchmod(const char *pathname, mode_t mode); -HOOK_DEF(int, fchmod, const char *pathname, mode_t mode) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_chmod, redirect_path, mode); - FREE(redirect_path, pathname); - return ret; -} - - -// int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags); -HOOK_DEF(int, fstatat, int dirfd, const char *pathname, struct stat *buf, int flags) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_fstatat64, dirfd, redirect_path, buf, flags); - FREE(redirect_path, pathname); - return ret; -} // int fstatat64(int dirfd, const char *pathname, struct stat *buf, int flags); HOOK_DEF(int, fstatat64, int dirfd, const char *pathname, struct stat *buf, int flags) { int res; const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_fstatat64, dirfd, redirect_path, buf, flags); - FREE(redirect_path, pathname); - return ret; -} - - -// int fstat(const char *pathname, struct stat *buf, int flags); -HOOK_DEF(int, fstat, const char *pathname, struct stat *buf) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_fstat64, redirect_path, buf); + int ret = syscall(__NR_newfstatat, dirfd, redirect_path, buf, flags); FREE(redirect_path, pathname); return ret; } @@ -156,14 +140,6 @@ HOOK_DEF(int, mknodat, int dirfd, const char *pathname, mode_t mode, dev_t dev) FREE(redirect_path, pathname); return ret; } -// int mknod(const char *pathname, mode_t mode, dev_t dev); -HOOK_DEF(int, mknod, const char *pathname, mode_t mode, dev_t dev) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_mknod, redirect_path, mode, dev); - FREE(redirect_path, pathname); - return ret; -} // int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags); @@ -207,17 +183,6 @@ HOOK_DEF(int, renameat, int olddirfd, const char *oldpath, int newdirfd, const c FREE(redirect_path_new, newpath); return ret; } -// int rename(const char *oldpath, const char *newpath); -HOOK_DEF(int, rename, const char *oldpath, const char *newpath) { - int res_old; - int res_new; - const char *redirect_path_old = relocate_path(oldpath, &res_old); - const char *redirect_path_new = relocate_path(newpath, &res_new); - int ret = syscall(__NR_rename, redirect_path_old, redirect_path_new); - FREE(redirect_path_old, oldpath); - FREE(redirect_path_new, newpath); - return ret; -} // int unlinkat(int dirfd, const char *pathname, int flags); @@ -228,14 +193,6 @@ HOOK_DEF(int, unlinkat, int dirfd, const char *pathname, int flags) { FREE(redirect_path, pathname); return ret; } -// int unlink(const char *pathname); -HOOK_DEF(int, unlink, const char *pathname) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_unlink, redirect_path); - FREE(redirect_path, pathname); - return ret; -} // int symlinkat(const char *oldpath, int newdirfd, const char *newpath); @@ -249,18 +206,6 @@ HOOK_DEF(int, symlinkat, const char *oldpath, int newdirfd, const char *newpath) FREE(redirect_path_new, newpath); return ret; } -// int symlink(const char *oldpath, const char *newpath); -HOOK_DEF(int, symlink, const char *oldpath, const char *newpath) { - int res_old; - int res_new; - const char *redirect_path_old = relocate_path(oldpath, &res_old); - const char *redirect_path_new = relocate_path(newpath, &res_new); - int ret = syscall(__NR_symlink, redirect_path_old, redirect_path_new); - FREE(redirect_path_old, oldpath); - FREE(redirect_path_new, newpath); - return ret; -} - // int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags); HOOK_DEF(int, linkat, int olddirfd, const char *oldpath, int newdirfd, const char *newpath, @@ -274,77 +219,6 @@ HOOK_DEF(int, linkat, int olddirfd, const char *oldpath, int newdirfd, const cha FREE(redirect_path_new, newpath); return ret; } -// int link(const char *oldpath, const char *newpath); -HOOK_DEF(int, link, const char *oldpath, const char *newpath) { - int res_old; - int res_new; - const char *redirect_path_old = relocate_path(oldpath, &res_old); - const char *redirect_path_new = relocate_path(newpath, &res_new); - int ret = syscall(__NR_link, redirect_path_old, redirect_path_new); - FREE(redirect_path_old, oldpath); - FREE(redirect_path_new, newpath); - return ret; -} - - -// int utimes(const char *filename, const struct timeval *tvp); -HOOK_DEF(int, utimes, const char *pathname, const struct timeval *tvp) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_utimes, redirect_path, tvp); - FREE(redirect_path, pathname); - return ret; -} - - -// int access(const char *pathname, int mode); -HOOK_DEF(int, access, const char *pathname, int mode) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_access, redirect_path, mode); - FREE(redirect_path, pathname); - return ret; -} - - -// int chmod(const char *path, mode_t mode); -HOOK_DEF(int, chmod, const char *pathname, mode_t mode) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_chmod, redirect_path, mode); - FREE(redirect_path, pathname); - return ret; -} - - -// int chown(const char *path, uid_t owner, gid_t group); -HOOK_DEF(int, chown, const char *pathname, uid_t owner, gid_t group) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_chown, redirect_path, owner, group); - FREE(redirect_path, pathname); - return ret; -} - - -// int lstat(const char *path, struct stat *buf); -HOOK_DEF(int, lstat, const char *pathname, struct stat *buf) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_lstat64, redirect_path, buf); - FREE(redirect_path, pathname); - return ret; -} - - -// int stat(const char *path, struct stat *buf); -HOOK_DEF(int, stat, const char *pathname, struct stat *buf) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_stat64, redirect_path, buf); - FREE(redirect_path, pathname); - return ret; -} // int mkdirat(int dirfd, const char *pathname, mode_t mode); @@ -355,24 +229,6 @@ HOOK_DEF(int, mkdirat, int dirfd, const char *pathname, mode_t mode) { FREE(redirect_path, pathname); return ret; } -// int mkdir(const char *pathname, mode_t mode); -HOOK_DEF(int, mkdir, const char *pathname, mode_t mode) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_mkdir, redirect_path, mode); - FREE(redirect_path, pathname); - return ret; -} - - -// int rmdir(const char *pathname); -HOOK_DEF(int, rmdir, const char *pathname) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_rmdir, redirect_path); - FREE(redirect_path, pathname); - return ret; -} // int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); @@ -383,25 +239,6 @@ HOOK_DEF(int, readlinkat, int dirfd, const char *pathname, char *buf, size_t buf FREE(redirect_path, pathname); return ret; } -// ssize_t readlink(const char *path, char *buf, size_t bufsiz); -HOOK_DEF(ssize_t, readlink, const char *pathname, char *buf, size_t bufsiz) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - ssize_t ret = syscall(__NR_readlink, redirect_path, buf, bufsiz); - FREE(redirect_path, pathname); - return ret; -} - - -// int __statfs64(const char *path, size_t size, struct statfs *stat); -HOOK_DEF(int, __statfs64, const char *pathname, size_t size, struct statfs *stat) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_statfs64, redirect_path, size, stat); - FREE(redirect_path, pathname); - return ret; -} - // int truncate(const char *path, off_t length); HOOK_DEF(int, truncate, const char *pathname, off_t length) { @@ -414,16 +251,6 @@ HOOK_DEF(int, truncate, const char *pathname, off_t length) { #define RETURN_IF_FORBID if(res == FORBID) return -1; -// int truncate64(const char *pathname, off_t length); -HOOK_DEF(int, truncate64, const char *pathname, off_t length) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - RETURN_IF_FORBID - int ret = syscall(__NR_truncate64, redirect_path, length); - FREE(redirect_path, pathname); - return ret; -} - // int chdir(const char *path); HOOK_DEF(int, chdir, const char *pathname) { @@ -436,16 +263,6 @@ HOOK_DEF(int, chdir, const char *pathname) { } -// int __getcwd(char *buf, size_t size); -HOOK_DEF(int, __getcwd, char *buf, size_t size) { - int ret = syscall(__NR_getcwd, buf, size); - if (!ret) { - - } - return ret; -} - - // int __statfs (__const char *__file, struct statfs *__buf); HOOK_DEF(int, __statfs, __const char *__file, struct statfs *__buf) { int res; @@ -455,15 +272,6 @@ HOOK_DEF(int, __statfs, __const char *__file, struct statfs *__buf) { return ret; } -// int lchown(const char *pathname, uid_t owner, gid_t group); -HOOK_DEF(int, lchown, const char *pathname, uid_t owner, gid_t group) { - int res; - const char *redirect_path = relocate_path(pathname, &res); - int ret = syscall(__NR_lchown, redirect_path, owner, group); - FREE(redirect_path, pathname); - return ret; -} - int inline getArrayItemCount(char *const array[]) { int i; for (i = 0; array[i]; ++i); @@ -663,25 +471,25 @@ void hook_dlopen(int api_level) { if (api_level > 25) { if (findSymbol("__dl__Z9do_dlopenPKciPK17android_dlextinfoPKv", "linker", (unsigned long *) &symbol) == 0) { - MSHookFunction(symbol, (void *) new_do_dlopen_V24, + hook_function(symbol, (void *) new_do_dlopen_V24, (void **) &orig_do_dlopen_V24); } } else if (api_level > 23) { if (findSymbol("__dl__Z9do_dlopenPKciPK17android_dlextinfoPv", "linker", (unsigned long *) &symbol) == 0) { - MSHookFunction(symbol, (void *) new_do_dlopen_V24, + hook_function(symbol, (void *) new_do_dlopen_V24, (void **) &orig_do_dlopen_V24); } } else if (api_level >= 19) { if (findSymbol("__dl__Z9do_dlopenPKciPK17android_dlextinfo", "linker", (unsigned long *) &symbol) == 0) { - MSHookFunction(symbol, (void *) new_do_dlopen_V19, + hook_function(symbol, (void *) new_do_dlopen_V19, (void **) &orig_do_dlopen_V19); } } else { if (findSymbol("__dl_dlopen", "linker", (unsigned long *) &symbol) == 0) { - MSHookFunction(symbol, (void *) new_dlopen, (void **) &orig_dlopen); + hook_function(symbol, (void *) new_dlopen, (void **) &orig_dlopen); } } } @@ -701,7 +509,6 @@ void IOUniformer::startUniformer(const char *so_path, int api_level, int preview HOOK_SYMBOL(handle, renameat); HOOK_SYMBOL(handle, fstatat64); HOOK_SYMBOL(handle, __statfs); - HOOK_SYMBOL(handle, __statfs64); HOOK_SYMBOL(handle, mkdirat); HOOK_SYMBOL(handle, mknodat); HOOK_SYMBOL(handle, truncate); @@ -710,29 +517,9 @@ void IOUniformer::startUniformer(const char *so_path, int api_level, int preview HOOK_SYMBOL(handle, unlinkat); HOOK_SYMBOL(handle, symlinkat); HOOK_SYMBOL(handle, utimensat); - HOOK_SYMBOL(handle, __getcwd); // HOOK_SYMBOL(handle, __getdents64); HOOK_SYMBOL(handle, chdir); HOOK_SYMBOL(handle, execve); - if (api_level <= 20) { - HOOK_SYMBOL(handle, access); - HOOK_SYMBOL(handle, __open); - HOOK_SYMBOL(handle, stat); - HOOK_SYMBOL(handle, lstat); - HOOK_SYMBOL(handle, fstatat); - HOOK_SYMBOL(handle, chmod); - HOOK_SYMBOL(handle, chown); - HOOK_SYMBOL(handle, rename); - HOOK_SYMBOL(handle, rmdir); - HOOK_SYMBOL(handle, mkdir); - HOOK_SYMBOL(handle, mknod); - HOOK_SYMBOL(handle, link); - HOOK_SYMBOL(handle, unlink); - HOOK_SYMBOL(handle, readlink); - HOOK_SYMBOL(handle, symlink); -// HOOK_SYMBOL(handle, getdents); -// HOOK_SYMBOL(handle, execv); - } dlclose(handle); } // hook_dlopen(api_level); diff --git a/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp b/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp index 8264375ff..35b7ae170 100755 --- a/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp +++ b/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp @@ -924,7 +924,9 @@ static void SubstrateHookFunction(SubstrateProcessRef process, void *symbol, voi #endif _extern void MSHookFunction(void *symbol, void *replace, void **result) { +#ifndef __LP64__ SubstrateHookFunction(NULL, symbol, replace, result); +#endif } #if defined(__APPLE__) && defined(__arm__) From a455358c6cf22e16e6070d3e0a4696a8124f70e4 Mon Sep 17 00:00:00 2001 From: tiann Date: Thu, 9 Jul 2020 16:53:29 +0800 Subject: [PATCH 06/11] ban 32bit app from selection list Signed-off-by: tiann --- VirtualApp/app/build.gradle | 2 +- .../java/io/virtualapp/home/adapters/CloneAppListAdapter.java | 1 + .../app/src/main/java/io/virtualapp/home/models/AppInfo.java | 1 + .../src/main/java/io/virtualapp/home/repo/AppRepository.java | 2 ++ VirtualApp/lib/build.gradle | 1 - .../lody/virtual/helper/compat/NativeLibraryHelperCompat.java | 3 +++ 6 files changed, 8 insertions(+), 2 deletions(-) diff --git a/VirtualApp/app/build.gradle b/VirtualApp/app/build.gradle index 849f6ef64..a90f69788 100644 --- a/VirtualApp/app/build.gradle +++ b/VirtualApp/app/build.gradle @@ -29,7 +29,7 @@ android { android { defaultConfig { ndk { - abiFilters "armeabi-v7a", "x86" + abiFilters "arm64-v8a", "x86_64" } } } diff --git a/VirtualApp/app/src/main/java/io/virtualapp/home/adapters/CloneAppListAdapter.java b/VirtualApp/app/src/main/java/io/virtualapp/home/adapters/CloneAppListAdapter.java index a527ad471..12ad55b2f 100644 --- a/VirtualApp/app/src/main/java/io/virtualapp/home/adapters/CloneAppListAdapter.java +++ b/VirtualApp/app/src/main/java/io/virtualapp/home/adapters/CloneAppListAdapter.java @@ -107,6 +107,7 @@ public void onBindViewHolder(ViewHolder holder, int position) { holder.itemView.setOnClickListener(v -> { mItemEventListener.onItemClick(info, position); }); + holder.itemView.setEnabled(info.is64bit); } @Override diff --git a/VirtualApp/app/src/main/java/io/virtualapp/home/models/AppInfo.java b/VirtualApp/app/src/main/java/io/virtualapp/home/models/AppInfo.java index 65bffbe2b..5c9b16477 100644 --- a/VirtualApp/app/src/main/java/io/virtualapp/home/models/AppInfo.java +++ b/VirtualApp/app/src/main/java/io/virtualapp/home/models/AppInfo.java @@ -15,4 +15,5 @@ public class AppInfo { public CharSequence version; public int cloneCount; public boolean disableMultiVersion; + public boolean is64bit; } diff --git a/VirtualApp/app/src/main/java/io/virtualapp/home/repo/AppRepository.java b/VirtualApp/app/src/main/java/io/virtualapp/home/repo/AppRepository.java index 89063ca2e..1e86ddd53 100644 --- a/VirtualApp/app/src/main/java/io/virtualapp/home/repo/AppRepository.java +++ b/VirtualApp/app/src/main/java/io/virtualapp/home/repo/AppRepository.java @@ -8,6 +8,7 @@ import com.lody.virtual.GmsSupport; import com.lody.virtual.client.core.InstallStrategy; import com.lody.virtual.client.core.VirtualCore; +import com.lody.virtual.helper.compat.NativeLibraryHelperCompat; import com.lody.virtual.helper.utils.DeviceUtil; import com.lody.virtual.remote.InstallResult; import com.lody.virtual.remote.InstalledAppInfo; @@ -200,6 +201,7 @@ private List convertPackageInfoToAppData(Context context, List getABIsFromApk(String apk) { return null; } + public static boolean isApk64(String apk) { + return isVM64(getABIsFromApk(apk)); + } } From 7c1500187c602cf7840fda881523413702ee7a0e Mon Sep 17 00:00:00 2001 From: tiann Date: Thu, 9 Jul 2020 17:00:03 +0800 Subject: [PATCH 07/11] import [And64InlineHook](https://github.com/Rprop/And64InlineHook) Signed-off-by: tiann --- .../jni/A64Inlinehook/And64InlineHook.cpp | 571 ++++++++++++++++++ .../jni/A64Inlinehook/And64InlineHook.hpp | 45 ++ VirtualApp/lib/src/main/jni/Android.mk | 1 + .../src/main/jni/Foundation/IOUniformer.cpp | 3 + 4 files changed, 620 insertions(+) create mode 100755 VirtualApp/lib/src/main/jni/A64Inlinehook/And64InlineHook.cpp create mode 100755 VirtualApp/lib/src/main/jni/A64Inlinehook/And64InlineHook.hpp diff --git a/VirtualApp/lib/src/main/jni/A64Inlinehook/And64InlineHook.cpp b/VirtualApp/lib/src/main/jni/A64Inlinehook/And64InlineHook.cpp new file mode 100755 index 000000000..18058bb92 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/A64Inlinehook/And64InlineHook.cpp @@ -0,0 +1,571 @@ +/* + * @date : 2018/04/18 + * @author : Rprop (r_prop@outlook.com) + * https://github.com/Rprop/And64InlineHook + */ +/* + MIT License + + Copyright (c) 2018 Rprop (r_prop@outlook.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ +#define __STDC_FORMAT_MACROS + +#if defined(__aarch64__) + +#include +#include +#include +#include "And64InlineHook.hpp" +#define A64_MAX_INSTRUCTIONS 5 +#define A64_MAX_REFERENCES (A64_MAX_INSTRUCTIONS * 2) +#define A64_NOP 0xd503201fu +#define A64_JNIEXPORT __attribute__((visibility("default"))) +#define __flush_cache(c, n) __builtin___clear_cache(reinterpret_cast(c), reinterpret_cast(c) + n) + + +typedef uint32_t *__restrict *__restrict instruction; +typedef struct +{ + struct fix_info + { + uint32_t *bp; + uint32_t ls; // left-shift counts + uint32_t ad; // & operand + }; + struct insns_info + { + union + { + uint64_t insu; + int64_t ins; + void *insp; + }; + fix_info fmap[A64_MAX_REFERENCES]; + }; + int64_t basep; + int64_t endp; + insns_info dat[A64_MAX_INSTRUCTIONS]; + +public: + inline bool is_in_fixing_range(const int64_t absolute_addr) { + return absolute_addr >= this->basep && absolute_addr < this->endp; + } + inline intptr_t get_ref_ins_index(const int64_t absolute_addr) { + return static_cast((absolute_addr - this->basep) / sizeof(uint32_t)); + } + inline intptr_t get_and_set_current_index(uint32_t *__restrict inp, uint32_t *__restrict outp) { + intptr_t current_idx = this->get_ref_ins_index(reinterpret_cast(inp)); + this->dat[current_idx].insp = outp; + return current_idx; + } + inline void reset_current_ins(const intptr_t idx, uint32_t *__restrict outp) { + this->dat[idx].insp = outp; + } + void insert_fix_map(const intptr_t idx, uint32_t *bp, uint32_t ls = 0u, uint32_t ad = 0xffffffffu) { + for (auto &f : this->dat[idx].fmap) { + if (f.bp == NULL) { + f.bp = bp; + f.ls = ls; + f.ad = ad; + return; + } //if + } + // What? GGing.. + } + void process_fix_map(const intptr_t idx) { + for (auto &f : this->dat[idx].fmap) { + if (f.bp == NULL) break; + *(f.bp) = *(f.bp) | (((int32_t(this->dat[idx].ins - reinterpret_cast(f.bp)) >> 2) << f.ls) & f.ad); + f.bp = NULL; + } + } +} context; + +//------------------------------------------------------------------------- + +static bool __fix_branch_imm(instruction inpp, instruction outpp, context *ctxp) +{ + static constexpr uint32_t mbits = 6u; + static constexpr uint32_t mask = 0xfc000000u; // 0b11111100000000000000000000000000 + static constexpr uint32_t rmask = 0x03ffffffu; // 0b00000011111111111111111111111111 + static constexpr uint32_t op_b = 0x14000000u; // "b" ADDR_PCREL26 + static constexpr uint32_t op_bl = 0x94000000u; // "bl" ADDR_PCREL26 + + const uint32_t ins = *(*inpp); + const uint32_t opc = ins & mask; + switch (opc) { + case op_b: + case op_bl: + { + intptr_t current_idx = ctxp->get_and_set_current_index(*inpp, *outpp); + int64_t absolute_addr = reinterpret_cast(*inpp) + (static_cast(ins << mbits) >> (mbits - 2u)); // sign-extended + int64_t new_pc_offset = static_cast(absolute_addr - reinterpret_cast(*outpp)) >> 2; // shifted + bool special_fix_type = ctxp->is_in_fixing_range(absolute_addr); + // whether the branch should be converted to absolute jump + if (!special_fix_type && llabs(new_pc_offset) >= (rmask >> 1)) { + bool b_aligned = (reinterpret_cast(*outpp + 2) & 7u) == 0u; + if (opc == op_b) { + if (b_aligned != true) { + (*outpp)[0] = A64_NOP; + ctxp->reset_current_ins(current_idx, ++(*outpp)); + } //if + (*outpp)[0] = 0x58000051u; // LDR X17, #0x8 + (*outpp)[1] = 0xd61f0220u; // BR X17 + memcpy(*outpp + 2, &absolute_addr, sizeof(absolute_addr)); + *outpp += 4; + } else { + if (b_aligned == true) { + (*outpp)[0] = A64_NOP; + ctxp->reset_current_ins(current_idx, ++(*outpp)); + } //if + (*outpp)[0] = 0x58000071u; // LDR X17, #12 + (*outpp)[1] = 0x1000009eu; // ADR X30, #16 + (*outpp)[2] = 0xd61f0220u; // BR X17 + memcpy(*outpp + 3, &absolute_addr, sizeof(absolute_addr)); + *outpp += 5; + } //if + } else { + if (special_fix_type) { + intptr_t ref_idx = ctxp->get_ref_ins_index(absolute_addr); + if (ref_idx <= current_idx) { + new_pc_offset = static_cast(ctxp->dat[ref_idx].ins - reinterpret_cast(*outpp)) >> 2; + } else { + ctxp->insert_fix_map(ref_idx, *outpp, 0u, rmask); + new_pc_offset = 0; + } //if + } //if + + (*outpp)[0] = opc | (new_pc_offset & ~mask); + ++(*outpp); + } //if + + ++(*inpp); + return ctxp->process_fix_map(current_idx), true; + } + } + return false; +} + +//------------------------------------------------------------------------- + +static bool __fix_cond_comp_test_branch(instruction inpp, instruction outpp, context *ctxp) +{ + static constexpr uint32_t lsb = 5u; + static constexpr uint32_t lmask01 = 0xff00001fu; // 0b11111111000000000000000000011111 + static constexpr uint32_t mask0 = 0xff000010u; // 0b11111111000000000000000000010000 + static constexpr uint32_t op_bc = 0x54000000u; // "b.c" ADDR_PCREL19 + static constexpr uint32_t mask1 = 0x7f000000u; // 0b01111111000000000000000000000000 + static constexpr uint32_t op_cbz = 0x34000000u; // "cbz" Rt, ADDR_PCREL19 + static constexpr uint32_t op_cbnz = 0x35000000u; // "cbnz" Rt, ADDR_PCREL19 + static constexpr uint32_t lmask2 = 0xfff8001fu; // 0b11111111111110000000000000011111 + static constexpr uint32_t mask2 = 0x7f000000u; // 0b01111111000000000000000000000000 + static constexpr uint32_t op_tbz = 0x36000000u; // 0b00110110000000000000000000000000 "tbz" Rt, BIT_NUM, ADDR_PCREL14 + static constexpr uint32_t op_tbnz = 0x37000000u; // 0b00110111000000000000000000000000 "tbnz" Rt, BIT_NUM, ADDR_PCREL14 + + const uint32_t ins = *(*inpp); + uint32_t lmask = lmask01; + if ((ins & mask0) != op_bc) { + uint32_t opc = ins & mask1; + if (opc != op_cbz && opc != op_cbnz) { + opc = ins & mask2; + if (opc != op_tbz && opc != op_tbnz) { + return false; + } //if + lmask = lmask2; + } //if + } //if + + intptr_t current_idx = ctxp->get_and_set_current_index(*inpp, *outpp); + int64_t absolute_addr = reinterpret_cast(*inpp) + ((ins & ~lmask) >> (lsb - 2u)); + int64_t new_pc_offset = static_cast(absolute_addr - reinterpret_cast(*outpp)) >> 2; // shifted + bool special_fix_type = ctxp->is_in_fixing_range(absolute_addr); + if (!special_fix_type && llabs(new_pc_offset) >= (~lmask >> (lsb + 1))) { + if ((reinterpret_cast(*outpp + 4) & 7u) != 0u) { + (*outpp)[0] = A64_NOP; + ctxp->reset_current_ins(current_idx, ++(*outpp)); + } //if + (*outpp)[0] = (((8u >> 2u) << lsb) & ~lmask) | (ins & lmask); // B.C #0x8 + (*outpp)[1] = 0x14000005u; // B #0x14 + (*outpp)[2] = 0x58000051u; // LDR X17, #0x8 + (*outpp)[3] = 0xd61f0220u; // BR X17 + memcpy(*outpp + 4, &absolute_addr, sizeof(absolute_addr)); + *outpp += 6; + } else { + if (special_fix_type) { + intptr_t ref_idx = ctxp->get_ref_ins_index(absolute_addr); + if (ref_idx <= current_idx) { + new_pc_offset = static_cast(ctxp->dat[ref_idx].ins - reinterpret_cast(*outpp)) >> 2; + } else { + ctxp->insert_fix_map(ref_idx, *outpp, lsb, ~lmask); + new_pc_offset = 0; + } //if + } //if + + (*outpp)[0] = (static_cast(new_pc_offset << lsb) & ~lmask) | (ins & lmask); + ++(*outpp); + } //if + + ++(*inpp); + return ctxp->process_fix_map(current_idx), true; +} + +//------------------------------------------------------------------------- + +static bool __fix_loadlit(instruction inpp, instruction outpp, context *ctxp) +{ + const uint32_t ins = *(*inpp); + + // memory prefetch("prfm"), just skip it + // http://infocenter.arm.com/help/topic/com.arm.doc.100069_0608_00_en/pge1427897420050.html + if ((ins & 0xff000000u) == 0xd8000000u) { + ctxp->process_fix_map(ctxp->get_and_set_current_index(*inpp, *outpp)); + ++(*inpp); + return true; + } //if + + static constexpr uint32_t msb = 8u; + static constexpr uint32_t lsb = 5u; + static constexpr uint32_t mask_30 = 0x40000000u; // 0b01000000000000000000000000000000 + static constexpr uint32_t mask_31 = 0x80000000u; // 0b10000000000000000000000000000000 + static constexpr uint32_t lmask = 0xff00001fu; // 0b11111111000000000000000000011111 + static constexpr uint32_t mask_ldr = 0xbf000000u; // 0b10111111000000000000000000000000 + static constexpr uint32_t op_ldr = 0x18000000u; // 0b00011000000000000000000000000000 "LDR Wt/Xt, label" | ADDR_PCREL19 + static constexpr uint32_t mask_ldrv = 0x3f000000u; // 0b00111111000000000000000000000000 + static constexpr uint32_t op_ldrv = 0x1c000000u; // 0b00011100000000000000000000000000 "LDR St/Dt/Qt, label" | ADDR_PCREL19 + static constexpr uint32_t mask_ldrsw = 0xff000000u; // 0b11111111000000000000000000000000 + static constexpr uint32_t op_ldrsw = 0x98000000u; // "LDRSW Xt, label" | ADDR_PCREL19 | load register signed word + // LDR S0, #0 | 0b00011100000000000000000000000000 | 32-bit + // LDR D0, #0 | 0b01011100000000000000000000000000 | 64-bit + // LDR Q0, #0 | 0b10011100000000000000000000000000 | 128-bit + // INVALID | 0b11011100000000000000000000000000 | may be 256-bit + + uint32_t mask = mask_ldr; + uintptr_t faligned = (ins & mask_30) ? 7u : 3u; + if ((ins & mask_ldr) != op_ldr) { + mask = mask_ldrv; + if (faligned != 7u) + faligned = (ins & mask_31) ? 15u : 3u; + if ((ins & mask_ldrv) != op_ldrv) { + if ((ins & mask_ldrsw) != op_ldrsw) { + return false; + } //if + mask = mask_ldrsw; + faligned = 7u; + } //if + } //if + + intptr_t current_idx = ctxp->get_and_set_current_index(*inpp, *outpp); + int64_t absolute_addr = reinterpret_cast(*inpp) + ((static_cast(ins << msb) >> (msb + lsb - 2u)) & ~3u); + int64_t new_pc_offset = static_cast(absolute_addr - reinterpret_cast(*outpp)) >> 2; // shifted + bool special_fix_type = ctxp->is_in_fixing_range(absolute_addr); + // special_fix_type may encounter issue when there are mixed data and code + if (special_fix_type || (llabs(new_pc_offset) + (faligned + 1u - 4u) / 4u) >= (~lmask >> (lsb + 1))) { // inaccurate, but it works + while ((reinterpret_cast(*outpp + 2) & faligned) != 0u) { + *(*outpp)++ = A64_NOP; + } + ctxp->reset_current_ins(current_idx, *outpp); + + // Note that if memory at absolute_addr is writeable (non-const), we will fail to fetch it. + // And what's worse, we may unexpectedly overwrite something if special_fix_type is true... + uint32_t ns = static_cast((faligned + 1) / sizeof(uint32_t)); + (*outpp)[0] = (((8u >> 2u) << lsb) & ~mask) | (ins & lmask); // LDR #0x8 + (*outpp)[1] = 0x14000001u + ns; // B #0xc + memcpy(*outpp + 2, reinterpret_cast(absolute_addr), faligned + 1); + *outpp += 2 + ns; + } else { + faligned >>= 2; // new_pc_offset is shifted and 4-byte aligned + while ((new_pc_offset & faligned) != 0) { + *(*outpp)++ = A64_NOP; + new_pc_offset = static_cast(absolute_addr - reinterpret_cast(*outpp)) >> 2; + } + ctxp->reset_current_ins(current_idx, *outpp); + + (*outpp)[0] = (static_cast(new_pc_offset << lsb) & ~mask) | (ins & lmask); + ++(*outpp); + } //if + + ++(*inpp); + return ctxp->process_fix_map(current_idx), true; +} + +//------------------------------------------------------------------------- + +static bool __fix_pcreladdr(instruction inpp, instruction outpp, context *ctxp) +{ + // Load a PC-relative address into a register + // http://infocenter.arm.com/help/topic/com.arm.doc.100069_0608_00_en/pge1427897645644.html + static constexpr uint32_t msb = 8u; + static constexpr uint32_t lsb = 5u; + static constexpr uint32_t mask = 0x9f000000u; // 0b10011111000000000000000000000000 + static constexpr uint32_t rmask = 0x0000001fu; // 0b00000000000000000000000000011111 + static constexpr uint32_t lmask = 0xff00001fu; // 0b11111111000000000000000000011111 + static constexpr uint32_t fmask = 0x00ffffffu; // 0b00000000111111111111111111111111 + static constexpr uint32_t max_val = 0x001fffffu; // 0b00000000000111111111111111111111 + static constexpr uint32_t op_adr = 0x10000000u; // "adr" Rd, ADDR_PCREL21 + static constexpr uint32_t op_adrp = 0x90000000u; // "adrp" Rd, ADDR_ADRP + + const uint32_t ins = *(*inpp); + intptr_t current_idx; + switch (ins & mask) { + case op_adr: + { + current_idx = ctxp->get_and_set_current_index(*inpp, *outpp); + int64_t lsb_bytes = static_cast(ins << 1u) >> 30u; + int64_t absolute_addr = reinterpret_cast(*inpp) + (((static_cast(ins << msb) >> (msb + lsb - 2u)) & ~3u) | lsb_bytes); + int64_t new_pc_offset = static_cast(absolute_addr - reinterpret_cast(*outpp)); + bool special_fix_type = ctxp->is_in_fixing_range(absolute_addr); + if (!special_fix_type && llabs(new_pc_offset) >= (max_val >> 1)) { + if ((reinterpret_cast(*outpp + 2) & 7u) != 0u) { + (*outpp)[0] = A64_NOP; + ctxp->reset_current_ins(current_idx, ++(*outpp)); + } //if + + (*outpp)[0] = 0x58000000u | (((8u >> 2u) << lsb) & ~mask) | (ins & rmask); // LDR #0x8 + (*outpp)[1] = 0x14000003u; // B #0xc + memcpy(*outpp + 2, &absolute_addr, sizeof(absolute_addr)); + *outpp += 4; + } else { + if (special_fix_type) { + intptr_t ref_idx = ctxp->get_ref_ins_index(absolute_addr & ~3ull); + if (ref_idx <= current_idx) { + new_pc_offset = static_cast(ctxp->dat[ref_idx].ins - reinterpret_cast(*outpp)); + } else { + ctxp->insert_fix_map(ref_idx, *outpp, lsb, fmask); + new_pc_offset = 0; + } //if + } //if + + // the lsb_bytes will never be changed, so we can use lmask to keep it + (*outpp)[0] = (static_cast(new_pc_offset << (lsb - 2u)) & fmask) | (ins & lmask); + ++(*outpp); + } //if + } + break; + case op_adrp: + { + current_idx = ctxp->get_and_set_current_index(*inpp, *outpp); + int32_t lsb_bytes = static_cast(ins << 1u) >> 30u; + int64_t absolute_addr = (reinterpret_cast(*inpp) & ~0xfffll) + ((((static_cast(ins << msb) >> (msb + lsb - 2u)) & ~3u) | lsb_bytes) << 12); + if (ctxp->is_in_fixing_range(absolute_addr)) { + intptr_t ref_idx = ctxp->get_ref_ins_index(absolute_addr/* & ~3ull*/); + if (ref_idx > current_idx) { + // the bottom 12 bits of absolute_addr are masked out, + // so ref_idx must be less than or equal to current_idx! + } //if + + // *absolute_addr may be changed due to relocation fixing + *(*outpp)++ = ins; // 0x90000000u; + } else { + if ((reinterpret_cast(*outpp + 2) & 7u) != 0u) { + (*outpp)[0] = A64_NOP; + ctxp->reset_current_ins(current_idx, ++(*outpp)); + } //if + + (*outpp)[0] = 0x58000000u | (((8u >> 2u) << lsb) & ~mask) | (ins & rmask); // LDR #0x8 + (*outpp)[1] = 0x14000003u; // B #0xc + memcpy(*outpp + 2, &absolute_addr, sizeof(absolute_addr)); // potential overflow? + *outpp += 4; + } //if + } + break; + default: + return false; + } + + ctxp->process_fix_map(current_idx); + ++(*inpp); + return true; +} + +//------------------------------------------------------------------------- + +static void __fix_instructions(uint32_t *__restrict inp, int32_t count, uint32_t *__restrict outp) +{ + context ctx; + ctx.basep = reinterpret_cast(inp); + ctx.endp = reinterpret_cast(inp + count); + memset(ctx.dat, 0, sizeof(ctx.dat)); + static_assert(sizeof(ctx.dat) / sizeof(ctx.dat[0]) == A64_MAX_INSTRUCTIONS, + "please use A64_MAX_INSTRUCTIONS!"); +#ifndef NDEBUG + if (count > A64_MAX_INSTRUCTIONS) { + A64_LOGE("too many fixing instructions!"); + } //if +#endif // NDEBUG + + uint32_t *const outp_base = outp; + + while (--count >= 0) { + if (__fix_branch_imm(&inp, &outp, &ctx)) continue; + if (__fix_cond_comp_test_branch(&inp, &outp, &ctx)) continue; + if (__fix_loadlit(&inp, &outp, &ctx)) continue; + if (__fix_pcreladdr(&inp, &outp, &ctx)) continue; + + // without PC-relative offset + ctx.process_fix_map(ctx.get_and_set_current_index(inp, outp)); + *(outp++) = *(inp++); + } + + static constexpr uint_fast64_t mask = 0x03ffffffu; // 0b00000011111111111111111111111111 + auto callback = reinterpret_cast(inp); + auto pc_offset = static_cast(callback - reinterpret_cast(outp)) >> 2; + if (llabs(pc_offset) >= (mask >> 1)) { + if ((reinterpret_cast(outp + 2) & 7u) != 0u) { + outp[0] = A64_NOP; + ++outp; + } //if + outp[0] = 0x58000051u; // LDR X17, #0x8 + outp[1] = 0xd61f0220u; // BR X17 + *reinterpret_cast(outp + 2) = callback; + outp += 4; + } else { + outp[0] = 0x14000000u | (pc_offset & mask); // "B" ADDR_PCREL26 + ++outp; + } //if + + const uintptr_t total = (outp - outp_base) * sizeof(uint32_t); + __flush_cache(outp_base, total); // necessary +} + +//------------------------------------------------------------------------- + +extern "C" { +#define __attribute __attribute__ +#define aligned(x) __aligned__(x) +#define __intval(p) reinterpret_cast(p) +#define __uintval(p) reinterpret_cast(p) +#define __ptr(p) reinterpret_cast(p) +#define __page_size 4096 +#define __page_align(n) __align_up(static_cast(n), __page_size) +#define __ptr_align(x) __ptr(__align_down(reinterpret_cast(x), __page_size)) +#define __align_up(x, n) (((x) + ((n) - 1)) & ~((n) - 1)) +#define __align_down(x, n) ((x) & -(n)) +#define __countof(x) static_cast(sizeof(x) / sizeof((x)[0])) // must be signed +#define __atomic_increase(p) __sync_add_and_fetch(p, 1) +#define __sync_cmpswap(p, v, n) __sync_bool_compare_and_swap(p, v, n) +#define __predict_true(exp) __builtin_expect((exp) != 0, 1) +#define __make_rwx(p, n) ::mprotect(__ptr_align(p), \ + __page_align(__uintval(p) + n) != __page_align(__uintval(p)) ? __page_align(n) + __page_size : __page_align(n), \ + PROT_READ | PROT_WRITE | PROT_EXEC) + +//------------------------------------------------------------------------- + +static __attribute((aligned(__page_size))) uint32_t __insns_pool[A64_MAX_BACKUPS][A64_MAX_INSTRUCTIONS * 10]; + +//------------------------------------------------------------------------- + +class A64HookInit +{ +public: + A64HookInit() + { + __make_rwx(__insns_pool, sizeof(__insns_pool)); + } +}; +static A64HookInit __init; + +//------------------------------------------------------------------------- + +static uint32_t *FastAllocateTrampoline() +{ + static_assert((A64_MAX_INSTRUCTIONS * 10 * sizeof(uint32_t)) % 8 == 0, "8-byte align"); + static volatile int32_t __index = -1; + + int32_t i = __atomic_increase(&__index); + if (__predict_true(i >= 0 && i < __countof(__insns_pool))) { + return __insns_pool[i]; + } //if + + return NULL; +} + +//------------------------------------------------------------------------- + +A64_JNIEXPORT void *A64HookFunctionV(void *const symbol, void *const replace, + void *const rwx, const uintptr_t rwx_size) +{ + static constexpr uint_fast64_t mask = 0x03ffffffu; // 0b00000011111111111111111111111111 + + uint32_t *trampoline = static_cast(rwx), *original = static_cast(symbol); + + static_assert(A64_MAX_INSTRUCTIONS >= 5, "please fix A64_MAX_INSTRUCTIONS!"); + auto pc_offset = static_cast(__intval(replace) - __intval(symbol)) >> 2; + if (llabs(pc_offset) >= (mask >>1)) { + int32_t count = (reinterpret_cast(original + 2) & 7u) != 0u ? 5 : 4; + if (trampoline) { + if (rwx_size < count * 10u) { + return NULL; + } //if + __fix_instructions(original, count, trampoline); + } //if + + if (__make_rwx(original, 5 * sizeof(uint32_t)) == 0) { + if (count == 5) { + original[0] = A64_NOP; + ++original; + } //if + original[0] = 0x58000051u; // LDR X17, #0x8 + original[1] = 0xd61f0220u; // BR X17 + *reinterpret_cast(original + 2) = __intval(replace); + __flush_cache(symbol, 5 * sizeof(uint32_t)); + + } else { + trampoline = NULL; + } //if + } else { + if (trampoline) { + if (rwx_size < 1u * 10u) { + return NULL; + } //if + __fix_instructions(original, 1, trampoline); + } //if + + if (__make_rwx(original, 1 * sizeof(uint32_t)) == 0) { + __sync_cmpswap(original, *original, 0x14000000u | (pc_offset & mask)); // "B" ADDR_PCREL26 + __flush_cache(symbol, 1 * sizeof(uint32_t)); + + } else { + trampoline = NULL; + } //if + } //if + + return trampoline; +} + +//------------------------------------------------------------------------- + +A64_JNIEXPORT void A64HookFunction(void *const symbol, void *const replace, void **result) +{ + void *trampoline = NULL; + if (result != NULL) { + trampoline = FastAllocateTrampoline(); + *result = trampoline; + if (trampoline == NULL) return; + } //if + + trampoline = A64HookFunctionV(symbol, replace, trampoline, A64_MAX_INSTRUCTIONS * 10u); + if (trampoline == NULL && result != NULL) { + *result = NULL; + } //if +} +} + +#endif // defined(__aarch64__) \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/A64Inlinehook/And64InlineHook.hpp b/VirtualApp/lib/src/main/jni/A64Inlinehook/And64InlineHook.hpp new file mode 100755 index 000000000..07fd29bb8 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/A64Inlinehook/And64InlineHook.hpp @@ -0,0 +1,45 @@ +/* + * @date : 2018/04/18 + * @author : Rprop (r_prop@outlook.com) + * https://github.com/Rprop/And64InlineHook + */ +/* + MIT License + + Copyright (c) 2018 Rprop (r_prop@outlook.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ +#pragma once + +#include + +#define A64_MAX_BACKUPS 256 + +#ifdef __cplusplus +extern "C" { +#endif + +void A64HookFunction(void *const symbol, void *const replace, void **result); +void *A64HookFunctionV(void *const symbol, void *const replace, + void *const rwx, const uintptr_t rwx_size); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/Android.mk b/VirtualApp/lib/src/main/jni/Android.mk index ef2b533d9..6129a58b6 100644 --- a/VirtualApp/lib/src/main/jni/Android.mk +++ b/VirtualApp/lib/src/main/jni/Android.mk @@ -21,6 +21,7 @@ LOCAL_SRC_FILES := Jni/VAJni.cpp \ Substrate/SubstrateDebug.cpp \ Substrate/SubstrateHook.cpp \ Substrate/SubstratePosixMemory.cpp \ + A64Inlinehook/And64InlineHook.cpp LOCAL_LDLIBS := -llog -latomic LOCAL_STATIC_LIBRARIES := fb diff --git a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp index 69c4e2458..4201b1949 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp @@ -6,6 +6,8 @@ #include #ifdef __LP64__ + +#include "A64Inlinehook/And64InlineHook.hpp" #else #include #endif @@ -76,6 +78,7 @@ void IOUniformer::init_env_before_all() { static inline void hook_function(void *addr, void *new_func, void **old_func) { #ifdef __LP64__ + A64HookFunction(addr, new_func, old_func); #else MSHookFunction(addr, new_func, old_func); #endif From 19ff7cfa2f1f97475a73e1dc112e148aadf44640 Mon Sep 17 00:00:00 2001 From: tiann Date: Thu, 9 Jul 2020 17:04:23 +0800 Subject: [PATCH 08/11] Add missing syscall for 64bit Signed-off-by: tiann --- README.md | 1 + .../lib/src/main/jni/Foundation/IOUniformer.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b66106c3..d1d37b158 100644 --- a/README.md +++ b/README.md @@ -89,3 +89,4 @@ Credits 1. [VirtualApp](https://github.com/asLody/VirtualApp) 2. [Xposed](https://github.com/rovo89/Xposed) +3. [And64InlineHook](https://github.com/Rprop/And64InlineHook) diff --git a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp index 4201b1949..1a5b3ef1b 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp @@ -275,6 +275,15 @@ HOOK_DEF(int, __statfs, __const char *__file, struct statfs *__buf) { return ret; } +// int statfs64 (__const char *__file, struct statfs *__buf); +HOOK_DEF(int, statfs64, __const char *__file, struct statfs *__buf) { + int res; + const char *redirect_path = relocate_path(__file, &res); + int ret = syscall(__NR_statfs, redirect_path, __buf); + FREE(redirect_path, __file); + return ret; +} + int inline getArrayItemCount(char *const array[]) { int i; for (i = 0; array[i]; ++i); @@ -520,9 +529,9 @@ void IOUniformer::startUniformer(const char *so_path, int api_level, int preview HOOK_SYMBOL(handle, unlinkat); HOOK_SYMBOL(handle, symlinkat); HOOK_SYMBOL(handle, utimensat); -// HOOK_SYMBOL(handle, __getdents64); HOOK_SYMBOL(handle, chdir); HOOK_SYMBOL(handle, execve); + HOOK_SYMBOL(handle, statfs64); dlclose(handle); } // hook_dlopen(api_level); From d65b4df0a680bb1f16e20ffbb7b80987b89cd1d7 Mon Sep 17 00:00:00 2001 From: tiann Date: Thu, 9 Jul 2020 17:04:53 +0800 Subject: [PATCH 09/11] pre-release: 0.19.0 Signed-off-by: tiann --- VirtualApp/app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VirtualApp/app/build.gradle b/VirtualApp/app/build.gradle index a90f69788..1442c9d3b 100644 --- a/VirtualApp/app/build.gradle +++ b/VirtualApp/app/build.gradle @@ -23,8 +23,8 @@ android { applicationId "io.va.exposed" minSdkVersion 21 targetSdkVersion 23 - versionCode 182 - versionName "0.18.2" + versionCode 190 + versionName "0.19.0" multiDexEnabled false android { defaultConfig { From 80147650b0d74afc624f1eae3b7e0ea903cdaf04 Mon Sep 17 00:00:00 2001 From: tiann Date: Fri, 10 Jul 2020 13:41:09 +0800 Subject: [PATCH 10/11] Fix compile error on x86_64 Signed-off-by: tiann --- VirtualApp/lib/src/main/jni/Foundation/fake_dlfcn.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VirtualApp/lib/src/main/jni/Foundation/fake_dlfcn.cpp b/VirtualApp/lib/src/main/jni/Foundation/fake_dlfcn.cpp index ad3e1984a..5a89e4871 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/fake_dlfcn.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/fake_dlfcn.cpp @@ -25,7 +25,7 @@ #include #include "fake_dlfcn.h" -#define TAG_NAME "test2:fake_dlfcn" +#define TAG_NAME "fake_dlfcn" #define log_info(fmt,args...) __android_log_print(ANDROID_LOG_INFO, TAG_NAME, (const char *) fmt, ##args) #define log_err(fmt,args...) __android_log_print(ANDROID_LOG_ERROR, TAG_NAME, (const char *) fmt, ##args) @@ -42,7 +42,7 @@ #define Elf_Ehdr Elf32_Ehdr #define Elf_Shdr Elf32_Shdr #define Elf_Sym Elf32_Sym -#elif defined(__aarch64__) +#elif defined(__aarch64__) || defined(__x86_64__) #define Elf_Ehdr Elf64_Ehdr #define Elf_Shdr Elf64_Shdr #define Elf_Sym Elf64_Sym From f5b0cb2db44ecdbd133e57267219bc9a9e979f0a Mon Sep 17 00:00:00 2001 From: tiann Date: Fri, 10 Jul 2020 17:21:35 +0800 Subject: [PATCH 11/11] A64InlineHook for arm64 and Substrate for x86_64 Signed-off-by: tiann --- VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp | 5 ++--- VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp index 1a5b3ef1b..3fc8cfda8 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp @@ -5,8 +5,7 @@ #include #include -#ifdef __LP64__ - +#ifdef __aarch64__ #include "A64Inlinehook/And64InlineHook.hpp" #else #include @@ -77,7 +76,7 @@ void IOUniformer::init_env_before_all() { static inline void hook_function(void *addr, void *new_func, void **old_func) { -#ifdef __LP64__ +#ifdef __aarch64__ A64HookFunction(addr, new_func, old_func); #else MSHookFunction(addr, new_func, old_func); diff --git a/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp b/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp index 35b7ae170..c16d43836 100755 --- a/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp +++ b/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp @@ -924,7 +924,7 @@ static void SubstrateHookFunction(SubstrateProcessRef process, void *symbol, voi #endif _extern void MSHookFunction(void *symbol, void *replace, void **result) { -#ifndef __LP64__ +#ifndef __aarch64__ SubstrateHookFunction(NULL, symbol, replace, result); #endif }