_SC_PAGESIZE

C:\cygwin\usr\include\sys\unistd.h

/*
* sysconf values per IEEE Std 1003.1, 2008 Edition
*/

#define _SC_ARG_MAX 0
#define _SC_CHILD_MAX 1
#define _SC_CLK_TCK 2
#define _SC_NGROUPS_MAX 3
#define _SC_OPEN_MAX 4
#define _SC_JOB_CONTROL 5
#define _SC_SAVED_IDS 6
#define _SC_VERSION 7
#define _SC_PAGESIZE 8
#define _SC_PAGE_SIZE _SC_PAGESIZE

#if defined(__arm__) int process_vm_readv_syscall = 376; int process_vm_writev_syscall = 377; #elif defined(__aarch64__) int process_vm_readv_syscall = 270; int process_vm_writev_syscall = 271; #elif defined(__i386__) int process_vm_readv_syscall = 347; int process_vm_writev_syscall = 348; #else int process_vm_readv_syscall = 310; int process_vm_writev_syscall = 311; #endif ssize_t process_v(pid_t __pid, const struct iovec *__local_iov, unsigned long __local_iov_count, const struct iovec *__remote_iov, unsigned long __remote_iov_count, unsigned long __flags, bool iswrite) { return syscall((iswrite ? process_vm_writev_syscall : process_vm_readv_syscall), __pid, __local_iov, __local_iov_count, __remote_iov, __remote_iov_count, __flags); } bool WriteAddr(void *addr, void *buffer, size_t length) { unsigned long page_size = sysconf(_SC_PAGESIZE); unsigned long size = page_size * sizeof(uintptr_t); return mprotect((void *) ((uintptr_t) addr - ((uintptr_t) addr % page_size) - page_size), (size_t) size, PROT_EXEC | PROT_READ | PROT_WRITE) == 0 && memcpy(addr, buffer, length) != 0; } // 进程读写内存 bool pvm(void *address, void *buffer, size_t size, bool iswrite) { struct iovec local[1]; struct iovec remote[1]; local[0].iov_base = buffer; local[0].iov_len = size; remote[0].iov_base = address; remote[0].iov_len = size; ssize_t bytes = process_v(pid, local, 1, remote, 1, 0, iswrite); return bytes == size; } // 读取内存 bool vm_readv(long address, void *buffer, size_t size) { return pvm(reinterpret_cast < void *>(address), buffer, size, false); } // 写入内存 bool vm_writev(long address, void *buffer, size_t size) { return pvm(reinterpret_cast < void *>(address), buffer, size, true); }读写不了怎么办
03-18
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/mman.h> #include <sys/uio.h> #include <signal.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <ctype.h> #include <sys/types.h> #include <stdint.h> #include <sys/syscall.h> #include <sys/ptrace.h> #include <sys/wait.h> // ARM64缓存类型定义 #ifndef CACHE_TYPE_INSTRUCTION #define CACHE_TYPE_INSTRUCTION 0 #endif #ifndef CACHE_TYPE_DATA #define CACHE_TYPE_DATA 1 #endif // 系统调用号数组(适配Linux 5系列内核) #if defined(__aarch64__) const int cache_flush_syscalls[] = {118, 123, 124, 125, 126, 0}; #endif typedef uint64_t ADDRESS; // 全局变量(存储目标进程信息) struct ProcessInfo { int pid; uint64_t so_base; } processInfo = {-1, 0}; typedef struct { uint64_t start_addr; uint64_t end_addr; char permissions[5]; } ModuleRange; typedef struct { ModuleRange ranges[200]; int count; } ModuleInfo; // 获取目标进程PID int getPID(const char *packageName) { int id = -1; DIR *dir = opendir("/proc"); if (!dir) { perror("打开/proc目录失败"); return -1; } struct dirent *entry; while ((entry = readdir(dir)) != NULL) { if (entry->d_type == DT_DIR) { id = atoi(entry->d_name); if (id > 0) { char filename[64], cmdline[64]; snprintf(filename, sizeof(filename), "/proc/%d/cmdline", id); FILE *fp = fopen(filename, "r"); if (fp) { if (fgets(cmdline, sizeof(cmdline), fp)) { cmdline[strcspn(cmdline, "\n")] = '\0'; if (strcmp(packageName, cmdline) == 0) { fclose(fp); closedir(dir); return id; } } fclose(fp); } } } } closedir(dir); return -1; } // 获取模块内存信息(增强权限检查) ModuleInfo get_module_info(int pid, const char *module_name) { ModuleInfo info = {0}; FILE *fp; char line[8192]; char filename[32]; snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); if ((fp = fopen(filename, "r")) == NULL) { perror("打开maps文件失败"); return info; } while (fgets(line, sizeof(line), fp)) { if (strstr(line, module_name)) { uint64_t start, end; char perms[5], offset[17], dev[6], inode[11], pathname[256]; // 增强解析逻辑 if (sscanf(line, "%lx-%lx %4s %16s %5s %10s %255[^\n]", &start, &end, perms, offset, dev, inode, pathname) >= 6) { if (start < end) { if (info.count < 200) { info.ranges[info.count].start_addr = start; info.ranges[info.count].end_addr = end; strncpy(info.ranges[info.count].permissions, perms, 4); info.ranges[info.count].permissions[4] = '\0'; info.count++; } else { printf("警告:模块映射段过多(超过200段),部分段未记录\n"); break; } } } } } fclose(fp); return info; } // 使用ptrace安全写入DWORD int SafeWriteDword(int pid, uint64_t addr, uint32_t value) { // 附加到目标进程 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) { perror("ptrace附加失败"); return -1; } // 等待进程暂停 int status; waitpid(pid, &status, 0); if (!WIFSTOPPED(status)) { perror("进程未暂停"); ptrace(PTRACE_DETACH, pid, NULL, NULL); return -1; } // 逐字写入(避免对齐问题) for (int i = 0; i < sizeof(uint32_t); i++) { uint8_t byte = (value >> (i * 8)) & 0xFF; long data = ptrace(PTRACE_PEEKTEXT, pid, addr + i, NULL); if (data == -1 && errno) { perror("ptrace读取失败"); ptrace(PTRACE_DETACH, pid, NULL, NULL); return -1; } // 修改单个字节 long new_data = (data & ~0xFF) | byte; if (ptrace(PTRACE_POKETEXT, pid, addr + i, new_data) == -1) { perror("ptrace写入失败"); ptrace(PTRACE_DETACH, pid, NULL, NULL); return -1; } } // 分离目标进程 if (ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1) { perror("ptrace分离失败"); return -1; } return 0; } // 使用ptrace安全读取DWORD int SafeReadDword(int pid, uint64_t addr, uint32_t *value) { *value = 0; // 附加到目标进程 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) { perror("ptrace附加失败"); return -1; } // 等待进程暂停 int status; waitpid(pid, &status, 0); if (!WIFSTOPPED(status)) { perror("进程未暂停"); ptrace(PTRACE_DETACH, pid, NULL, NULL); return -1; } // 逐字读取(避免对齐问题) for (int i = 0; i < sizeof(uint32_t); i++) { long data = ptrace(PTRACE_PEEKTEXT, pid, addr + i, NULL); if (data == -1 && errno) { perror("ptrace读取失败"); ptrace(PTRACE_DETACH, pid, NULL, NULL); return -1; } *value |= ((uint32_t)(data & 0xFF)) << (i * 8); } // 分离目标进程 if (ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1) { perror("ptrace分离失败"); return -1; } return 0; } // 使用__builtin___clear_cache刷新缓存 int flush_with_builtin(uint64_t addr, size_t size) { char *start = (char *)(addr & ~(4095ULL)); char *end = start + size; __builtin___clear_cache(start, end); printf("成功: 使用__builtin___clear_cache刷新指令缓存\n"); return 0; } // 五级强刷新机制 int enhanced_flush_cache(uint64_t addr, size_t size) { uint64_t aligned_addr = addr & ~(4095ULL); size_t aligned_size = ((addr + size - aligned_addr + 4095) / 4096) * 4096; #ifdef __aarch64__ // 1. 优先使用__builtin___clear_cache if (flush_with_builtin(aligned_addr, aligned_size) == 0) { return 0; } // 2. 尝试系统调用刷新 const int *syscall_num = cache_flush_syscalls; while (*syscall_num != 0) { int ret_instr = syscall(*syscall_num, aligned_addr, aligned_size, CACHE_TYPE_INSTRUCTION); if (ret_instr == 0) { printf("成功: 使用syscall %d 刷新缓存\n", *syscall_num); return 0; } syscall_num++; } // 3. mprotect内存属性修改方案 void *page_start = (void *)aligned_addr; int pagesize = sysconf(_SC_PAGESIZE); unsigned long page_count = (aligned_size + pagesize - 1) / pagesize; int protection = PROT_READ | PROT_WRITE | PROT_EXEC; if (mprotect(page_start, page_count * pagesize, protection) == 0) { printf("成功: 通过mprotect修改内存保护属性刷新缓存\n"); return 0; } // 4. msync强制同步方案 if (msync((void *)aligned_addr, aligned_size, MS_SYNC | MS_INVALIDATE) == 0) { printf("成功: 使用msync同步刷新缓存\n"); return 0; } // 5. 终极方案:重建内存映射 void *tmp = mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (tmp) { memcpy(tmp, (void *)aligned_addr, aligned_size); munmap((void *)aligned_addr, aligned_size); mmap((void *)aligned_addr, aligned_size, PROT_READ | PROT_EXEC, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0); memcpy((void *)aligned_addr, tmp, aligned_size); munmap(tmp, aligned_size); printf("成功: 通过重建内存映射刷新缓存\n"); return 0; } #endif perror("所有缓存刷新方法均失败"); return -1; } // 暂停目标进程 int pause_process(int pid) { if (kill(pid, SIGSTOP) == -1) { perror("发送SIGSTOP失败"); return -1; } // 等待进程真正停止 int status; waitpid(pid, &status, WUNTRACED); if (!WIFSTOPPED(status)) { perror("进程未正确停止"); return -1; } printf("进程已暂停(PID: %d)\n", pid); return 0; } // 恢复目标进程 int resume_process(int pid) { if (kill(pid, SIGCONT) == -1) { perror("发送SIGCONT失败"); return -1; } printf("进程已恢复运行(PID: %d)\n", pid); return 0; } // 主Hook函数 void hook_il2cpp() { const char *packageName = "com.tencent.tmgp.cf"; const uint64_t HOOK_OFFSET = 0x7EFD168; const uint32_t HOOK_VALUE = 505416143; const uint32_t ORIGINAL_VALUE = 505416142; processInfo.pid = getPID(packageName); if (processInfo.pid <= 0) { printf("获取PID失败\n"); return; } printf("获取到目标进程PID: %d\n", processInfo.pid); ModuleInfo module_info = get_module_info(processInfo.pid, "libil2cpp.so"); if (module_info.count == 0) { printf("获取SO模块地址失败(可能无权限或模块未加载)\n"); return; } // 使用第一个可执行段的起始地址作为模块基址 uint64_t module_base = 0; for (int i = 0; i < module_info.count; i++) { if (strstr(module_info.ranges[i].permissions, "x")) { module_base = module_info.ranges[i].start_addr; break; } } if (module_base == 0) { printf("未找到可执行段,使用第一个段作为基址\n"); module_base = module_info.ranges[0].start_addr; } uint64_t target_addr = module_base + HOOK_OFFSET; printf("\nlibil2cpp.so 模块基址: 0x%016lx\n", module_base); printf("目标Hook地址: 0x%016lx (基址 + 0x%lx)\n", target_addr, HOOK_OFFSET); // 验证目标地址是否在模块范围内且具有写权限 int in_range = 0; int has_write_permission = 0; for (int i = 0; i < module_info.count; i++) { if (target_addr >= module_info.ranges[i].start_addr && target_addr <= module_info.ranges[i].end_addr) { in_range = 1; if (strstr(module_info.ranges[i].permissions, "w")) { has_write_permission = 1; } break; } } if (!in_range) { printf("\n目标地址0x%016lx超出模块范围,退出操作\n", target_addr); return; } if (!has_write_permission) { printf("\n警告:目标地址无写权限,尝试修改内存保护属性\n"); } // 暂停进程进行内存操作 if (pause_process(processInfo.pid) != 0) { printf("暂停进程失败,退出Hook流程\n"); return; } // 读取原始值并验证 uint32_t original_val; if (SafeReadDword(processInfo.pid, target_addr, &original_val) != 0) { printf("读取原始值失败,恢复进程并退出\n"); resume_process(processInfo.pid); return; } printf("原始值: %u (预期: %u)\n", original_val, ORIGINAL_VALUE); if (original_val != ORIGINAL_VALUE) { printf("警告:原始值(%u)与预期值(%u)不匹配,继续操作但结果可能异常\n", original_val, ORIGINAL_VALUE); } // 写入新值 if (SafeWriteDword(processInfo.pid, target_addr, HOOK_VALUE) != 0) { printf("修改失败(可能因内存保护或权限问题),恢复进程并退出\n"); resume_process(processInfo.pid); return; } printf("成功写入新值: %u\n", HOOK_VALUE); // 刷新指令缓存 if (enhanced_flush_cache(target_addr & ~(4095), 4096) != 0) { printf("警告:缓存刷新失败,可能存在执行风险\n"); } // 验证新值 uint32_t new_val; if (SafeReadDword(processInfo.pid, target_addr, &new_val) == 0) { printf("验证修改: 新值 = %u (预期: %u)\n", new_val, HOOK_VALUE); if (new_val == HOOK_VALUE) { printf("\033[32m验证成功:值已修改为预期值\033[0m\n"); } else { printf("\033[31m验证失败:新值(%u)与预期值(%u)不匹配\033[0m\n", new_val, HOOK_VALUE); } } else { printf("验证修改失败(无法读取新值)\n"); } // 恢复进程运行 if (resume_process(processInfo.pid) != 0) { printf("恢复进程失败\n"); return; } printf("进程已恢复运行\n"); // 等待进程稳定 sleep(2); // 验证恢复后的值 uint32_t restored_val; if (SafeReadDword(processInfo.pid, target_addr, &restored_val) == 0) { printf("恢复后的值: %u (预期: %u)\n", restored_val, ORIGINAL_VALUE); if (restored_val == ORIGINAL_VALUE) { printf("\033[32m验证成功:值已恢复为原始值\033[0m\n"); } else { printf("\033[31m验证失败:恢复后的值(%u)与原始值(%u)不匹配\033[0m\n", restored_val, ORIGINAL_VALUE); } } else { printf("验证恢复值失败(可能无权限或地址不可读)\n"); } } int main() { if (getuid() != 0) { printf("需要root权限运行!\n"); return 1; } hook_il2cpp(); return 0; }获取到目标进程PID: 24442 libil2cpp.so 模块基址: 0x0000006f46366000 目标Hook地址: 0x0000006f4e263168 (基址 + 0x7efd168) 警告:目标地址无写权限,尝试修改内存保护属性 进程未正确停止: No child processes 暂停进程失败,退出Hook流程 [进程已结束 - 按回车关闭]修复好完整发给我 确认无任何报错后
最新发布
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值