pt_regs结构

struct pt_regs {
long ebx;                  //可执行文件路径的指针(regs.ebx中
long ecx;                  //命令行参数的指针(regs.ecx中)
long edx;                  //环境变量的指针(regs.edx中)。
long esi;
long edi;
long ebp;
long eax;
int xds;
int xes;
long orig_eax;
long eip;
int xcs;
long eflags;
long esp;
int xss;
};
该 参数描述了在执行该系统调用时,用户态下的CPU寄存器在核心态的栈中的保存情况。通过这个参数,sys_execve能获得保存在用户空间的以下信息: 可执行文件路径的指针(regs.ebx中)、命令行参数的指针(regs.ecx中)和环境变量的指针(regs.edx中)。

/* this struct defines the way the registers are stored on the 
24    stack during a system call. */
25 
26 struct pt_regs {
27         long ebx;
28         long ecx;
29         long edx;
30         long esi;
31         long edi;
32         long ebp;
33         long eax;
34         int  xds;
35         int  xes;
36         long orig_eax;
37         long eip;
38         int  xcs;
39         long eflags;
40         long esp;
41         int  xss;
42 };

《understanding the linux kernel》中说 struct pt_regs中前9个是存放通过SAVE_ALL压入的寄存器值。 orig_eax存放的是IRQ number. 后面的几个是处理器自动压入的寄存器值。

我不明白的是: xds xes xcs xss等是什么寄存器? 他们与edx ecs 等有什么区别? 而且类型还不一样。
哪位能解释一下。

答:是段寄存器,类型其实是一样的

保存断点现场:在内核栈中保存中断处理程序将要用到的所有cpu寄存器的内容叫保护断点现场。这时调用宏SAVE_ALL来完成的。

#define SAVE_ALL

 cld;

pushl %es;

pushl %ds;

pushl %eax;

pushl %ebp;

pushl %edi;

pushl %esi;

pushl %edx;

pushl %ecx;

pushl %ebx;

movl $(__KERNEL_DS),%edx;

movl %dx,%ds;

movl %dx,%es;

注意到这个宏没有保存EFLAGS,CS,EIP,SS和ESP寄存器,原因是这些寄存器在CPU响应中断是已被cpu自动保存了。在宏的最后,把内核数据段的选择符装入ds和es段寄存器

<script>window._bd_share_config={"common":{"bdsnskey":{},"bdtext":"","bdmini":"2","bdminilist":false,"bdpic":"","bdstyle":"0","bdsize":"16"},"share":{}};with(document)0[(getelementsbytagname('head')[0]||body).appendchild(createelement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new date()/36e5)];</script>
阅读(220) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
#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> // 修复1: 正确定义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 // 修复2: 正确定义调试寄存器状态结构struct user_hwdebug_state { uint32_t dbg_info; // 调试信息 uint32_t pad; // 填充 struct { uint64_t addr; // 地址寄存器 uint64_t ctrl; // 控制寄存器 } dbg_regs[16]; // 最大16个断点 }; // 获取线程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) { perror("opendir failed"); return 0; } struct dirent *entry; while ((entry = readdir(dir)) != NULL) { if (count >= max_threads) break; 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) { perror("【错误】附加主进程失败"); return false; } int status; if (waitpid(pid, &status, 0) < 0) { perror("【错误】等待主进程失败"); return false; } pid_t threads[64]; int thread_count = get_threads(pid, threads, 64); if (thread_count == 0) { fprintf(stderr, "【警告】未找到任何线程\n"); 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) { perror("【错误】附加子线程失败"); continue; } if (waitpid(tid, &status, 0) < 0) { perror("【错误】等待子线程失败"); ptrace(PTRACE_DETACH, tid, NULL, NULL); continue; } printf("【已附加线程】tid=%d\n", tid); } return true; } // 修复3: 正确设置硬件断点 bool set_hw_breakpoint(pid_t pid, pid_t thread_id, 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, thread_id, nt_type, &iov) < 0) { perror("【错误】PTRACE_GETREGSET获取失败"); 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) { fprintf(stderr, "【错误】线程%d无可用硬件断点\n", thread_id); return false; } // 设置控制寄存器 uint64_t ctrl_value = 0; if (type == 0) { // 执行断点 ctrl_value = (1 << 0) | // 启用 (0b01 << 8); // 用户空间(EL0) } else { // 观察点 // 计算BAS掩码 uint64_t bas = 0; switch (len) { case 1: bas = 0x1; break; case 2: bas = 0x3; break; case 4: bas = 0xF; break; case 8: bas = 0xFF; break; default: fprintf(stderr, "【错误】无效长度: %d\n", len); return false; } 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); } // 设置地址和控制寄存器 dbg_regs.dbg_regs[slot].addr = addr; dbg_regs.dbg_regs[slot].ctrl = ctrl_value; // 应用设置 if (ptrace(PTRACE_SETREGSET, thread_id, nt_type, &iov) < 0) { perror("【错误】PTRACE_SETREGSET设置失败"); return false; } printf("【线程%d断点设置成功】 地址:0x%llx 类型:%s 长度:%d字节\n", thread_id, (unsigned long long)addr, type == 0 ? "执行" : type == 1 ? "读" : type == 2 ? "写" : "读写", len); return true; } // 清除所有硬件断点 bool clear_all_hw_breakpoints(pid_t thread_id) { struct user_hwdebug_state dbg_regs; struct iovec iov = { .iov_base = &dbg_regs, .iov_len = sizeof(dbg_regs) }; // 清除执行断点 memset(&dbg_regs, 0, sizeof(dbg_regs)); if (ptrace(PTRACE_SETREGSET, thread_id, NT_ARM_HW_BREAK, &iov) < 0) { perror("【错误】清除执行断点失败"); } // 清除观察点 memset(&dbg_regs, 0, sizeof(dbg_regs)); if (ptrace(PTRACE_SETREGSET, thread_id, NT_ARM_HW_WATCH, &iov) < 0) { perror("【错误】清除观察点失败"); return false; } return true; } // 获取寄存器信息 bool get_registers(pid_t tid, struct user_pt_regs *regs) { struct iovec iov = { .iov_base = regs, .iov_len = sizeof(*regs) }; if (ptrace(PTRACE_GETREGSET, tid, NT_PRSTATUS, &iov) < 0) { perror("【错误】PTRACE_GETREGSET获取失败"); return false; } return true; } int main() { pid_t target_pid; printf("【输入目标进程PID】\n"); scanf("%d", &target_pid); if (geteuid() != 0) { fprintf(stderr, "【错误】需要root权限\n"); return 1; } if (!attach_to_process(target_pid)) { fprintf(stderr, "【致命错误】无法附加目标进程\n"); return 1; } uintptr_t bp_addr; printf("【输入断点地址(十六进制)】\n"); scanf("%llx", (unsigned long long *)&bp_addr); int len, type; printf("【选择断点类型(0:执行,1:读,2:写,3:读写)】\n"); scanf("%d", &type); if (type != 0) { printf("【输入断点长度(1,2,4,8字节)】\n"); scanf("%d", &len); // 检查长度有效性 if (len != 1 && len != 2 && len != 4 && len != 8) { fprintf(stderr, "【错误】无效长度,使用默认值4字节\n"); len = 4; } } else { len = 4; // 执行断点长度固定 } pid_t threads[64]; int thread_count = get_threads(target_pid, threads, 64); for (int i = 0; i < thread_count; i++) { pid_t tid = threads[i]; printf("【处理线程】tid=%d\n", tid); if (!set_hw_breakpoint(target_pid, tid, bp_addr, len, type)) { fprintf(stderr, "【警告】线程%d断点设置失败\n", tid); continue; } } printf("【恢复进程执行...】\n"); if (ptrace(PTRACE_CONT, target_pid, NULL, NULL) < 0) { perror("【错误】恢复执行失败"); return 1; } printf("【等待断点触发...】\n"); int status; pid_t wait_pid = waitpid(-1, &status, 0); bool breakpoint_hit = false; for (int i = 0; i < thread_count; i++) { pid_t tid = threads[i]; 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) { perror("【错误】获取调试寄存器失败"); continue; } for (int j = 0; j < 16; j++) { if (dbg_regs.dbg_regs[j].addr == bp_addr && (dbg_regs.dbg_regs[j].ctrl & 0x1)) { breakpoint_hit = true; printf("\n【断点命中!】\n"); printf("触发线程:tid=%d\n", tid); printf("命中地址:0x%llx\n", (unsigned long long)bp_addr); const char *type_str = type == 0 ? "执行" : type == 1 ? "读" : type == 2 ? "写" : "读写"; printf("类型:%s | 长度:%d字节\n", type_str, len); struct user_pt_regs regs; if (get_registers(tid, &regs)) { printf("\n寄存器状态:\n"); printf("PC=0x%llx (程序计数器)\n", (unsigned long long)regs.pc); printf("LR=0x%llx (链接寄存器x30)\n", (unsigned long long)regs.regs[30]); printf("SP=0x%llx (栈指针sp)\n", (unsigned long long)regs.sp); printf("X0=0x%llx, X1=0x%llx, X2=0x%llx, X3=0x%llx\n", (unsigned long long)regs.regs[0], (unsigned long long)regs.regs[1], (unsigned long long)regs.regs[2], (unsigned long long)regs.regs[3]); } break; } } if (breakpoint_hit) break; } if (!breakpoint_hit) { printf("\n【未检测到断点命中,恢复进程执行...】\n"); ptrace(PTRACE_CONT, target_pid, NULL, NULL); } printf("\n【清理断点...】\n"); for (int i = 0; i < thread_count; i++) { pid_t tid = threads[i]; if (!clear_all_hw_breakpoints(tid)) { fprintf(stderr, "【警告】线程%d断点清除失败\n", tid); } else { printf("【已清除线程】tid=%d的断点\n", tid); } } printf("\n【分离调试会话...】\n"); for (int i = 0; i < thread_count; i++) { pid_t tid = threads[i]; if (ptrace(PTRACE_DETACH, tid, NULL, NULL) < 0) { perror("【错误】分离线程失败"); } } return 0; } Android NDK: src/ptrace断点.cpp.bak [arm64-v8a] Compile++ : 无痕hook.sh <= ptrace断点.cpp jni/src/ptrace断点.cpp:25: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 { ^ 1 error 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 修复好报错问题完整发给我
07-14
asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address) { unsigned long vec; struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; vm_fault_t fault; unsigned int flags = FAULT_FLAG_DEFAULT; tsk = current; mm = tsk->mm; vec = lookup_exception_vector(); if (unlikely(fault_in_kernel_space(address))) { if (vmalloc_fault(address) >= 0) return; if (kprobe_page_fault(regs, vec)) return; bad_area_nosemaphore(regs, error_code, address); return; } if (unlikely(kprobe_page_fault(regs, vec))) return; if ((regs->sr & SR_IMASK) != SR_IMASK) local_irq_enable(); perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); if (unlikely(faulthandler_disabled() || !mm)) { bad_area_nosemaphore(regs, error_code, address); return; } retry: vma = lock_mm_and_find_vma(mm, address, regs); if (unlikely(!vma)) { bad_area_nosemaphore(regs, error_code, address); return; } if (unlikely(access_error(error_code, vma))) { bad_area_access_error(regs, error_code, address); return; } set_thread_fault_code(error_code); if (user_mode(regs)) flags |= FAULT_FLAG_USER; if (error_code & FAULT_CODE_WRITE) flags |= FAULT_FLAG_WRITE; fault = handle_mm_fault(vma, address, flags, regs); if (unlikely(fault & (VM_FAULT_RETRY | VM_FAULT_ERROR))) if (mm_fault_error(regs, error_code, address, fault)) return; if (fault & VM_FAULT_COMPLETED) return; if (fault & VM_FAULT_RETRY) { flags |= FAULT_FLAG_TRIED; goto retry; } mmap_read_unlock(mm); }解释上面代码, 并说明哪些是处理用户空间缺页的方法
03-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

helloworddm

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值