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);
系统调用参数有问题吗?
答案 0 :(得分:10)
正在调用execve
系统调用 ,但您确实传递了错误的参数。
(您可以使用strace
运行可执行文件来查看此内容。)
有三个问题:
.ascii
不会终止字符串。 (你可能会很幸运,因为在这个例子的.data
部分中没有任何内容,但是不能保证......)添加0,或使用.asciz
(或.string
)而不是。
movl file_to_run, %edi
将{{1>}符号指向的值移动到file_to_run
,即字符串的前4个字节({{1} }})。字符串的地址只是符号本身的值,因此您需要使用%edi
前缀作为文字值:0x6e69622f
。同样,你需要说$
几行。 (这是AT& T语法和英特尔语法之间混淆的常见原因!)
参数以错误的顺序放置在堆栈中:movl $file_to_run, %edi
的地址低于movl $file_to_run, %ebx
。因此,命令字符串的地址应写入-0x8(%ebp)
,0应写入-0x4(%ebp)
,-0x8(%ebp)
指令应为-0x4(%ebp)
。
固定代码:
leal
答案 1 :(得分:1)
您实际上并不需要在其他参数中加载任何内容。如果您在x86中执行此操作,则以下更简单的代码也将起作用:
.global _main
.section .text
.data
file_to_run:
.asciz "/bin/sh"
.section .text
.globl main
_main:
pushl %ebp
movl %esp, %ebp
movl $11, %eax # sys_execve
movl $file_to_run, %ebx # file to execute
movl $0, %ecx # Null value will work too
movl $0, %edx # Null will works too
int $0x80
leave
ret
这将在调用系统调用后基本上打开一个shell终端。