来自Assembly的sys_execve系统调用

asm_execve.s:

 .section .data
 file_to_run:
 .ascii“/ bin / sh”

 .section .text
 .globl主

主要:
     pushl%ebp
     movl%esp,%ebp
     subl $ 0x8,%esp#两个指针的数组。 数组[0] = file_to_run数组[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#文件来执行       
     leal -4(%ebp),%ecx#命令行参数
     movl $ 0,%edx#环境块
     int $ 0x80              

    离开
     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 
亚历克斯@ alex32:〜/ $项目 

预期的产出是:

 alex @ alex32:〜/ project $ ./asm_execve 
 $ exit
亚历克斯@ alex32:〜/ $项目

这个大会程序应该像下面的C代码一样工作:

 char * data [2];
 data [0] =“/ bin / sh”; 
数据[1] = NULL;
 execve(data [0],data,NULL);

系统调用参数有问题吗?

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

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

有三个问题:

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

  2. movl file_to_run, %edifile_to_run符号指向的值移动到%edi ,即字符串的前4个字节( 0x6e69622f )。 字符串的地址就是符号本身的值,所以你需要使用$ prefix作为字面值: movl $file_to_run, %edi 。 同样的,你需要再说movl $file_to_run, %ebx几行。 (这是AT&T语法和Intel语法混淆的常见原因!)

  3. 参数以错误的顺序放置在堆栈上: -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终端。