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

NASM终端输入读取问题求助:超长输入触发Shell执行意外命令

NASM汇编输入溢出导致Shell执行命令的Bug修复

问题描述

我写了一段NASM汇编代码读取终端输入并输出结果,运行基本正常,但有严重bug:输入长度超过10字符时,超出部分会被Shell当作命令执行。比如输入“012345678rm mycode”后,“rm mycode”会被执行,导致程序文件mycode被删除。

附原代码:

section .data
yourinputis db "your input is =",0
len equ $ - yourinputis

section .bss
msginput    resb    10

section .text
global _start


_start:
    mov eax,3 ;read syscall
    mov ebx,2
    mov ecx,msginput
    mov edx,9 ; I don't know that is correct?
    int 80h

    mov eax,4 ;write syscall
    mov ebx,1
    mov ecx,yourinputis
    mov edx,len
    int 80h

    mov eax,4 ;write syscall
    mov ebx,1
    mov ecx,msginput
    mov edx,10
    int 80h

exit:
    mov eax,1 ;exit syscall
    xor ebx,ebx
    int 80h

问题原因

这个bug的核心是read系统调用未处理输入缓冲区溢出,残留的输入字符会被后续Shell拾取执行。你的代码只读取9个字符,输入超出的部分会留在终端的输入缓冲区里,程序退出后Shell会自动读取这些剩余内容,当作新命令执行。

修复方案

1. 正确处理read的返回值

read系统调用结束后,eax会返回实际读取的字节数(包含换行符),用这个值控制输出长度,避免输出未初始化的内存。

2. 清理剩余输入字符

如果输入长度超过缓冲区大小,循环读取剩余字符并丢弃,防止Shell获取这些内容。

3. 合理设置缓冲区读取长度

msginput申请了10字节,可将read的edx设为9,留一个字节存储终止符,避免输出乱码。

修改后的代码

section .data
yourinputis db "your input is =",0
len equ $ - yourinputis
newline db 0xA ; 换行符,用于输出后换行

section .bss
msginput    resb    10

section .text
global _start


_start:
    ; 读取输入,最多9个字符,留1字节存终止符
    mov eax,3          ; read系统调用号
    mov ebx,0          ; 标准输入(用0代替2,2是标准错误,终端虽能读但0更标准)
    mov ecx,msginput
    mov edx,9
    int 80h

    cmp eax,0          ; 判断是否读取失败或EOF
    jle exit

    ; 检查是否读取到换行符,没读到则说明输入过长,清理缓冲区
    mov esi, eax
    dec esi
    cmp byte [msginput + esi], 0xA
    jz input_ok

clear_buffer:
    ; 循环读取剩余字符直到换行或EOF
    mov eax,3
    mov ebx,0
    mov ecx,msginput ; 临时用缓冲区存丢弃的字符
    mov edx,1
    int 80h
    cmp eax,0
    jle input_ok
    cmp byte [msginput], 0xA
    jnz clear_buffer

input_ok:
    ; 添加字符串终止符,避免输出乱码
    mov byte [msginput + eax], 0

    ; 输出提示文本
    mov eax,4          ; write系统调用号
    mov ebx,1          ; 标准输出
    mov ecx,yourinputis
    mov edx,len
    int 80h

    ; 输出读取到的输入
    mov eax,4
    mov ebx,1
    mov ecx,msginput
    mov edx,eax        ; 用read返回的实际读取长度控制输出
    int 80h

    ; 输出换行符
    mov eax,4
    mov ebx,1
    mov ecx,newline
    mov edx,1
    int 80h

exit:
    mov eax,1          ; exit系统调用号
    xor ebx,ebx
    int 80h

关键修改说明

  • 将标准输入的文件描述符从2改为0,2是标准错误流,0才是标准输入的正确描述符。
  • 读取后检查是否读到换行符,若没读到则循环清理缓冲区直到读完剩余输入。
  • 用read返回的实际长度控制输出,避免输出多余的未初始化内存。
  • 添加了换行符输出,让结果更整洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 22:26:26