Apple M1平台ARM64代码注入其他进程触发EXC_BAD_ACCESS问题
ARM64进程注入时_pthread_set_self处EXC_BAD_ACCESS问题分析
核心原因推测
- 栈帧上下文无效:注入自身进程时,payload复用当前线程的合法栈帧,x29(帧指针)指向系统维护的有效栈结构,因此
[x29, #0x18]能正确读取thread_id。但注入其他进程时,你分配的是独立远程栈,若未正确初始化x29使其指向合法栈帧基地址,就会导致偏移访问到未映射/无权限的内存区域(比如你遇到的0x10005e85c)。ARM64要求x29必须严格指向栈帧固定位置,否则偏移访问必然出错。 - Thread_id存储位置与偏移不匹配:你在payload中可能将thread_id存在栈的某个位置,但注入目标进程时,栈的基地址和自身进程测试的布局不同,导致
[x29, #0x18]对应的地址并非存放thread_id的位置,反而指向非法内存。 - 远程线程上下文配置错误:创建远程线程时,若未正确设置sp(栈指针)和x29的初始值,会导致payload执行时栈结构混乱。比如sp未指向你分配的栈顶部(ARM64栈向下生长),x29未关联到sp的合法位置,都会引发栈访问错误。
- ASLR地址空间差异:自身进程与目标进程的ASLR布局完全独立,你测试时依赖的栈偏移或内存地址,在目标进程中可能属于未映射区域,硬编码偏移必然导致访问失败。
排查与修复建议
- 强制初始化栈帧结构:在payload执行最开始,手动构建合法ARM64栈帧:将sp设置为你分配的远程栈顶部,再把x29初始化为sp的值,确保后续基于x29的偏移访问都落在你分配的栈内存范围内。
- 避免基于x29的硬编码偏移:不要依赖
[x29, #0x18]这种固定偏移读取thread_id,改为直接将thread_id加载到x0寄存器(比如mov x0, #thread_id_value或从sp的相对偏移读取),绕开栈帧依赖。 - 验证远程栈地址范围:注入前打印你分配的远程栈的起始和结束地址,崩溃时检查
[x29, #0x18]对应的地址是否在这个范围内——如果不在,说明栈帧偏移计算完全错误。 - 检查远程线程上下文:确认创建远程线程时,传递的上下文结构体中,sp和x29被正确设置为你分配的栈的相关地址,而非默认值或随机值。
内容的提问来源于stack exchange,提问作者Brandon
相关产品推荐
相关产品推荐

