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
运行你的可执行文件来看到这一点。)
有三个问题:
.ascii
不会0-终止字符串。 (你可能会很幸运,因为在这个例子中你的.data
节没有任何内容,但是不能保证…)添加一个0,或者使用.asciz
(或.string
)。
movl file_to_run, %edi
将file_to_run
符号指向的值移动到%edi
,即字符串的前4个字节( 0x6e69622f
)。 字符串的地址就是符号本身的值,所以你需要使用$
prefix作为字面值: 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终端。