x86_64 Linux汇编获取argv[1]时尾部出现多余bash内容求助
问题:x86_64汇编获取argv[1]后输出尾部附带多余内容
在x86_64 Linux环境下用汇编编写程序获取argv[1]的值,输出时尾部会附加多余的bash相关内容。目前仅能通过减少预留字节临时消除,但argv[1]是动态值,无法固定长度。
原汇编代码
bits 64 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MACROS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %define SYS_WRITE 1 %define SYS_EXIT 60 %define EXIT_SUCESS 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SECTIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .bss filename: resb 32 section .data usage_msg: db "Usage: ./pac <filename>", 10, 0 usage_msg_len: equ $-usage_msg section .text global _start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; PROGRAM ENTRY POINT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _start: pop rax ; pop argc into rax cmp rax, 2 ; make sure <filename> has been passed jl .not_enough_args jmp .enough_args .not_enough_args: call print_usage jmp .exit .enough_args: pop rax pop rax ; pop argv[1] into rax mov [filename], rax ; move argv[1] into filename ; print filename for testing mov rax, SYS_WRITE mov rdi, SYS_WRITE mov rsi, [filename] mov rdx, 32 syscall jmp .exit .exit: mov rax, SYS_EXIT mov rdi, EXIT_SUCESS syscall ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; CALLS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; print_usage: mov rax, SYS_WRITE mov rdi, SYS_WRITE mov rsi, usage_msg mov rdx, usage_msg_len syscall ret
程序运行输出
$ ./pac file.txt file.txtSHELL=/bin/bashSESSION
问题分析与修复
核心问题
- 固定长度输出导致垃圾数据:调用
sys_write时硬编码了rdx=32,但argv[1]是以空字节(\0)结尾的字符串,实际长度远小于32,所以会把内存中字符串后面的随机数据(包括bash环境变量)一起输出。 - 文件描述符参数语义错误:
mov rdi, SYS_WRITE虽然数值是1(stdout的文件描述符),但语义混淆,应该明确指向标准输出。 - 无用的内存存储:
mov [filename], rax完全没必要,argv[1]本身就是字符串的指针,直接使用即可,不需要额外存到bss段。
修复方案
添加计算字符串长度的函数,获取argv[1]的实际长度再传给sys_write;同时修正参数错误,去掉冗余代码。
修复后的完整代码
bits 64 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MACROS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %define SYS_WRITE 1 %define SYS_EXIT 60 %define EXIT_SUCCESS 0 %define STDOUT 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SECTIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .data usage_msg: db "Usage: ./pac <filename>", 10, 0 usage_msg_len: equ $-usage_msg newline: db 10 section .text global _start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; PROGRAM ENTRY POINT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _start: pop rax ; pop argc into rax cmp rax, 2 ; check if filename is provided jl .not_enough_args .enough_args: pop rax ; pop argv[0] (program name) pop rsi ; pop argv[1] pointer into rsi call strlen ; calculate length of argv[1], result in rax mov rdx, rax ; pass length to sys_write ; print the filename mov rax, SYS_WRITE mov rdi, STDOUT syscall ; print newline to match usual terminal output mov rax, SYS_WRITE mov rdi, STDOUT mov rsi, newline mov rdx, 1 syscall jmp .exit .not_enough_args: call print_usage jmp .exit .exit: mov rax, SYS_EXIT mov rdi, EXIT_SUCCESS syscall ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; CALLS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; strlen: calculate length of string pointed to by rsi, returns length in rax strlen: xor rax, rax ; initialize length counter to 0 .str_loop: cmp byte [rsi + rax], 0 ; check if current byte is null terminator je .str_done inc rax ; increment counter jmp .str_loop .str_done: ret print_usage: mov rax, SYS_WRITE mov rdi, STDOUT mov rsi, usage_msg mov rdx, usage_msg_len syscall ret
修复说明
strlen函数:遍历字符串直到遇到空字节,返回实际长度,确保sys_write只输出有效内容。- 修正文件描述符:用
STDOUT宏明确指定标准输出,代码可读性更强。 - 去掉冗余存储:直接使用
rsi存储argv[1]的指针,无需中转到bss段。 - 新增换行输出:让输出符合终端常规格式,可选保留。
现在运行程序,输出只会显示file.txt(带换行),不会附带多余内容。
内容的提问来源于stack exchange,提问作者joshjkk
相关产品推荐
相关产品推荐

