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

编写用于syscall 59的NASM汇编char*数组时遇命令未找到问题

64位NASM汇编执行/bin/bash -c "echo hello; ls -la"的问题

我尝试编写64位NASM汇编程序,启动时执行命令:/bin/bash -c "echo hello; ls -la",当前的汇编代码如下:

section .text
  global _start
    _start:
        BITS 64
        jmp short two
    one:
        pop rbx

        mov [rbx+34], rbx
        xor al, al
        mov [rbx+9],  al
        mov [rbx+12], al
        mov [rbx+33], al

        xor rdx, rdx
        mov [rbx+66], rdx

        mov rcx, rbx
        add rcx, 10
        mov [rbx+42], rcx

        add rcx, 3
        mov [rbx+50], rcx

        add rcx, 53
        mov [rbx+58], rcx

        mov rdi, rbx
        lea rsi, [rbx+34]
        mov rax, 59
        syscall
     two:
        call one
        db '/bin/bash', 0xFF
        db '-c', 0xFF
        db '"echo hello; ls -la"', 0xFF
        db 'AAAAAAAA'
        db 'BBBBBBBB'
        db 'CCCCCCCC'
        db 'DDDDDDDD'
        db 'FFFFFFFF'

作为汇编新手,我的理解是只需将多个指针连续存放在内存中,因此把实际参数的指针存入占位的AAAAAAAA至FFFFFFFF内存区域,并在syscall前将首个引用地址移入rsi。但程序运行报错,结束时rsi指向0x4000e9,对应的内存数据如下:

0x4000c7:   0x2f    0x62    0x69    0x6e    0x2f    0x62    0x61    0x73
0x4000cf:   0x68    0x00    0x2d    0x63    0x00    0x22    0x65    0x63
0x4000d7:   0x68    0x6f    0x20    0x68    0x65    0x6c    0x6c    0x6f
0x4000df:   0x3b    0x20    0x6c    0x73    0x20    0x2d    0x6c    0x61
0x4000e7:   0x22    0x00    0xc7    0x00    0x40    0x00    0x00    0x00
0x4000ef:   0x00    0x00    0xd1    0x00    0x40    0x00    0x00    0x00
0x4000f7:   0x00    0x00    0xd4    0x00    0x40    0x00    0x00    0x00
0x4000ff:   0x00    0x00    0x09    0x01    0x40    0x00    0x00    0x00
0x400107:   0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00

gdb猜测的参数如下:

Guessed arguments:
arg[0]: 0x4000c7 ("/bin/bash")
arg[1]: 0x4000e9 --> 0x4000c7 ("/bin/bash")
arg[2]: 0x0 
arg[3]: 0x400109 --> 0x0 

程序运行时的错误信息:

: echo hello; ls -la: command not found

问题根源

  1. 字符串多余双引号:-c参数不需要外层双引号,你在字符串中加入的"会被bash当成命令的一部分,导致它尝试执行"echo这个不存在的命令。
  2. argv数组构造错误:execve要求argv数组以NULL结尾,你代码中给最后一个元素设置了无效指针,而非0,导致bash收到错误的参数列表。
  3. 指针计算失误:构造第三个参数指针时错误地给rcx加了53,这完全偏离了目标字符串的起始地址。

修正后的代码

section .text
  global _start
_start:
    BITS 64
    jmp short two
one:
    pop rbx                 ; rbx指向字符串起始位置

    ; 将各字符串的终止符替换为0(Linux C风格字符串要求)
    xor al, al
    mov [rbx+9], al         ; /bin/bash的终止符(共9字节)
    mov [rbx+12], al        ; -c的终止符(/bin/bash+终止符共10字节,-c占2字节)
    mov [rbx+33], al        ; echo hello; ls -la的终止符(起始于rbx+13,长度20)

    ; 构造argv数组:[&"/bin/bash", &"-c", &"echo hello; ls -la", NULL]
    mov [rbx+34], rbx       ; argv[0] = /bin/bash的地址
    mov rcx, rbx
    add rcx, 10             ; rcx指向"-c"的起始地址
    mov [rbx+42], rcx       ; argv[1] = -c的地址
    add rcx, 3              ; rcx指向命令字符串起始地址(-c+终止符共3字节)
    mov [rbx+50], rcx       ; argv[2] = 命令字符串地址
    xor rdx, rdx
    mov [rbx+58], rdx       ; argv[3] = NULL,数组终止

    ; 调用execve系统调用
    mov rdi, rbx            ; rdi = 程序路径地址
    lea rsi, [rbx+34]       ; rsi = argv数组地址
    xor rdx, rdx            ; rdx = envp(设为NULL)
    mov rax, 59             ; execve的系统调用号
    syscall
two:
    call one
    db '/bin/bash', 0xFF
    db '-c', 0xFF
    db 'echo hello; ls -la', 0xFF
    ; argv数组占位空间(4个8字节指针,共32字节)
    db 'AAAAAAAA'
    db 'BBBBBBBB'
    db 'CCCCCCCC'
    db 'DDDDDDDD'

修正点说明

  • 移除命令字符串的外层双引号,直接传递echo hello; ls -la作为-c的参数。
  • 将argv数组最后一个元素设为NULL,确保参数列表正确终止。
  • 修正第三个参数的指针计算,指向命令字符串的正确起始位置。
  • 将envp参数设为NULL,让bash继承当前环境变量。

运行修正后的代码即可正确执行目标命令,输出hello和当前目录的文件列表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:45:55