来自Assembly的execve系统调用

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);

系统调用参数有问题吗?


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

(你可以通过使用strace运行你的可执行文件来看到这一点。)

有三个问题:

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

  • movl file_to_run, %edifile_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


  • 固定代码:

    .section .data
    file_to_run:
    .asciz       "/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, -0x8(%ebp)   
        movl $0, -0x4(%ebp)
    
        movl $11, %eax                      # sys_execve
        movl $file_to_run, %ebx              # file to execute       
        leal -8(%ebp), %ecx                 # command line parameters
        movl $0, %edx                       # environment block
        int  $0x80              
    
        leave
        ret
    

    实际上,您不需要在其他参数中加载任何内容。 如果你在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终端。

    链接地址: http://www.djcxy.com/p/80339.html

    上一篇: execve system call from Assembly

    下一篇: Recognizing stack frames in a stack using saved EBP values