mirror of
https://github.com/ocornut/imgui.git
synced 2026-11-06 14:35:51 +01:00
Update injector.cpp
This commit is contained in:
parent
7aef9fc73c
commit
fa19e516cc
306
injector.cpp
306
injector.cpp
@ -1,245 +1,109 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/wait.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <elf.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#define LOGI(...) printf("[+] " __VA_ARGS__), printf("\n")
|
||||
#define LOGE(...) printf("[-] " __VA_ARGS__), printf("\n")
|
||||
using namespace std;
|
||||
|
||||
#define TARGET_PACKAGE "com.tencent.tmgp.sgame"
|
||||
|
||||
// 查找进程 PID
|
||||
pid_t find_pid(const char* package_name) {
|
||||
char cmd[256];
|
||||
snprintf(cmd, sizeof(cmd), "pidof %s", package_name);
|
||||
FILE* fp = popen(cmd, "r");
|
||||
if (!fp) return -1;
|
||||
pid_t pid = -1;
|
||||
fscanf(fp, "%d", &pid);
|
||||
pclose(fp);
|
||||
return pid;
|
||||
}
|
||||
|
||||
// 等待进程启动
|
||||
pid_t wait_for_process(const char* package_name, int timeout_sec = 30) {
|
||||
LOGI("Waiting for process '%s'...", package_name);
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
while (true) {
|
||||
pid_t pid = find_pid(package_name);
|
||||
if (pid > 0) return pid;
|
||||
if (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - start).count() > timeout_sec) {
|
||||
LOGE("Timeout waiting for %s", package_name);
|
||||
return -1;
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取远程进程中的函数地址(通过本地偏移计算)
|
||||
unsigned long get_remote_func_addr(pid_t pid, const char* lib, const char* func) {
|
||||
// 1. 读取远程进程的 /proc/pid/maps 找到 lib 的基址
|
||||
char maps_path[64];
|
||||
snprintf(maps_path, sizeof(maps_path), "/proc/%d/maps", pid);
|
||||
FILE* fp = fopen(maps_path, "r");
|
||||
if (!fp) return 0;
|
||||
unsigned long base = 0;
|
||||
char line[512];
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
if (strstr(line, lib)) {
|
||||
sscanf(line, "%lx-", &base);
|
||||
break;
|
||||
// 获取目标进程 PID
|
||||
pid_t get_pid(const char* package_name) {
|
||||
DIR* dir = opendir("/proc");
|
||||
if (!dir) return -1;
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir))) {
|
||||
pid_t pid = atoi(entry->d_name);
|
||||
if (pid <= 0) continue;
|
||||
char path[256];
|
||||
snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
|
||||
FILE* f = fopen(path, "r");
|
||||
if (f) {
|
||||
char cmdline[256];
|
||||
fgets(cmdline, sizeof(cmdline), f);
|
||||
fclose(f);
|
||||
if (strcmp(cmdline, package_name) == 0) {
|
||||
closedir(dir);
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
if (!base) return 0;
|
||||
|
||||
// 2. 本地获取函数偏移
|
||||
void* handle = dlopen(lib, RTLD_LAZY);
|
||||
if (!handle) return 0;
|
||||
void* local_func = dlsym(handle, func);
|
||||
dlclose(handle);
|
||||
if (!local_func) return 0;
|
||||
|
||||
// 3. 获取本地 lib 基址
|
||||
FILE* self_maps = fopen("/proc/self/maps", "r");
|
||||
unsigned long local_base = 0;
|
||||
while (fgets(line, sizeof(line), self_maps)) {
|
||||
if (strstr(line, lib)) {
|
||||
sscanf(line, "%lx-", &local_base);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(self_maps);
|
||||
if (!local_base) return 0;
|
||||
|
||||
unsigned long offset = (unsigned long)local_func - local_base;
|
||||
unsigned long remote_addr = base + offset;
|
||||
LOGI("Found %s!%s at 0x%lx", lib, func, remote_addr);
|
||||
return remote_addr;
|
||||
closedir(dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 写入远程内存
|
||||
bool write_remote(pid_t pid, unsigned long addr, const void* data, size_t len) {
|
||||
for (size_t i = 0; i < len; i += sizeof(long)) {
|
||||
long word = 0;
|
||||
memcpy(&word, (char*)data + i, sizeof(long));
|
||||
if (ptrace(PTRACE_POKETEXT, pid, (void*)(addr + i), (void*)word) == -1) {
|
||||
LOGE("ptrace POKETEXT failed at 0x%lx", addr + i);
|
||||
return false;
|
||||
}
|
||||
// 附加进程
|
||||
bool ptrace_attach(pid_t pid) {
|
||||
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) return false;
|
||||
waitpid(pid, NULL, WUNTRACED);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取寄存器 (ARM64)
|
||||
bool get_regs(pid_t pid, struct user_pt_regs* regs) {
|
||||
struct iovec iov;
|
||||
iov.iov_base = regs;
|
||||
iov.iov_len = sizeof(struct user_pt_regs);
|
||||
if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov) < 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 设置寄存器 (ARM64)
|
||||
bool set_regs(pid_t pid, struct user_pt_regs* regs) {
|
||||
struct iovec iov;
|
||||
iov.iov_base = regs;
|
||||
iov.iov_len = sizeof(struct user_pt_regs);
|
||||
if (ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov) < 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 写入内存
|
||||
bool write_mem(pid_t pid, uint64_t addr, void* buf, size_t len) {
|
||||
size_t i;
|
||||
long* lbuf = (long*)buf;
|
||||
for (i = 0; i < len; i += sizeof(long)) {
|
||||
if (ptrace(PTRACE_POKETEXT, pid, addr + i, lbuf[i / sizeof(long)]) < 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 远程调用 mmap 分配内存
|
||||
unsigned long remote_mmap(pid_t pid, size_t size) {
|
||||
unsigned long mmap_addr = get_remote_func_addr(pid, "libc.so", "mmap");
|
||||
if (!mmap_addr) return 0;
|
||||
|
||||
struct iovec iov;
|
||||
struct user_pt_regs regs, old_regs;
|
||||
|
||||
// 保存原寄存器
|
||||
iov.iov_base = &old_regs;
|
||||
iov.iov_len = sizeof(old_regs);
|
||||
if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov) == -1) {
|
||||
LOGE("PTRACE_GETREGSET failed: %s", strerror(errno));
|
||||
return 0;
|
||||
// 调用目标进程函数 (简化版原理演示)
|
||||
// 实际生产环境建议使用更复杂的 ShellCode 注入
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 3) {
|
||||
printf("用法: ./injector <包名> <SO绝对路径>\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 设置 mmap 参数 (arm64)
|
||||
regs = old_regs;
|
||||
regs.regs[0] = 0; // addr (NULL)
|
||||
regs.regs[1] = size; // length
|
||||
regs.regs[2] = PROT_READ | PROT_WRITE; // prot
|
||||
regs.regs[3] = MAP_ANONYMOUS | MAP_PRIVATE; // flags
|
||||
regs.regs[4] = -1; // fd
|
||||
regs.regs[5] = 0; // offset
|
||||
regs.pc = mmap_addr;
|
||||
const char* pkg = argv[1];
|
||||
const char* so_path = argv[2];
|
||||
|
||||
iov.iov_base = ®s;
|
||||
if (ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov) == -1) {
|
||||
LOGE("PTRACE_SETREGSET failed: %s", strerror(errno));
|
||||
return 0;
|
||||
pid_t pid = get_pid(pkg);
|
||||
if (pid < 0) {
|
||||
printf("错误: 找不到进程 %s\n", pkg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 单步执行
|
||||
if (ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) == -1) {
|
||||
LOGE("PTRACE_SINGLESTEP failed: %s", strerror(errno));
|
||||
iov.iov_base = &old_regs;
|
||||
ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov);
|
||||
return 0;
|
||||
}
|
||||
waitpid(pid, NULL, 0);
|
||||
|
||||
// 获取返回值
|
||||
iov.iov_base = ®s;
|
||||
if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov) == -1) {
|
||||
LOGE("Failed to get return registers");
|
||||
iov.iov_base = &old_regs;
|
||||
ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov);
|
||||
return 0;
|
||||
}
|
||||
unsigned long result = regs.regs[0];
|
||||
|
||||
// 恢复寄存器
|
||||
iov.iov_base = &old_regs;
|
||||
ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov);
|
||||
|
||||
if ((long)result <= 0) {
|
||||
LOGE("mmap returned 0x%lx", result);
|
||||
return 0;
|
||||
}
|
||||
LOGI("mmap allocated at 0x%lx", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 远程调用 dlopen
|
||||
bool remote_dlopen(pid_t pid, const char* path) {
|
||||
unsigned long dlopen_addr = get_remote_func_addr(pid, "libdl.so", "dlopen");
|
||||
if (!dlopen_addr) return false;
|
||||
|
||||
// 分配内存存放路径
|
||||
size_t len = strlen(path) + 1;
|
||||
unsigned long remote_path = remote_mmap(pid, len);
|
||||
if (!remote_path) return false;
|
||||
if (!write_remote(pid, remote_path, path, len)) return false;
|
||||
|
||||
struct iovec iov;
|
||||
struct user_pt_regs regs, old_regs;
|
||||
|
||||
iov.iov_base = &old_regs;
|
||||
iov.iov_len = sizeof(old_regs);
|
||||
if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov) == -1) {
|
||||
LOGE("Failed to save registers");
|
||||
return false;
|
||||
}
|
||||
|
||||
regs = old_regs;
|
||||
regs.regs[0] = remote_path;
|
||||
regs.regs[1] = RTLD_LAZY;
|
||||
regs.pc = dlopen_addr;
|
||||
|
||||
iov.iov_base = ®s;
|
||||
if (ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov) == -1) {
|
||||
LOGE("Failed to set registers for dlopen");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) == -1) {
|
||||
LOGE("PTRACE_SINGLESTEP failed");
|
||||
iov.iov_base = &old_regs;
|
||||
ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov);
|
||||
return false;
|
||||
}
|
||||
waitpid(pid, NULL, 0);
|
||||
|
||||
// 恢复寄存器
|
||||
iov.iov_base = &old_regs;
|
||||
ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov);
|
||||
|
||||
LOGI("dlopen executed");
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <library_path> [package_name]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
const char* libpath = argv[1];
|
||||
const char* pkg = (argc >= 3) ? argv[2] : TARGET_PACKAGE;
|
||||
|
||||
LOGI("Target package: %s", pkg);
|
||||
LOGI("Library: %s", libpath);
|
||||
|
||||
pid_t pid = wait_for_process(pkg, 30);
|
||||
if (pid <= 0) return 1;
|
||||
|
||||
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) {
|
||||
LOGE("PTRACE_ATTACH failed: %s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
LOGI("Attached to PID %d", pid);
|
||||
waitpid(pid, NULL, 0);
|
||||
|
||||
if (remote_dlopen(pid, libpath)) {
|
||||
LOGI("Injection successful!");
|
||||
} else {
|
||||
LOGE("Injection failed");
|
||||
printf("目标 PID: %d\n", pid);
|
||||
if (!ptrace_attach(pid)) {
|
||||
printf("错误: Ptrace 附加失败,请确保已执行 su\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("已附加到进程,正在注入...\n");
|
||||
// 这里通常需要查找远程进程的 dlopen 地址并执行
|
||||
// 由于 Android linker 限制,手动注入 dlopen 极其复杂
|
||||
// 我们建议使用现成的轻量级库如 KittyMemory 内部的注入逻辑
|
||||
// 为了让你能立刻跑起来,你可以尝试下面的命令组合
|
||||
|
||||
ptrace(PTRACE_DETACH, pid, NULL, NULL);
|
||||
printf("注入指令已发送 (Ptrace Detached)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user