打印命令行参数 x86 程序集
Printing Commandline Arguments x86 Assembly
首先,我是汇编新手,但在 C++ 方面有不错的背景。我的问题源于我关注的关于 Commandline arguments using assembly.
的教程
当程序处于 运行 时,它会根据教程执行它应该执行的所有操作,即显示程序输入列表:
./asm1 arg1 arg2 arg3
问题在于您提供星号作为参数时:
./asm1 *
It effectively does a /usr/bin/ls on the CWD.
我的问题是如何防止这种情况,以及有关实施该计划的更好方法的任何建议。
Replaced:
; the loop
cmp ecx, eax ; if ecx not equal to eax
jne begin_for_loop ; jmp to loop, else exit
With:
; the loop
cmp ecx, eax ; if ecx not equal to eax
jmp begin_for_loop ; jmp to loop, else exit
And I found a bigger issue where the program prints ENV variables to the screen.
原程序如下:
; FOR LOOP: Print commandline arguments> an equivalent program to
this in assembly
SECTION .data
argv db "Arguments = %s",10,0
argc db "Argument Count = %d",10,0
SECTION .text
; allow access to printf
extern printf
; make main_function available externally
global main
main: ; int main (int argc, char* argv[])
push ebp
mov ebp,esp
sub esp, 10
mov eax, DWORD [ebp + 8] ; points to argc
mov ebx, DWORD [ebp + 12] ; points to argv
mov ecx, 0 ; mov ZERO to count register
begin_for_loop:
; always preserve values prior to external function calls
; external function calls may modify values you placed in registers
push ebx ; preserve ebx; holds argument address
push eax ; preserve eax; holds number of arguments
push ecx ; preserve ecx; holds the counter
; call printf
push DWORD [ebx]
push argv
call printf
add esp, 8 ; clean up the stack
; always restore in backwards order
pop ecx ; restore counter
pop eax ; restore number of arguments
pop ebx ; restore argument address
inc ecx ; increase our counter by 1
add ebx, 4 ; move to next argument in the array
; the loop
cmp ecx, eax ; if ecx not equal to eax
jne begin_for_loop ; jmp to loop, else exit
mov esp,ebp
pop ebp
ret
预期输出:
$ ./asm5 me you them us
Arguments = ./asm5
Arguments = me
Arguments = you
Arguments = them
Arguments = us
有问题的输出:
$ ./asm5 me you them us *
Arguments = ./asm5
Arguments = me
Arguments = you
Arguments = them
Arguments = us
Arguments = asm1
Arguments = asm1.asm
Arguments = asm1.o
Arguments = asm2
Arguments = asm2.asm
Arguments = asm3
Arguments = asm3.asm
Arguments = asm4
Arguments = asm4.asm
Arguments = asm5
Arguments = asm5.asm
Arguments = asm-template.asm
Arguments = compile-asm.sh
Arguments = cpp_libs
在 POSIX 系统上,如果您从 shell 启动程序,shell 将执行所谓的 globbing,扩展 *
并用匹配的文件替换它;结果将用作调用程序的参数。
你不能做任何事情来阻止它进入你的程序,你看到的参数确实是它从 shell 获得的参数(IOW,它们是已传递给 exec
的参数) .
如果您想在从 shell 启动程序时将文字 *
传递给您的程序,则必须引用它。
./asm5 me you them us "*"
当然 none 如果某些其他程序启动您的程序并将参数直接传递给 exec
,而没有 shell 妨碍,当然会发生这种情况。
Replaced:
; the loop
cmp ecx, eax ; if ecx not equal to eax
jne begin_for_loop ; jmp to loop, else exit
With:
; the loop
cmp ecx, eax ; if ecx not equal to eax
jmp begin_for_loop ; jmp to loop, else exit
And I found a bigger issue where the program prints ENV variables to the screen.
这是因为您忽略了终止 argv
参数列表的 NULL,而您正在继续阅读接下来的内容;在您的情况下,这恰好是环境内存块。
首先,我是汇编新手,但在 C++ 方面有不错的背景。我的问题源于我关注的关于 Commandline arguments using assembly.
的教程当程序处于 运行 时,它会根据教程执行它应该执行的所有操作,即显示程序输入列表:
./asm1 arg1 arg2 arg3
问题在于您提供星号作为参数时:
./asm1 *
It effectively does a /usr/bin/ls on the CWD.
我的问题是如何防止这种情况,以及有关实施该计划的更好方法的任何建议。
Replaced:
; the loop
cmp ecx, eax ; if ecx not equal to eax
jne begin_for_loop ; jmp to loop, else exit
With:
; the loop
cmp ecx, eax ; if ecx not equal to eax
jmp begin_for_loop ; jmp to loop, else exit
And I found a bigger issue where the program prints ENV variables to the screen.
原程序如下:
; FOR LOOP: Print commandline arguments> an equivalent program to
this in assembly
SECTION .data
argv db "Arguments = %s",10,0
argc db "Argument Count = %d",10,0
SECTION .text
; allow access to printf
extern printf
; make main_function available externally
global main
main: ; int main (int argc, char* argv[])
push ebp
mov ebp,esp
sub esp, 10
mov eax, DWORD [ebp + 8] ; points to argc
mov ebx, DWORD [ebp + 12] ; points to argv
mov ecx, 0 ; mov ZERO to count register
begin_for_loop:
; always preserve values prior to external function calls
; external function calls may modify values you placed in registers
push ebx ; preserve ebx; holds argument address
push eax ; preserve eax; holds number of arguments
push ecx ; preserve ecx; holds the counter
; call printf
push DWORD [ebx]
push argv
call printf
add esp, 8 ; clean up the stack
; always restore in backwards order
pop ecx ; restore counter
pop eax ; restore number of arguments
pop ebx ; restore argument address
inc ecx ; increase our counter by 1
add ebx, 4 ; move to next argument in the array
; the loop
cmp ecx, eax ; if ecx not equal to eax
jne begin_for_loop ; jmp to loop, else exit
mov esp,ebp
pop ebp
ret
预期输出:
$ ./asm5 me you them us
Arguments = ./asm5
Arguments = me
Arguments = you
Arguments = them
Arguments = us
有问题的输出:
$ ./asm5 me you them us *
Arguments = ./asm5
Arguments = me
Arguments = you
Arguments = them
Arguments = us
Arguments = asm1
Arguments = asm1.asm
Arguments = asm1.o
Arguments = asm2
Arguments = asm2.asm
Arguments = asm3
Arguments = asm3.asm
Arguments = asm4
Arguments = asm4.asm
Arguments = asm5
Arguments = asm5.asm
Arguments = asm-template.asm
Arguments = compile-asm.sh
Arguments = cpp_libs
在 POSIX 系统上,如果您从 shell 启动程序,shell 将执行所谓的 globbing,扩展 *
并用匹配的文件替换它;结果将用作调用程序的参数。
你不能做任何事情来阻止它进入你的程序,你看到的参数确实是它从 shell 获得的参数(IOW,它们是已传递给 exec
的参数) .
如果您想在从 shell 启动程序时将文字 *
传递给您的程序,则必须引用它。
./asm5 me you them us "*"
当然 none 如果某些其他程序启动您的程序并将参数直接传递给 exec
,而没有 shell 妨碍,当然会发生这种情况。
Replaced:
; the loop cmp ecx, eax ; if ecx not equal to eax jne begin_for_loop ; jmp to loop, else exit
With:
; the loop cmp ecx, eax ; if ecx not equal to eax jmp begin_for_loop ; jmp to loop, else exit
And I found a bigger issue where the program prints ENV variables to the screen.
这是因为您忽略了终止 argv
参数列表的 NULL,而您正在继续阅读接下来的内容;在您的情况下,这恰好是环境内存块。