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

CTF无0x00限制下能否强制GAS生成2字节相对JMP指令?

如何强制GAS生成2字节的JMP rel16指令?

绝对可以搞定这个问题!GAS在32位汇编模式下默认会生成4字节的JMP rel32指令(哪怕偏移量在16位范围内),这就导致高位出现0x00字节,正好踩中CTF shellcode的禁忌。不过我们有两种可靠的方法强制它输出2字节的JMP rel16:

方法1:使用jmpw显式指定16位跳转宽度

GAS支持通过jmpw指令(后缀w代表word,即16位)直接生成2字节的相对跳转。这个指令会明确告诉汇编器生成0xE9 opcode + 16位偏移的组合,不会出现冗余的高位0字节。

示例代码:

shellcode:
    ; 这里放你的主体shellcode代码
    jmpw sc_data  ; 生成2字节的JMP rel16,无0x00字节
    ; 填充至0x514字节,用nop(0x90)填充避免干扰
    times 0x514 - ($ - shellcode) db 0x90
    ; 覆盖全局符号的常量
    dd 0xdeadbeef
sc_data:
    ; 你的数据段,比如字符串等
    db '/bin/sh', 0

方法2:手动编码指令字节(更直接可控)

如果jmpw在某些场景下不生效(比如特定版本的GAS),可以直接手动构造指令的机器码,完全掌控每一个字节:

shellcode:
    ; 手动构造JMP rel16:opcode是0xE9,后跟16位相对偏移
    .byte 0xE9
    ; 计算偏移:目标地址 - (当前地址 + 2),因为JMP指令占2字节,偏移是相对于下一条指令的
    .word sc_data - ($ + 2)
    ; 填充到0x514字节
    times 0x514 - ($ - shellcode) db 0x90
    ; 全局符号覆盖常量
    dd 0xcafebabe
sc_data:
    db '/bin/sh', 0

关键说明

  • GAS默认生成JMP rel32的原因是在32位模式下,它优先使用32位偏移以兼容更大的地址空间,哪怕偏移量很小。显式指定16位宽度就能绕过这个默认行为。
  • 测试时可以用objdump -d查看生成的机器码,确认JMP指令是2字节且没有0x00字节:
    objdump -d -m i386 your_shellcode.o
    
  • 汇编时记得指定32位模式,比如用as -32 -o shellcode.o shellcode.s,避免64位模式下的指令差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:49:12