You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86_64 Linux汇编shellcode写入.text段报错及mprotect使用求助

问题解答

1. 段错误原因确认

你的判断基本正确。现代Linux系统默认启用W^X(写入异或执行)内存保护机制:可执行内存页默认不可写,可写页默认不可执行。如果你的shellcode所在内存页被标记为可执行但不可写,执行mov [rdx+7], al这类写入操作时,必然会触发段错误——这是系统对违反内存权限的直接响应。

2. 能否通过mprotect设置内存页为可写且可执行

完全可以。mprotect系统调用支持修改指定内存区域的权限,只要你能定位到目标内存页的起始地址,且该页属于当前进程空间,就能将其权限设置为PROT_READ | PROT_WRITE | PROT_EXEC,从而同时支持写入和执行操作。

3. 汇编中获取内存页起始地址的方法

x86_64 Linux下内存页默认大小为4KB(可通过getpagesize系统调用确认),要获取shellcode所在页的起始地址,只需将当前指令的地址对齐到页边界即可,具体步骤如下:

  • 用call指令获取当前指令地址:执行call get_current_addr后,返回地址会被压入栈中,在get_current_addr标签处通过pop rbx就能将当前指令的地址存入rbx寄存器。
  • 用页掩码对齐地址:执行and rbx, 0xfffffffffffff000(4KB页的掩码为~0xfff,64位下对应值为0xfffffffffffff000),即可将rbx中的地址对齐到当前页的起始位置。

示例汇编片段

; 获取当前shellcode所在页的起始地址
call get_current_addr
get_current_addr:
    pop rbx                 ; rbx = 当前指令的内存地址
    and rbx, 0xfffffffffffff000  ; 对齐到4KB页边界

; 调用mprotect修改内存权限
mov rdi, rbx               ; 参数1:页起始地址
mov rsi, 4096              ; 参数2:修改的内存大小(整页)
mov rdx, 7                 ; 参数3:PROT_READ|PROT_WRITE|PROT_EXEC(7=1|2|4)
mov rax, 10                ; x86_64 Linux下mprotect的系统调用号为10
syscall

调用mprotect完成权限修改后,你就可以安全地向该内存区域写入数据了。需要注意的是,部分系统可能开启了SMAP/SMEP等额外保护机制,但在常规漏洞研究环境中,上述方法足以解决问题。

内容的提问来源于stack exchange,提问作者Tom BARAT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 18:53:16