refine code

This commit is contained in:
5ec1cff
2024-01-05 13:41:40 +08:00
parent ad32c4efb0
commit 675febfd14
4 changed files with 54 additions and 50 deletions

View File

@@ -94,7 +94,7 @@ public:
return true; return true;
} }
bool UnregisterHandler(EventHandler &handler) { [[maybe_unused]] bool UnregisterHandler(EventHandler &handler) {
if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, handler.GetFd(), nullptr) == -1) { if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, handler.GetFd(), nullptr) == -1) {
PLOGE("failed to del event handler"); PLOGE("failed to del event handler");
return false; return false;
@@ -149,7 +149,7 @@ struct SocketHandler : public EventHandler {
return sock_fd_; return sock_fd_;
} }
void HandleEvent(EventLoop &loop, uint32_t event) override { void HandleEvent(EventLoop &loop, uint32_t) override {
struct [[gnu::packed]] MsgHead { struct [[gnu::packed]] MsgHead {
Command cmd; Command cmd;
int length; int length;
@@ -346,7 +346,7 @@ public:
return signal_fd_; return signal_fd_;
} }
void HandleEvent(EventLoop &loop, uint32_t event) override { void HandleEvent(EventLoop &, uint32_t) override {
for (;;) { for (;;) {
ssize_t s = read(signal_fd_, &fdsi, sizeof(fdsi)); ssize_t s = read(signal_fd_, &fdsi, sizeof(fdsi));
if (s == -1) { if (s == -1) {
@@ -602,7 +602,7 @@ void send_control_command(Command cmd) {
if (nsend == -1) { if (nsend == -1) {
err(EXIT_FAILURE, "send"); err(EXIT_FAILURE, "send");
} else if (nsend != sizeof(cmd)) { } else if (nsend != sizeof(cmd)) {
printf("send %ld != %ld\n", nsend, sizeof(cmd)); printf("send %zu != %zu\n", nsend, sizeof(cmd));
exit(1); exit(1);
} }
printf("command sent\n"); printf("command sent\n");

View File

@@ -14,6 +14,8 @@
#include <signal.h> #include <signal.h>
#include <sys/system_properties.h> #include <sys/system_properties.h>
#include <string> #include <string>
#include <cinttypes>
#include "utils.hpp" #include "utils.hpp"
bool inject_on_main(int pid, const char *lib_path) { bool inject_on_main(int pid, const char *lib_path) {
@@ -23,42 +25,42 @@ bool inject_on_main(int pid, const char *lib_path) {
struct user_regs_struct regs{}, backup{}; struct user_regs_struct regs{}, backup{};
auto map = MapInfo::Scan(std::to_string(pid)); auto map = MapInfo::Scan(std::to_string(pid));
if (!get_regs(pid, regs)) return false; if (!get_regs(pid, regs)) return false;
auto arg = reinterpret_cast<uintptr_t *>(regs.REG_SP); auto arg = static_cast<uintptr_t>(regs.REG_SP);
LOGD("kernel argument %p %s", arg, get_addr_mem_region(map, arg).c_str()); LOGV("kernel argument %" PRIxPTR " %s", arg, get_addr_mem_region(map, arg).c_str());
int argc; int argc;
auto argv = reinterpret_cast<char **>(reinterpret_cast<uintptr_t *>(arg) + 1); auto argv = reinterpret_cast<char **>(reinterpret_cast<uintptr_t *>(arg) + 1);
LOGD("argv %p", argv); LOGV("argv %p", argv);
read_proc(pid, arg, &argc, sizeof(argc)); read_proc(pid, arg, &argc, sizeof(argc));
LOGD("argc %d", argc); LOGV("argc %d", argc);
auto envp = argv + argc + 1; auto envp = argv + argc + 1;
LOGD("envp %p", envp); LOGV("envp %p", envp);
auto p = envp; auto p = envp;
while (true) { while (true) {
uintptr_t *buf; uintptr_t *buf;
read_proc(pid, (uintptr_t *) p, &buf, sizeof(buf)); read_proc(pid, (uintptr_t) p, &buf, sizeof(buf));
if (buf != nullptr) ++p; if (buf != nullptr) ++p;
else break; else break;
} }
++p; ++p;
auto auxv = reinterpret_cast<ElfW(auxv_t) *>(p); auto auxv = reinterpret_cast<ElfW(auxv_t) *>(p);
LOGD("auxv %p %s", auxv, get_addr_mem_region(map, auxv).c_str()); LOGV("auxv %p %s", auxv, get_addr_mem_region(map, (uintptr_t) auxv).c_str());
auto v = auxv; auto v = auxv;
void *entry_addr = nullptr; uintptr_t entry_addr = 0;
void *addr_of_entry_addr = nullptr; uintptr_t addr_of_entry_addr = 0;
while (true) { while (true) {
ElfW(auxv_t) buf; ElfW(auxv_t) buf;
read_proc(pid, (uintptr_t *) v, &buf, sizeof(buf)); read_proc(pid, (uintptr_t) v, &buf, sizeof(buf));
if (buf.a_type == AT_ENTRY) { if (buf.a_type == AT_ENTRY) {
entry_addr = reinterpret_cast<void *>(buf.a_un.a_val); entry_addr = (uintptr_t) buf.a_un.a_val;
addr_of_entry_addr = reinterpret_cast<char *>(v) + offsetof(ElfW(auxv_t), a_un); addr_of_entry_addr = (uintptr_t) v + offsetof(ElfW(auxv_t), a_un);
LOGD("entry address %p %s (v=%p, entry_addr=%p)", entry_addr, LOGV("entry address %" PRIxPTR " %s (entry=%" PRIxPTR ", entry_addr=%" PRIxPTR ")", entry_addr,
get_addr_mem_region(map, entry_addr).c_str(), v, addr_of_entry_addr); get_addr_mem_region(map, entry_addr).c_str(), (uintptr_t) v, addr_of_entry_addr);
break; break;
} }
if (buf.a_type == AT_NULL) break; if (buf.a_type == AT_NULL) break;
v++; v++;
} }
if (entry_addr == nullptr) { if (entry_addr == 0) {
LOGE("failed to get entry"); LOGE("failed to get entry");
return false; return false;
} }
@@ -66,13 +68,13 @@ bool inject_on_main(int pid, const char *lib_path) {
// Replace the program entry with an invalid address // Replace the program entry with an invalid address
// For arm32 compatibility, we set the last bit to the same as the entry address // For arm32 compatibility, we set the last bit to the same as the entry address
uintptr_t break_addr = (-0x05ec1cff & ~1) | ((uintptr_t) entry_addr & 1); uintptr_t break_addr = (-0x05ec1cff & ~1) | ((uintptr_t) entry_addr & 1);
if (!write_proc(pid, (uintptr_t *) addr_of_entry_addr, &break_addr, sizeof(break_addr))) return false; if (!write_proc(pid, (uintptr_t) addr_of_entry_addr, &break_addr, sizeof(break_addr))) return false;
ptrace(PTRACE_CONT, pid, 0, 0); ptrace(PTRACE_CONT, pid, 0, 0);
int status; int status;
wait_for_trace(pid, &status, __WALL); wait_for_trace(pid, &status, __WALL);
if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSEGV) { if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSEGV) {
if (!get_regs(pid, regs)) return false; if (!get_regs(pid, regs)) return false;
if ((regs.REG_IP & ~1) != (break_addr & ~1)) { if (static_cast<uintptr_t>(regs.REG_IP & ~1) != (break_addr & ~1)) {
LOGE("stopped at unknown addr %p", (void *) regs.REG_IP); LOGE("stopped at unknown addr %p", (void *) regs.REG_IP);
return false; return false;
} }
@@ -80,7 +82,7 @@ bool inject_on_main(int pid, const char *lib_path) {
LOGD("stopped at entry"); LOGD("stopped at entry");
// restore entry address // restore entry address
if (!write_proc(pid, (uintptr_t *) addr_of_entry_addr, &entry_addr, sizeof(entry_addr))) return false; if (!write_proc(pid, (uintptr_t) addr_of_entry_addr, &entry_addr, sizeof(entry_addr))) return false;
// backup registers // backup registers
memcpy(&backup, &regs, sizeof(regs)); memcpy(&backup, &regs, sizeof(regs));
@@ -119,11 +121,13 @@ bool inject_on_main(int pid, const char *lib_path) {
args.clear(); args.clear();
args.push_back(dlerror_str_addr); args.push_back(dlerror_str_addr);
auto dlerror_len = remote_call(pid, regs, (uintptr_t) strlen_addr, (uintptr_t) libc_return_addr, args); auto dlerror_len = remote_call(pid, regs, (uintptr_t) strlen_addr, (uintptr_t) libc_return_addr, args);
LOGD("dlerror len %ld", dlerror_len); if (dlerror_len <= 0) {
if (dlerror_len <= 0) return false; LOGE("dlerror len <= 0");
return false;
}
std::string err; std::string err;
err.resize(dlerror_len + 1, 0); err.resize(dlerror_len + 1, 0);
read_proc(pid, (uintptr_t*) dlerror_str_addr, err.data(), dlerror_len); read_proc(pid, (uintptr_t) dlerror_str_addr, err.data(), dlerror_len);
LOGE("dlerror info %s", err.c_str()); LOGE("dlerror info %s", err.c_str());
return false; return false;
} }

View File

@@ -102,8 +102,8 @@ std::vector<MapInfo> MapInfo::Scan(const std::string& pid) {
return info; return info;
} }
ssize_t write_proc(int pid, uintptr_t *remote_addr, const void *buf, size_t len) { ssize_t write_proc(int pid, uintptr_t remote_addr, const void *buf, size_t len) {
LOGD("write to remote addr %p size %zu", remote_addr, len); LOGV("write to remote addr %" PRIxPTR " size %zu", remote_addr, len);
struct iovec local{ struct iovec local{
.iov_base = (void *) buf, .iov_base = (void *) buf,
.iov_len = len .iov_len = len
@@ -115,13 +115,13 @@ ssize_t write_proc(int pid, uintptr_t *remote_addr, const void *buf, size_t len)
auto l = process_vm_writev(pid, &local, 1, &remote, 1, 0); auto l = process_vm_writev(pid, &local, 1, &remote, 1, 0);
if (l == -1) { if (l == -1) {
PLOGE("process_vm_writev"); PLOGE("process_vm_writev");
} else if (l != len) { } else if (static_cast<size_t>(l) != len) {
LOGW("not fully written: %zu, excepted %zu", l, len); LOGW("not fully written: %zu, excepted %zu", l, len);
} }
return l; return l;
} }
ssize_t read_proc(int pid, uintptr_t *remote_addr, void *buf, size_t len) { ssize_t read_proc(int pid, uintptr_t remote_addr, void *buf, size_t len) {
struct iovec local{ struct iovec local{
.iov_base = (void *) buf, .iov_base = (void *) buf,
.iov_len = len .iov_len = len
@@ -133,7 +133,7 @@ ssize_t read_proc(int pid, uintptr_t *remote_addr, void *buf, size_t len) {
auto l = process_vm_readv(pid, &local, 1, &remote, 1, 0); auto l = process_vm_readv(pid, &local, 1, &remote, 1, 0);
if (l == -1) { if (l == -1) {
PLOGE("process_vm_readv"); PLOGE("process_vm_readv");
} else if (l != len) { } else if (static_cast<size_t>(l) != len) {
LOGW("not fully read: %zu, excepted %zu", l, len); LOGW("not fully read: %zu, excepted %zu", l, len);
} }
return l; return l;
@@ -177,9 +177,9 @@ bool set_regs(int pid, struct user_regs_struct &regs) {
return true; return true;
} }
std::string get_addr_mem_region(std::vector<MapInfo> &info, void *addr) { std::string get_addr_mem_region(std::vector<MapInfo> &info, uintptr_t addr) {
for (auto &map: info) { for (auto &map: info) {
if (map.start <= (uintptr_t) addr && map.end > (uintptr_t) addr) { if (map.start <= addr && map.end > addr) {
auto s = std::string(map.path); auto s = std::string(map.path);
s += ' '; s += ' ';
s += map.perms & PROT_READ ? 'r' : '-'; s += map.perms & PROT_READ ? 'r' : '-';
@@ -248,24 +248,24 @@ void align_stack(struct user_regs_struct &regs, long preserve) {
regs.REG_SP = (regs.REG_SP - preserve) & ~0xf; regs.REG_SP = (regs.REG_SP - preserve) & ~0xf;
} }
void *push_string(int pid, struct user_regs_struct &regs, const char *str) { uintptr_t push_string(int pid, struct user_regs_struct &regs, const char *str) {
auto len = strlen(str) + 1; auto len = strlen(str) + 1;
regs.REG_SP -= len; regs.REG_SP -= len;
align_stack(regs); align_stack(regs);
auto addr = reinterpret_cast<uintptr_t *>(regs.REG_SP); auto addr = static_cast<uintptr_t>(regs.REG_SP);
if (!write_proc(pid, addr, str, len)) { if (!write_proc(pid, addr, str, len)) {
LOGE("failed to write string %s", str); LOGE("failed to write string %s", str);
} }
LOGD("pushed string %p", addr); LOGD("pushed string %" PRIxPTR, addr);
return addr; return addr;
} }
uintptr_t remote_call(int pid, struct user_regs_struct &regs, uintptr_t func_addr, uintptr_t return_addr, uintptr_t remote_call(int pid, struct user_regs_struct &regs, uintptr_t func_addr, uintptr_t return_addr,
std::vector<long> &args) { std::vector<long> &args) {
align_stack(regs); align_stack(regs);
LOGD("call %d args", args.size()); LOGV("calling remote function %" PRIxPTR " args %zu", func_addr, args.size());
for (auto &a: args) { for (auto &a: args) {
LOGD("arg %p", (void *) a); LOGV("arg %p", (void *) a);
} }
#if defined(__x86_64__) #if defined(__x86_64__)
if (args.size() >= 1) { if (args.size() >= 1) {
@@ -289,12 +289,12 @@ uintptr_t remote_call(int pid, struct user_regs_struct &regs, uintptr_t func_add
if (args.size() > 6) { if (args.size() > 6) {
auto remain = (args.size() - 6) * sizeof(long); auto remain = (args.size() - 6) * sizeof(long);
align_stack(regs, remain); align_stack(regs, remain);
if (!write_proc(pid, (uintptr_t *) regs.REG_SP, args.data(), remain)) { if (!write_proc(pid, (uintptr_t) regs.REG_SP, args.data(), remain)) {
LOGE("failed to push arguments"); LOGE("failed to push arguments");
} }
} }
regs.REG_SP -= sizeof(long); regs.REG_SP -= sizeof(long);
if (!write_proc(pid, (uintptr_t *) regs.REG_SP, &return_addr, sizeof(return_addr))) { if (!write_proc(pid, (uintptr_t) regs.REG_SP, &return_addr, sizeof(return_addr))) {
LOGE("failed to write return addr"); LOGE("failed to write return addr");
} }
regs.REG_IP = func_addr; regs.REG_IP = func_addr;
@@ -302,34 +302,34 @@ uintptr_t remote_call(int pid, struct user_regs_struct &regs, uintptr_t func_add
if (args.size() > 0) { if (args.size() > 0) {
auto remain = (args.size()) * sizeof(long); auto remain = (args.size()) * sizeof(long);
align_stack(regs, remain); align_stack(regs, remain);
if (!write_proc(pid, (uintptr_t *)regs.REG_SP, args.data(), remain)) { if (!write_proc(pid, (uintptr_t) regs.REG_SP, args.data(), remain)) {
LOGE("failed to push arguments"); LOGE("failed to push arguments");
} }
} }
regs.REG_SP -= sizeof(long); regs.REG_SP -= sizeof(long);
if (!write_proc(pid, (uintptr_t*) regs.REG_SP, &return_addr, sizeof(return_addr))) { if (!write_proc(pid, (uintptr_t) regs.REG_SP, &return_addr, sizeof(return_addr))) {
LOGE("failed to write return addr"); LOGE("failed to write return addr");
} }
regs.REG_IP = func_addr; regs.REG_IP = func_addr;
#elif defined(__aarch64__) #elif defined(__aarch64__)
for (int i = 0; i < args.size() && i < 8; i++) { for (size_t i = 0; i < args.size() && i < 8; i++) {
regs.regs[i] = args[i]; regs.regs[i] = args[i];
} }
if (args.size() > 8) { if (args.size() > 8) {
auto remain = (args.size() - 8) * sizeof(long); auto remain = (args.size() - 8) * sizeof(long);
align_stack(regs, remain); align_stack(regs, remain);
write_proc(pid, (uintptr_t *)regs.REG_SP, args.data(), remain); write_proc(pid, (uintptr_t)regs.REG_SP, args.data(), remain);
} }
regs.regs[30] = return_addr; regs.regs[30] = return_addr;
regs.REG_IP = func_addr; regs.REG_IP = func_addr;
#elif defined(__arm__) #elif defined(__arm__)
for (int i = 0; i < args.size() && i < 4; i++) { for (size_t i = 0; i < args.size() && i < 4; i++) {
regs.uregs[i] = args[i]; regs.uregs[i] = args[i];
} }
if (args.size() > 4) { if (args.size() > 4) {
auto remain = (args.size() - 4) * sizeof(long); auto remain = (args.size() - 4) * sizeof(long);
align_stack(regs, remain); align_stack(regs, remain);
write_proc(pid, (uintptr_t *)regs.REG_SP, args.data(), remain); write_proc(pid, (uintptr_t)regs.REG_SP, args.data(), remain);
} }
regs.uregs[14] = return_addr; regs.uregs[14] = return_addr;
regs.REG_IP = func_addr; regs.REG_IP = func_addr;
@@ -353,7 +353,7 @@ uintptr_t remote_call(int pid, struct user_regs_struct &regs, uintptr_t func_add
return 0; return 0;
} }
if (WSTOPSIG(status) == SIGSEGV) { if (WSTOPSIG(status) == SIGSEGV) {
if (regs.REG_IP != return_addr) { if (static_cast<uintptr_t>(regs.REG_IP) != return_addr) {
LOGE("wrong return addr %p", (void *) regs.REG_IP); LOGE("wrong return addr %p", (void *) regs.REG_IP);
return 0; return 0;
} }

View File

@@ -60,15 +60,15 @@ struct MapInfo {
#define user_regs_struct user_regs #define user_regs_struct user_regs
#endif #endif
ssize_t write_proc(int pid, uintptr_t *remote_addr, const void *buf, size_t len); ssize_t write_proc(int pid, uintptr_t remote_addr, const void *buf, size_t len);
ssize_t read_proc(int pid, uintptr_t *remote_addr, void *buf, size_t len); ssize_t read_proc(int pid, uintptr_t remote_addr, void *buf, size_t len);
bool get_regs(int pid, struct user_regs_struct &regs); bool get_regs(int pid, struct user_regs_struct &regs);
bool set_regs(int pid, struct user_regs_struct &regs); bool set_regs(int pid, struct user_regs_struct &regs);
std::string get_addr_mem_region(std::vector<MapInfo> &info, void *addr); std::string get_addr_mem_region(std::vector<MapInfo> &info, uintptr_t addr);
void *find_module_base(std::vector<MapInfo> &info, std::string_view suffix); void *find_module_base(std::vector<MapInfo> &info, std::string_view suffix);
@@ -80,7 +80,7 @@ void *find_func_addr(
void align_stack(struct user_regs_struct &regs, long preserve = 0); void align_stack(struct user_regs_struct &regs, long preserve = 0);
void *push_string(int pid, struct user_regs_struct &regs, const char *str); uintptr_t push_string(int pid, struct user_regs_struct &regs, const char *str);
uintptr_t remote_call(int pid, struct user_regs_struct &regs, uintptr_t func_addr, uintptr_t return_addr, uintptr_t remote_call(int pid, struct user_regs_struct &regs, uintptr_t func_addr, uintptr_t return_addr,
std::vector<long> &args); std::vector<long> &args);