用 sysctl/proc 等枚举或 remote 请求得到 PID
例如如果通过进程名获取进程 PID:
调用一个内部函数 GetAllInfosMatchingName:
内部会调用 sysctl,从内核中枚举出所有进程(CTL_KERN, KERN_PROC, KERN_PROC_ALL)。 --》DNBGetAllInfos
然后遍历列表,把 kp_proc.p_comm(进程名字段)与 name 比较。
把所有匹配的结果放入 matching_proc_infos
基本mach要走的基本流程点
本文在lldb方面就不再过多赘述--例如MachTask::TaskPortForProcessID这一块
最后会走 MachProcess::AttachForDebug(),这个实现会使用 ptrace(如 PT_ATTACHEXC)。
路径如下
从这一步来说lldb就已经借用了ptrace,如果有如下反调试代码
会设置 exception ports(Mach)来接收 kernel 发来的异常;
1.保存原有异常端口调用 task_get_exception_ports(...) 把当前的端口、行为、flavor 等读出来备份
2.恢复/写回异常端口PortInfo::Restore() 里循环调用 task_set_exception_ports(...) 把之前保存的端口逐项写回。
如果这时候就已经发生了EXC_SOFT_SIGNAL
lldb在异常路径中会去调用 ptrace 更新信号(PT_THUPDATE)
debugserver 用 PT_THUPDATE 把信号补到内核的 signal ,来保证把 Mach 异常与 UNIX 信号对齐
拦截异常 →(可选)通过 PT_THUPDATE 注入/抑制信号 → mach_msg 回复恢复线程,控制调试行为,又保持进程的 UNIX 信号语义不变
和lldb操作一样,用 sysctl/proc 等枚举或 remote 请求得到 PID
task_for_pid(self, pid, &task) 拿到目标 task。
mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, &exc_port) 分配一个异常接收端口;
mach_port_insert_right(self, exc_port, exc_port, MACH_MSG_TYPE_MAKE_SEND) 插入发送权;
task_set_exception_ports(task, 0x1BFE, exc_port, EXCEPTION_DEFAULT(1), MACHINE_THREAD_STATE(6)) 把所有重要异常(含断点/观察点/单步/崩溃等)的投递,绑定到创建的 exc_port。
mach_msg_server(exc_server, 0x800, exc_port, 0):用 XNU 自带的 exc_server MIG 处理例程在异常端口上跑服务。
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!