Replace native bridge with fuse + ptrace

This commit is contained in:
Nullptr
2023-10-20 13:49:03 +08:00
parent 77cb323506
commit 5f2dd50703
18 changed files with 452 additions and 301 deletions

View File

@@ -13,16 +13,7 @@ LOCAL_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := zygisk_loader
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
FILE_LIST := $(filter %.cpp, $(call walk, $(LOCAL_PATH)/loader))
LOCAL_SRC_FILES := $(FILE_LIST:COMMON_FILE_LIST:$(LOCAL_PATH)/%=%)
LOCAL_STATIC_LIBRARIES := cxx common
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := zygisk_injector
LOCAL_MODULE := zygisk
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
FILE_LIST := $(filter %.cpp, $(call walk, $(LOCAL_PATH)/injector))
LOCAL_SRC_FILES := $(FILE_LIST:COMMON_FILE_LIST:$(LOCAL_PATH)/%=%)

View File

@@ -8,32 +8,14 @@
namespace zygiskd {
bool sMagicRead = false;
static std::string sSocketName;
void ReadMagic() {
sMagicRead = true;
char magic[PATH_MAX]{0};
auto fp = fopen(kZygiskMagic, "r");
if (fp == nullptr) {
PLOGE("Open magic file");
return;
}
fgets(magic, PATH_MAX, fp);
fclose(fp);
sSocketName.append(LP_SELECT("zygiskd32", "zygiskd64")).append(magic);
LOGD("Socket name: %s", sSocketName.data());
}
int Connect(uint8_t retry) {
if (!sMagicRead) ReadMagic();
int fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
struct sockaddr_un addr{
.sun_family = AF_UNIX,
.sun_path={0},
};
strcpy(addr.sun_path + 1, sSocketName.data());
socklen_t socklen = sizeof(sa_family_t) + strlen(addr.sun_path + 1) + 1;
strcpy(addr.sun_path, kCPSocketPath);
socklen_t socklen = sizeof(addr);
while (retry--) {
int r = connect(fd, reinterpret_cast<struct sockaddr*>(&addr), socklen);
@@ -66,16 +48,6 @@ namespace zygiskd {
return fd;
}
std::string ReadNativeBridge() {
UniqueFd fd = Connect(1);
if (fd == -1) {
PLOGE("ReadNativeBridge");
return "";
}
socket_utils::write_u8(fd, (uint8_t) SocketAction::ReadNativeBridge);
return socket_utils::read_string(fd);
}
uint32_t GetProcessFlags(uid_t uid) {
UniqueFd fd = Connect(1);
if (fd == -1) {

View File

@@ -11,7 +11,7 @@
# define LP_SELECT(lp32, lp64) lp32
#endif
constexpr auto kZygiskMagic = "/system/zygisk_magic";
constexpr auto kCPSocketPath = "/dev/zygisk/" LP_SELECT("cp32", "cp64") ".sock";
class UniqueFd {
using Fd = int;
@@ -54,7 +54,6 @@ namespace zygiskd {
enum class SocketAction {
PingHeartBeat,
RequestLogcatFd,
ReadNativeBridge,
GetProcessFlags,
ReadModules,
RequestCompanionSocket,
@@ -65,8 +64,6 @@ namespace zygiskd {
int RequestLogcatFd();
std::string ReadNativeBridge();
std::vector<Module> ReadModules();
uint32_t GetProcessFlags(uid_t uid);

View File

@@ -8,12 +8,19 @@ using namespace std;
void *self_handle = nullptr;
extern "C" [[gnu::visibility("default")]]
void entry(void *handle) {
void entry(void* handle) {
LOGI("Zygisk library injected");
self_handle = handle;
if (!zygiskd::PingHeartbeat()) {
LOGE("Zygisk daemon is not running");
return;
}
#ifdef NDEBUG
logging::setfd(zygiskd::RequestLogcatFd());
#endif
self_handle = handle;
LOGD("Load injector successfully");
LOGD("Start hooking");
hook_functions();
}

View File

@@ -1,100 +0,0 @@
#include <string_view>
#include <sys/system_properties.h>
#include <unistd.h>
#include <array>
#include "daemon.h"
#include "dl.h"
#include "logging.h"
#include "native_bridge_callbacks.h"
extern "C" [[gnu::visibility("default")]]
uint8_t NativeBridgeItf[sizeof(NativeBridgeCallbacks<__ANDROID_API_R__>) * 2]{0};
namespace {
constexpr auto kZygoteProcesses = {"zygote", "zygote32", "zygote64", "usap32", "usap64"};
constexpr auto kInjector = "/system/" LP_SELECT("lib", "lib64") "/libzygisk_injector.so";
void* sOriginalBridge = nullptr;
}
__used __attribute__((destructor))
void Destructor() {
if (sOriginalBridge) {
dlclose(sOriginalBridge);
}
}
__used __attribute__((constructor))
void Constructor() {
if (getuid() != 0) {
return;
}
std::string_view cmdline = getprogname();
if (std::none_of(
kZygoteProcesses.begin(), kZygoteProcesses.end(),
[&](const char* p) { return cmdline == p; }
)) {
LOGW("Not started as zygote (cmdline=%s)", cmdline.data());
return;
}
std::string native_bridge;
do {
if (!zygiskd::PingHeartbeat()) break;
#ifdef NDEBUG
logging::setfd(zygiskd::RequestLogcatFd());
#endif
LOGI("Read native bridge");
native_bridge = zygiskd::ReadNativeBridge();
LOGI("Load injector");
auto handle = DlopenExt(kInjector, RTLD_NOW);
if (handle == nullptr) {
LOGE("Failed to dlopen injector: %s", dlerror());
break;
}
auto entry = dlsym(handle, "entry");
if (entry == nullptr) {
LOGE("Failed to dlsym injector entry: %s", dlerror());
dlclose(handle);
break;
}
reinterpret_cast<void (*)(void*)>(entry)(handle);
} while (false);
do {
if (native_bridge.empty() || native_bridge == "0") break;
LOGI("Load original native bridge: %s", native_bridge.data());
sOriginalBridge = dlopen(native_bridge.data(), RTLD_NOW);
if (sOriginalBridge == nullptr) {
LOGE("%s", dlerror());
break;
}
auto* original_native_bridge_itf = dlsym(sOriginalBridge, "NativeBridgeItf");
if (original_native_bridge_itf == nullptr) {
LOGE("%s", dlerror());
break;
}
long sdk = 0;
char value[PROP_VALUE_MAX + 1];
if (__system_property_get("ro.build.version.sdk", value) > 0) {
sdk = strtol(value, nullptr, 10);
}
auto callbacks_size = 0;
if (sdk >= __ANDROID_API_R__) {
callbacks_size = sizeof(NativeBridgeCallbacks<__ANDROID_API_R__>);
} else if (sdk == __ANDROID_API_Q__) {
callbacks_size = sizeof(NativeBridgeCallbacks<__ANDROID_API_Q__>);
}
memcpy(NativeBridgeItf, original_native_bridge_itf, callbacks_size);
} while (false);
logging::setfd(-1);
}