Add injector

This commit is contained in:
Nullptr
2023-01-29 22:38:00 +08:00
parent fc8b7c1b4d
commit 70024cc082
17 changed files with 653 additions and 69 deletions
+79
View File
@@ -0,0 +1,79 @@
#include <linux/un.h>
#include <sys/socket.h>
#include <unistd.h>
#include "daemon.h"
#include "dl.h"
#include "socket_utils.h"
namespace zygiskd {
UniqueFd Connect(uint8_t retry) {
UniqueFd fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
struct sockaddr_un addr{
.sun_family = AF_UNIX,
.sun_path={0},
};
strncpy(addr.sun_path + 1, kZygiskSocket.data(), kZygiskSocket.size());
socklen_t socklen = sizeof(sa_family_t) + strlen(addr.sun_path + 1) + 1;
while (retry--) {
int r = connect(fd, reinterpret_cast<struct sockaddr*>(&addr), socklen);
if (r != -1) return r;
LOGW("retrying to connect to zygiskd, sleep 1s");
sleep(1);
}
return -1;
}
bool PingHeartbeat() {
auto fd = Connect(5);
if (fd == -1) {
PLOGE("Connect to zygiskd");
return false;
}
return true;
}
std::string ReadNativeBridge() {
auto fd = Connect(1);
if (fd == -1) {
PLOGE("ReadNativeBridge");
return "";
}
socket_utils::write_u8(fd, (uint8_t) SocketAction::ReadNativeBridge);
return socket_utils::read_string(fd);
}
UniqueFd ReadInjector() {
auto fd = Connect(1);
if (fd == -1) {
PLOGE("ReadInjector");
return -1;
}
socket_utils::write_u8(fd, (uint8_t) SocketAction::ReadInjector);
return socket_utils::recv_fd(fd);
}
std::vector<Module> ReadModules() {
std::vector<Module> modules;
auto fd = Connect(1);
if (fd == -1) {
PLOGE("ReadModules");
return modules;
}
socket_utils::write_u8(fd, (uint8_t) SocketAction::ReadModules);
size_t len = socket_utils::read_usize(fd);
for (size_t i = 0; i < len; i++) {
std::string name = socket_utils::read_string(fd);
UniqueFd module_fd = socket_utils::recv_fd(fd);
auto handle = DlopenMem(module_fd, RTLD_NOW);
if (handle == nullptr) {
LOGW("Failed to dlopen module %s: %s", name.data(), dlerror());
continue;
}
modules.emplace_back(name, handle);
}
return modules;
}
}
+51
View File
@@ -0,0 +1,51 @@
#include <cstdio>
#include <dlfcn.h>
#include <libgen.h>
#include <climits>
#include <cstring>
#include <android/dlext.h>
#include "dl.h"
#include "logging.h"
extern "C" [[gnu::weak]] struct android_namespace_t*
//NOLINTNEXTLINE
__loader_android_create_namespace([[maybe_unused]] const char* name,
[[maybe_unused]] const char* ld_library_path,
[[maybe_unused]] const char* default_library_path,
[[maybe_unused]] uint64_t type,
[[maybe_unused]] const char* permitted_when_isolated_path,
[[maybe_unused]] android_namespace_t* parent,
[[maybe_unused]] const void* caller_addr);
void* DlopenExt(const char* path, int flags) {
auto info = android_dlextinfo{};
auto* dir = dirname(path);
auto* ns = &__loader_android_create_namespace == nullptr ? nullptr :
__loader_android_create_namespace(path, dir, nullptr,
2, /* ANDROID_NAMESPACE_TYPE_SHARED */
nullptr, nullptr,
reinterpret_cast<void*>(&DlopenExt));
if (ns) {
info.flags = ANDROID_DLEXT_USE_NAMESPACE;
info.library_namespace = ns;
LOGD("Open %s with namespace %p", path, ns);
} else {
LOGD("Cannot create namespace for %s", path);
}
auto* handle = android_dlopen_ext(path, flags, &info);
if (handle) {
LOGD("dlopen %s: %p", path, handle);
} else {
LOGE("dlopen %s: %s", path, dlerror());
}
return handle;
}
void* DlopenMem(int memfd, int flags) {
char path[PATH_MAX];
sprintf(path, "/proc/self/fd/%d", memfd);
return DlopenExt(path, flags);
}
+114
View File
@@ -0,0 +1,114 @@
#include <cstddef>
#include <sys/socket.h>
#include <unistd.h>
#include "socket_utils.h"
namespace socket_utils {
ssize_t xread(int fd, void* buf, size_t count) {
size_t read_sz = 0;
ssize_t ret;
do {
ret = read(fd, (std::byte*) buf + read_sz, count - read_sz);
if (ret < 0) {
if (errno == EINTR) continue;
PLOGE("read");
return ret;
}
read_sz += ret;
} while (read_sz != count && ret != 0);
if (read_sz != count) {
PLOGE("read (%d != %d)", count, read_sz);
}
return read_sz;
}
ssize_t xwrite(int fd, const void* buf, size_t count) {
size_t write_sz = 0;
ssize_t ret;
do {
ret = write(fd, (std::byte*) buf + write_sz, count - write_sz);
if (ret < 0) {
if (errno == EINTR) continue;
PLOGE("write");
return ret;
}
write_sz += ret;
} while (write_sz != count && ret != 0);
if (write_sz != count) {
PLOGE("write (%d != %d)", count, write_sz);
}
return write_sz;
}
ssize_t xrecvmsg(int sockfd, struct msghdr* msg, int flags) {
int rec = recvmsg(sockfd, msg, flags);
if (rec < 0) PLOGE("recvmsg");
return rec;
}
void* recv_fds(int sockfd, char* cmsgbuf, size_t bufsz, int cnt) {
iovec iov = {
.iov_base = &cnt,
.iov_len = sizeof(cnt),
};
msghdr msg = {
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = cmsgbuf,
.msg_controllen = bufsz
};
xrecvmsg(sockfd, &msg, MSG_WAITALL);
cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
if (msg.msg_controllen != bufsz ||
cmsg == nullptr ||
cmsg->cmsg_len != CMSG_LEN(sizeof(int) * cnt) ||
cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS) {
return nullptr;
}
return CMSG_DATA(cmsg);
}
template<typename T>
inline T read_exact(int fd) {
T res;
return sizeof(T) == xread(fd, &res, sizeof(T)) ? res : -1;
}
template<typename T>
inline bool write_exact(int fd, T val) {
return sizeof(T) == xwrite(fd, &val, sizeof(T));
}
size_t read_usize(int fd) {
return read_exact<size_t>(fd);
}
std::string read_string(int fd) {
auto len = read_exact<size_t>(fd);
char buf[len + 1];
buf[len] = '\0';
xread(fd, buf, len);
return buf;
}
bool write_u8(int fd, uint8_t val) {
return write_exact<uint8_t>(fd, val);
}
int recv_fd(int sockfd) {
char cmsgbuf[CMSG_SPACE(sizeof(int))];
void* data = recv_fds(sockfd, cmsgbuf, sizeof(cmsgbuf), 1);
if (data == nullptr) return -1;
int result;
memcpy(&result, data, sizeof(int));
return result;
}
}