Use rirud to read files from /data/adb

This commit is contained in:
LoveSy 2020-12-02 23:10:17 +08:00 committed by solohsu
parent baf1d6b6bb
commit f04628e997
12 changed files with 194 additions and 200 deletions

View File

@ -43,9 +43,19 @@ ext {
riruModuleId = "edxp" riruModuleId = "edxp"
zipPathMagiskRelease = "$buildDir/tmp/release/magisk" zipPathMagiskRelease = "$buildDir/tmp/release/magisk"
moduleMinRiruApiVersion = 9 moduleMinRiruApiVersion = 10
moduleMinRiruVersionName = "v22.0" moduleMinRiruVersionName = "v23.0"
moduleMaxRiruApiVersion = 9 moduleMaxRiruApiVersion = 10
}
repositories {
mavenLocal()
jcenter()
maven { url 'https://dl.bintray.com/rikkaw/Libraries' }
}
dependencies {
implementation 'rikka.ndk:riru:10'
} }
android { android {
@ -54,6 +64,10 @@ android {
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
buildFeatures {
prefab true
}
externalNativeBuild { externalNativeBuild {
cmake { cmake {
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64' abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'

View File

@ -1,7 +1,6 @@
cmake_minimum_required(VERSION 3.4.1) cmake_minimum_required(VERSION 3.4.1)
add_subdirectory(xhook) add_subdirectory(xhook)
add_subdirectory(riru)
add_subdirectory(yahfa) add_subdirectory(yahfa)
add_subdirectory(android) add_subdirectory(android)

View File

@ -1,6 +0,0 @@
cmake_minimum_required(VERSION 3.4.1)
aux_source_directory(src SRC_LIST)
add_library(riru STATIC ${SRC_LIST})
target_include_directories(riru INTERFACE src)

View File

@ -1,169 +0,0 @@
#ifndef RIRU_H
#define RIRU_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <jni.h>
#include <sys/types.h>
// ---------------------------------------------------------
typedef void(onModuleLoaded_v9)();
typedef int(shouldSkipUid_v9)(int uid);
typedef void(nativeForkAndSpecializePre_v9)(
JNIEnv *env, jclass cls, jint *uid, jint *gid, jintArray *gids, jint *runtimeFlags,
jobjectArray *rlimits, jint *mountExternal, jstring *seInfo, jstring *niceName,
jintArray *fdsToClose, jintArray *fdsToIgnore, jboolean *is_child_zygote,
jstring *instructionSet, jstring *appDataDir, jboolean *isTopApp, jobjectArray *pkgDataInfoList,
jobjectArray *whitelistedDataInfoList, jboolean *bindMountAppDataDirs, jboolean *bindMountAppStorageDirs);
typedef void(nativeForkAndSpecializePost_v9)(JNIEnv *env, jclass cls, jint res);
typedef void(nativeForkSystemServerPre_v9)(
JNIEnv *env, jclass cls, uid_t *uid, gid_t *gid, jintArray *gids, jint *runtimeFlags,
jobjectArray *rlimits, jlong *permittedCapabilities, jlong *effectiveCapabilities);
typedef void(nativeForkSystemServerPost_v9)(JNIEnv *env, jclass cls, jint res);
typedef void(nativeSpecializeAppProcessPre_v9)(
JNIEnv *env, jclass cls, jint *uid, jint *gid, jintArray *gids, jint *runtimeFlags,
jobjectArray *rlimits, jint *mountExternal, jstring *seInfo, jstring *niceName,
jboolean *startChildZygote, jstring *instructionSet, jstring *appDataDir,
jboolean *isTopApp, jobjectArray *pkgDataInfoList, jobjectArray *whitelistedDataInfoList,
jboolean *bindMountAppDataDirs, jboolean *bindMountAppStorageDirs);
typedef void(nativeSpecializeAppProcessPost_v9)(JNIEnv *env, jclass cls);
typedef struct {
int supportHide;
int version;
const char *versionName;
onModuleLoaded_v9 *onModuleLoaded;
shouldSkipUid_v9 *shouldSkipUid;
nativeForkAndSpecializePre_v9 *forkAndSpecializePre;
nativeForkAndSpecializePost_v9 *forkAndSpecializePost;
nativeForkSystemServerPre_v9 *forkSystemServerPre;
nativeForkSystemServerPost_v9 *forkSystemServerPost;
nativeSpecializeAppProcessPre_v9 *specializeAppProcessPre;
nativeSpecializeAppProcessPost_v9 *specializeAppProcessPost;
} RiruModuleInfoV9;
// ---------------------------------------------------------
typedef void *(RiruGetFunc_v9)(uint32_t token, const char *name);
typedef void (RiruSetFunc_v9)(uint32_t token, const char *name, void *func);
typedef void *(RiruGetJNINativeMethodFunc_v9)(uint32_t token, const char *className, const char *name, const char *signature);
typedef void (RiruSetJNINativeMethodFunc_v9)(uint32_t token, const char *className, const char *name, const char *signature, void *func);
typedef const JNINativeMethod *(RiruGetOriginalJNINativeMethodFunc_v9)(const char *className, const char *name, const char *signature);
typedef void *(RiruGetGlobalValue_v9)(const char *key);
typedef void(RiruPutGlobalValue_v9)(const char *key, void *value);
typedef struct {
uint32_t token;
RiruGetFunc_v9 *getFunc;
RiruGetJNINativeMethodFunc_v9 *getJNINativeMethodFunc;
RiruSetFunc_v9 *setFunc;
RiruSetJNINativeMethodFunc_v9 *setJNINativeMethodFunc;
RiruGetOriginalJNINativeMethodFunc_v9 *getOriginalJNINativeMethodFunc;
RiruGetGlobalValue_v9 *getGlobalValue;
RiruPutGlobalValue_v9 *putGlobalValue;
} RiruApiV9;
typedef void *(RiruInit_t)(void *);
#ifdef RIRU_MODULE
#define RIRU_EXPORT __attribute__((visibility("default"))) __attribute__((used))
/*
* Init will be called three times.
*
* The first time:
* Returns the highest version number supported by both Riru and the module.
*
* arg: (int *) Riru's API version
* returns: (int *) the highest possible API version
*
* The second time:
* Returns the RiruModuleX struct created by the module (X is the return of the first call).
*
* arg: (RiruApiVX *) RiruApi strcut, this pointer can be saved for further use
* returns: (RiruModuleX *) RiruModule strcut
*
* The second time:
* Let the module to cleanup (such as RiruModuleX struct created before).
*
* arg: null
* returns: (ignored)
*
*/
void* init(void *arg) RIRU_EXPORT;
extern int riru_api_version;
extern RiruApiV9 *riru_api_v9;
inline void *riru_get_func(const char *name) {
if (riru_api_version == 9) {
return riru_api_v9->getFunc(riru_api_v9->token, name);
}
return NULL;
}
inline void *riru_get_native_method_func(const char *className, const char *name, const char *signature) {
if (riru_api_version == 9) {
return riru_api_v9->getJNINativeMethodFunc(riru_api_v9->token, className, name, signature);
}
return NULL;
}
inline const JNINativeMethod *riru_get_original_native_methods(const char *className, const char *name, const char *signature) {
if (riru_api_version == 9) {
return riru_api_v9->getOriginalJNINativeMethodFunc(className, name, signature);
}
return NULL;
}
inline void riru_set_func(const char *name, void *func) {
if (riru_api_version == 9) {
riru_api_v9->setFunc(riru_api_v9->token, name, func);
}
}
inline void riru_set_native_method_func(const char *className, const char *name, const char *signature,
void *func) {
if (riru_api_version == 9) {
riru_api_v9->setJNINativeMethodFunc(riru_api_v9->token, className, name, signature, func);
}
}
inline void *riru_get_global_value(const char *key) {
if (riru_api_version == 9) {
return riru_api_v9->getGlobalValue(key);
}
return NULL;
}
inline void riru_put_global_value(const char *key, void *value) {
if (riru_api_version == 9) {
riru_api_v9->putGlobalValue(key, value);
}
}
#endif
#ifdef __cplusplus
}
#endif
#endif //RIRU_H

View File

@ -7,5 +7,6 @@ aux_source_directory(src/jni SRC_JNI_LIST)
include_directories(include src) include_directories(include src)
add_library(riru_edxp SHARED ${SRC_LIST} ${SRC_JNI_LIST}) add_library(riru_edxp SHARED ${SRC_LIST} ${SRC_JNI_LIST})
find_package(riru REQUIRED CONFIG)
find_library(log-lib log) find_library(log-lib log)
target_link_libraries(riru_edxp yahfa riru xhook android dobby ${log-lib}) target_link_libraries(riru_edxp yahfa riru::riru xhook android dobby ${log-lib})

View File

@ -19,6 +19,7 @@
#include "art/runtime/native/native_util.h" #include "art/runtime/native/native_util.h"
#include "config_manager.h" #include "config_manager.h"
#include "utils.h" #include "utils.h"
#include "rirud_socket.h"
/* /*
* Logic: * Logic:
@ -79,22 +80,23 @@
* of the conf on its own data dir) * of the conf on its own data dir)
* *
*/ */
namespace edxp { namespace edxp {
namespace fs = std::filesystem; namespace fs = std::filesystem;
fs::path ConfigManager::RetrieveBaseConfigPath() const { fs::path ConfigManager::RetrieveBaseConfigPath() const {
fs::path misc_path("/data/adb/edxp/misc_path"); fs::path misc_path("/data/adb/edxp/misc_path");
if (path_exists(misc_path)) { try {
std::ifstream ifs(misc_path); RirudSocket rirud_socket{};
if (ifs.good()) { auto path = rirud_socket.ReadFile(misc_path);
return fs::path("/data/misc") / path.erase(std::find_if(path.rbegin(), path.rend(), [](unsigned char ch) {
std::string{std::istream_iterator<char>(ifs), return !std::isspace(ch);
std::istream_iterator<char>()} / }).base(), path.end());
std::to_string(user_); return fs::path("/data/misc") / path / std::to_string(user_);
} } catch (const RirudSocket::RirudSocketException &e) {
LOGE("%s", e.what());
return {};
} }
LOGW("fallback because %s is not accessible", misc_path.c_str());
return data_path_prefix_ / kPrimaryInstallerPkgName;
} }
std::string ConfigManager::RetrieveInstallerPkgName() const { std::string ConfigManager::RetrieveInstallerPkgName() const {
@ -257,7 +259,7 @@ namespace edxp {
} }
bool ConfigManager::InitConfigPath() const { bool ConfigManager::InitConfigPath() const {
if (base_config_path_.string().rfind("/data/misc") != 0) return true; if (base_config_path_.empty()) return false;
try { try {
fs::create_directories(base_config_path_); fs::create_directories(base_config_path_);
fs::permissions(base_config_path_.parent_path(), fs::permissions(base_config_path_.parent_path(),

View File

@ -14,7 +14,7 @@
#include "logging.h" #include "logging.h"
#include "config.h" #include "config.h"
#include "edxp_context.h" #include "edxp_context.h"
#include "riru.h" #include <riru.h>
#include "config_manager.h" #include "config_manager.h"
#include "native_hook.h" #include "native_hook.h"
@ -90,7 +90,7 @@ namespace edxp {
} }
int riru_api_version; int riru_api_version;
RiruApiV9 *riru_api_v9; RiruApiV10 *riru_api_v10;
RIRU_EXPORT void *init(void *arg) { RIRU_EXPORT void *init(void *arg) {
static int step = 0; static int step = 0;
@ -106,11 +106,13 @@ RIRU_EXPORT void *init(void *arg) {
} }
case 2: { case 2: {
switch (riru_api_version) { switch (riru_api_version) {
case 10:
[[fallthrough]];
case 9: { case 9: {
riru_api_v9 = (RiruApiV9 *) arg; riru_api_v10 = (RiruApiV10 *) arg;
auto module = (RiruModuleInfoV9 *) malloc(sizeof(RiruModuleInfoV9)); auto module = (RiruModuleInfoV10 *) malloc(sizeof(RiruModuleInfoV10));
memset(module, 0, sizeof(RiruModuleInfoV9)); memset(module, 0, sizeof(RiruModuleInfoV10));
_module = module; _module = module;
module->supportHide = true; module->supportHide = true;

View File

@ -0,0 +1,105 @@
//
// Created by loves on 12/2/2020.
//
#include "rirud_socket.h"
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <logging.h>
#include <cerrno>
namespace fs = std::filesystem;
template<>
void RirudSocket::Write<std::string>(const std::string &str) {
auto count = str.size();
auto *buf = str.data();
Write(buf, count);
}
template<typename T>
void RirudSocket::Write(const T &obj) {
auto len = sizeof(T);
auto *buf = &obj;
Write(reinterpret_cast<const char*>(buf), len);
}
template<>
void RirudSocket::Read<std::string>(std::string &str) {
auto count = str.size();
auto *buf = str.data();
Read(buf, count);
}
template<typename T>
void RirudSocket::Read(T &obj) {
auto len = sizeof(T);
auto *buf = &obj;
Read(reinterpret_cast<char*>(buf), len);
}
RirudSocket::RirudSocket() {
if ((fd_ = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0) {
throw RirudSocketException(strerror(errno));
}
struct sockaddr_un addr{
.sun_family = AF_UNIX,
.sun_path={0}
};
strcpy(addr.sun_path + 1, "rirud");
socklen_t socklen = sizeof(sa_family_t) + strlen(addr.sun_path + 1) + 1;
if (connect(fd_, reinterpret_cast<struct sockaddr *>(&addr), socklen) == -1) {
throw RirudSocketException(strerror(errno));
}
}
RirudSocket::~RirudSocket() {
if (fd_ != -1)
close(fd_);
}
std::string RirudSocket::ReadFile(const fs::path &path) {
Write(ACTION_READ_FILE);
Write(path.string().size());
Write(path.string());
int32_t rirud_errno;
Read(rirud_errno);
if(rirud_errno != 0) {
throw RirudSocketException(strerror(rirud_errno));
}
uint32_t file_size;
Read(file_size);
std::string content;
content.resize(file_size);
Read(content);
return content;
}
void RirudSocket::Write(const char *buf, size_t len) const {
auto count = len;
while (count > 0) {
ssize_t size = write(fd_, buf, count < SSIZE_MAX ? count : SSIZE_MAX);
if (size == -1) {
if (errno == EINTR) continue;
else throw RirudSocketException(strerror(errno));
}
buf = buf + size;
count -= size;
}
}
void RirudSocket::Read(char *out, size_t len) const {
while (len > 0) {
ssize_t ret = read(fd_, out, len);
if (ret <= 0) {
if(errno == EINTR) continue;
else throw RirudSocketException(strerror(errno));
}
out = out + ret;
len -= ret;
}
}

View File

@ -0,0 +1,47 @@
//
// Created by loves on 12/2/2020.
//
#pragma once
#include <string>
#include <filesystem>
class RirudSocket {
public:
// class DirIter {};
class RirudSocketException : public std::runtime_error {
public:
RirudSocketException(const std::string &what) : std::runtime_error(what) {}
};
RirudSocket();
std::string ReadFile(const std::filesystem::path &path);
// DirIter ReadDir(const std::filesystem::path &path);
// DirIter RecursiveReadDir(const std::filesystem::path &path);
~RirudSocket();
private:
RirudSocket(const RirudSocket &) = delete;
RirudSocket operator=(const RirudSocket &) = delete;
inline static const uint32_t ACTION_READ_FILE = 4;
template<typename T>
void Write(const T &);
template<typename T>
void Read(T &);
void Write(const char *buf, size_t len) const;
void Read(char *buf, size_t len) const;
int fd_ = -1;
};

View File

@ -1,4 +1,2 @@
allow system_server system_server process execmem allow system_server system_server process execmem
allow system_server system_server memprotect mmap_zero allow system_server system_server memprotect mmap_zero
# TODO: use rirud
allow zygote adb_data_file file { getattr read }

View File

@ -1,2 +1,3 @@
androidCompileSdkVersion=30 androidCompileSdkVersion=30
androidCompileNdkVersion=22.0.6917172 androidCompileNdkVersion=22.0.6917172
android.prefabVersion=1.1.2