来自Assembly的sys_execve系统调用

时间:2012-02-18 15:21:47

标签: linux assembly x86 system-calls

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 个答案:

答案 0 :(得分:10)

正在调用execve系统调用 ,但您确实传递了错误的参数。

(您可以使用strace运行可执行文件来查看此内容。)

有三个问题:

  1. .ascii不会终止字符串。 (你可能会很幸运,因为在这个例子的.data部分中没有任何内容,但是不能保证......)添加0,或使用.asciz(或.string )而不是。

  2. movl file_to_run, %edi将{{1>}符号指向的值移动到file_to_run,即字符串的前4个字节({{1} }})。字符串的地址只是符号本身的值,因此您需要使用%edi前缀作为文字值:0x6e69622f。同样,你需要说$几行。 (这是AT& T语法和英特尔语法之间混淆的常见原因!)

  3. 参数以错误的顺序放置在堆栈中:movl $file_to_run, %edi的地址低于movl $file_to_run, %ebx。因此,命令字符串的地址应写入-0x8(%ebp),0应写入-0x4(%ebp)-0x8(%ebp)指令应为-0x4(%ebp)

    < / LI>

    固定代码:

    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终端。