#define _GNU_SOURCE
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <elf.h>
#include <sys/uio.h>
#include <sys/stat.h>
#include <dirent.h>
#include <asm/ptrace.h>
#include <android/log.h> // Android日志支持
// 修复1: 避免结构体重定义
#ifndef USER_HWDEBUG_STATE_DEFINED
#define USER_HWDEBUG_STATE_DEFINED
// ARM64硬件调试寄存器定义
#ifndef NT_ARM_HW_BREAK
#define NT_ARM_HW_BREAK 0x402 // 执行断点寄存器集
#endif
#ifndef NT_ARM_HW_WATCH
#define NT_ARM_HW_WATCH 0x403 // 观察点寄存器集
#endif
// ARM64硬件调试状态结构体
struct user_hwdebug_state {
uint32_t dbg_info; // 调试信息字段
uint32_t pad; // 填充对齐
struct {
uint64_t addr; // 断点地址寄存器
uint64_t ctrl; // 控制寄存器
} dbg_regs[16]; // 最大16个硬件断点槽位
};
#endif
// 获取进程的所有线程ID
int get_threads(pid_t pid, pid_t *threads, int max_threads) {
char path[64];
int count = 0;
snprintf(path, sizeof(path), "/proc/%d/task", pid);
DIR *dir = opendir(path);
if (!dir) {
__android_log_print(ANDROID_LOG_ERROR, "HWBP", "打开/proc失败: %s", strerror(errno));
return 0;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL && count < max_threads) {
if (entry->d_type == DT_DIR &&
strcmp(entry->d_name, ".") != 0 &&
strcmp(entry->d_name, "..") != 0) {
threads[count++] = atoi(entry->d_name);
}
}
closedir(dir);
return count;
}
// 附加到目标进程及其所有线程
bool attach_to_process(pid_t pid) {
// 附加主进程
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
__android_log_print(ANDROID_LOG_ERROR, "HWBP", "附加主进程失败: %s", strerror(errno));
return false;
}
// 等待主进程停止
int status;
if (waitpid(pid, &status, 0) < 0 || !WIFSTOPPED(status)) {
__android_log_print(ANDROID_LOG_ERROR, "HWBP", "等待主进程失败");
return false;
}
// 获取所有线程
pid_t threads[64];
int thread_count = get_threads(pid, threads, 64);
if (thread_count == 0) {
__android_log_print(ANDROID_LOG_WARN, "HWBP", "未找到任何线程");
return false;
}
// 附加所有线程
for (int i = 0; i < thread_count; i++) {
pid_t tid = threads[i];
if (tid == pid) continue; // 跳过主线程
if (ptrace(PTRACE_ATTACH, tid, NULL, NULL) < 0) {
__android_log_print(ANDROID_LOG_ERROR, "HWBP", "附加线程%d失败: %s", tid, strerror(errno));
continue;
}
if (waitpid(tid, &status, 0) < 0 || !WIFSTOPPED(status)) {
__android_log_print(ANDROID_LOG_ERROR, "HWBP", "等待线程%d失败", tid);
ptrace(PTRACE_DETACH, tid, NULL, NULL);
continue;
}
__android_log_print(ANDROID_LOG_INFO, "HWBP", "已附加线程: %d", tid);
}
return true;
}
// 设置ARM64硬件断点
bool set_hw_breakpoint(pid_t tid, uintptr_t addr, int len, int type) {
// 选择寄存器集类型
int nt_type = (type == 0) ? NT_ARM_HW_BREAK : NT_ARM_HW_WATCH;
struct user_hwdebug_state dbg_regs;
struct iovec iov = { .iov_base = &dbg_regs, .iov_len = sizeof(dbg_regs) };
// 获取当前调试寄存器状态
if (ptrace(PTRACE_GETREGSET, tid, nt_type, &iov) < 0) {
__android_log_print(ANDROID_LOG_ERROR, "HWBP", "获取寄存器集失败: %s", strerror(errno));
return false;
}
// 查找空闲断点槽位
int slot = -1;
for (int i = 0; i < 16; i++) {
if (dbg_regs.dbg_regs[i].addr == 0) {
slot = i;
break;
}
}
if (slot == -1) {
__android_log_print(ANDROID_LOG_ERROR, "HWBP", "线程%d无可用断点槽位", tid);
return false;
}
// 设置控制寄存器值
uint64_t ctrl_value = 0;
if (type == 0) { // 执行断点
// 启用位(bit0) + 用户空间权限(EL0, bits[9:8]=0b01)
ctrl_value = (1 << 0) | (0b01 << 8);
} else { // 观察点
// 计算BAS掩码 (字节选择)
uint64_t bas = 0;
switch (len) {
case 1: bas = 0x1; break; // 1字节: 0b0001
case 2: bas = 0x3; break; // 2字节: 0b0011
case 4: bas = 0xF; break; // 4字节: 0b1111
case 8: bas = 0xFF; break; // 8字节: 0b11111111
default:
__android_log_print(ANDROID_LOG_ERROR, "HWBP", "无效长度%d,使用4字节", len);
bas = 0xF;
}
// 基础设置
ctrl_value = (1 << 0) | // 启用
(0b01 << 8); // 用户空间(EL0)
// 设置访问类型
if (type == 1) { // 读
ctrl_value |= (0b01 << 3); // Load
} else if (type == 2) { // 写
ctrl_value |= (0b10 << 3); // Store
} else if (type == 3) { // 读写
ctrl_value |= (0b11 << 3); // Load/Store
}
// 设置长度(BAS)
ctrl_value |= (bas << 16); // BAS位置[23:16]
}
// 设置断点地址和控制值
dbg_regs.dbg_regs[slot].addr = addr;
dbg_regs.dbg_regs[slot].ctrl = ctrl_value;
// 应用设置到目标线程
if (ptrace(PTRACE_SETREGSET, tid, nt_type, &iov) < 0) {
__android_log_print(ANDROID_LOG_ERROR, "HWBP", "设置寄存器集失败: %s", strerror(errno));
return false;
}
__android_log_print(ANDROID_LOG_INFO, "HWBP",
"线程%d: 地址=0x%llx, 类型=%s, 长度=%d字节",
tid, (unsigned long long)addr,
type == 0 ? "执行" : type == 1 ? "读" : type == 2 ? "写" : "读写",
len);
return true;
}
// 主调试函数
void debug_process(pid_t target_pid, uintptr_t bp_addr, int bp_type, int bp_len) {
// 附加到目标进程
if (!attach_to_process(target_pid)) {
__android_log_print(ANDROID_LOG_ERROR, "HWBP", "无法附加到进程%d", target_pid);
return;
}
// 获取所有线程
pid_t threads[64];
int thread_count = get_threads(target_pid, threads, 64);
// 为所有线程设置断点
for (int i = 0; i < thread_count; i++) {
if (!set_hw_breakpoint(threads[i], bp_addr, bp_len, bp_type)) {
__android_log_print(ANDROID_LOG_WARN, "HWBP", "线程%d断点设置失败", threads[i]);
}
}
// 恢复进程执行
for (int i = 0; i < thread_count; i++) {
ptrace(PTRACE_CONT, threads[i], NULL, NULL);
}
__android_log_print(ANDROID_LOG_INFO, "HWBP", "进程恢复执行");
// 等待断点触发
int status;
pid_t hit_tid = waitpid(-1, &status, 0);
if (hit_tid > 0 && WIFSTOPPED(status)) {
__android_log_print(ANDROID_LOG_INFO, "HWBP", "断点命中! 线程ID=%d", hit_tid);
// 获取寄存器状态
struct user_pt_regs regs;
struct iovec iov = { .iov_base = ®s, .iov_len = sizeof(regs) };
if (ptrace(PTRACE_GETREGSET, hit_tid, NT_PRSTATUS, &iov) == 0) {
__android_log_print(ANDROID_LOG_INFO, "HWBP", "PC=0x%llx", (unsigned long long)regs.pc);
__android_log_print(ANDROID_LOG_INFO, "HWBP", "LR=0x%llx", (unsigned long long)regs.regs[30]);
}
}
// 清理并分离
for (int i = 0; i < thread_count; i++) {
ptrace(PTRACE_DETACH, threads[i], NULL, NULL);
}
__android_log_print(ANDROID_LOG_INFO, "HWBP", "调试会话结束");
}
// JNI入口函数
JNIEXPORT void JNICALL
Java_com_example_debugtool_Debugger_nativeSetHardwareBreakpoint(
JNIEnv *env,
jobject thiz,
jint pid,
jlong address,
jint type,
jint length) {
// 检查权限
if (geteuid() != 0) {
__android_log_print(ANDROID_LOG_ERROR, "HWBP", "需要root权限");
return;
}
// 启动调试
debug_process((pid_t)pid, (uintptr_t)address, type, length);
}报错问题:Android NDK: src/ptrace断点.cpp.bak
[arm64-v8a] Compile++ : 无痕hook.sh <= ptrace断点.cpp
jni/src/ptrace断点.cpp:30:8: error: redefinition of
'user_hwdebug_state'
struct user_hwdebug_state {
^
/data/data/com.aide.ui.mgai/no_backup/ndksupport-1710240003/android-ndk-aide/sysroot/usr/include/aarch64-linux-android/asm/ptrace.h:61:8: note:
previous definition is here
struct user_hwdebug_state {
^
jni/src/ptrace断点.cpp:240:1: error: unknown type name
'JNIEXPORT'
JNIEXPORT void JNICALL
^
jni/src/ptrace断点.cpp:240:11: error: expected
unqualified-id
JNIEXPORT void JNICALL
^
3 errors generated.
make: *** [/data/data/com.aide.ui.mgai/no_backup/ndksupport-1710240003/android-ndk-aide/build/core/build-binary.mk:530: obj/local/arm64-v8a/objs/无痕hook.sh/src/ptrace 断点.o] Error 1帮我彻底修复好完整发给我