asm_execve.s:
.section .data
file_to_run:
.ascii "/bin/sh"
.section .text
.globl main
main:
pushl %ebp
movl %esp, %ebp
subl $0x8, %esp # array of two pointers. array[0] = file_to_run array[1] = 0
movl file_to_run, %edi
movl %edi, -0x4(%ebp)
movl $0, -0x8(%ebp)
movl $11, %eax # sys_execve
movl file_to_run, %ebx # file to execute
leal -4(%ebp), %ecx # command line parameters
movl $0, %edx # environment block
int $0x80
leave
ret
生成文件:
NAME = asm_execve
$(NAME) : $(NAME).s
gcc -o $(NAME) $(NAME).s
程序已执行,但未调用sys_execve:
alex@alex32:~/project$ make
gcc -o asm_execve asm_execve.s
alex@alex32:~/project$ ./asm_execve
alex@alex32:~/project$
预期产出是:
alex@alex32:~/project$ ./asm_execve
$ exit
alex@alex32:~/project$
这个汇编程序应该像下面的C代码一样工作:
char *data[2];
data[0] = "/bin/sh";
data[1] = NULL;
execve(data[0], data, NULL);
系统调用参数有问题吗?
2 回答
正在调用
execve
系统调用,但您确实传递了错误的参数 .(您可以通过使用strace运行可执行文件来查看此内容 . )
有三个问题:
.ascii
不会终止字符串 . (你可能会很幸运,因为在这个例子的.data
部分中没有任何内容,但是不能保证...)添加0,或者使用.asciz
(或.string
)代替 .movl file_to_run, %edi
将file_to_run
符号指向的值移动到%edi
,即字符串的前4个字节(0x6e69622f
) . 字符串的地址只是符号本身的值,因此您需要使用$
前缀作为文字值:movl $file_to_run, %edi
. 同样,你需要说几行movl $file_to_run, %ebx
. (这是AT&T语法和Intel语法之间混淆的常见原因!)参数以错误的顺序放在堆栈中:
-0x8(%ebp)
是低于-0x4(%ebp)
的地址 . 因此,命令字符串的地址应写入-0x8(%ebp)
,0应写入-0x4(%ebp)
,leal
指令应为leal -8(%ebp), %ecx
.固定代码:
实际上你不需要在其他参数中加载任何东西 . 如果您在x86中执行此操作,则以下更简单的代码也将起作用:
这将在调用系统调用后基本上打开一个shell终端 .